关于结构体内存的分配与赋值

最近项目中使用了很多结构体,其中有如下关于结构体的赋值问题:

设结构体 A , B

且,A与B均为同类型的结构体.

 

现假设要想将 B的值给A,

 

至于是否可以像 A = B这样去赋值,就像普通的变量一样使用 

 

查了很多资料,包括谭浩强的教材,几乎都是清一色的说不能这样去赋值,赋值不成功。

 

但是这两天,在具体的编译器上这样去用的时候,却是可以的,和用memcpy一样的效果。

 

刚开始怀疑书上是否有错,后来查了许多资料,原来,只是C语言的版本不同而已,因此,哪怕同一

 

类编译器只要,可能版本的不一样,也可能导致有的程序能编译,有的不能编译。

 

下面,是从维基上摘录的信息,一般新的编译器应该支持最新版本的编译器,所以在用编译器的时候

 

要注意一下编译器的C语言版本。

 

早期發展

C語言最早是由丹尼斯·里奇為了在PDP-11電腦上運行的UNIX系統所設計出來的程式語言,第一次發展在1969年到1973年之間。之所以被稱為“C”是因為C語言的很多特性是由一種更早的被稱為B語言的程式語言中發展而來。早期作業系統的核心大多由組合語言組成,隨著C語言的發展,C語言已經可以用來編寫作業系統的核心。1973年Unix作業系統核心正式用C語言改寫,這是C語言第一次應用在作業系統的核心編寫上。

[编辑]K&R C

1978年,丹尼斯·里奇(Dennis Ritchie)和布萊恩·柯林漢(Brian Kernighan)合作出版了《C程序设计语言》的第一版。書中介紹的C語言標準也被C語言程式設計師稱作“K&R C”,第二版的書中也包含了一些ANSI C的標準。K&R C主要介绍了以下特色:

  • 结构(struct)类型

  • 长整数(long int)类型

  • 无符号整数(unsigned int)类型

  • 把运算符=+和=-改为+=和-=。因为=+和=-會使得編譯器不知道使用者要處理i = -10還是i =- 10,使得處理上產生混淆。

即使在後來ANSI C標準被提出的許多年後,K&R C仍然是許多編譯器的最低標準要求,許多老舊的編譯仍然運行K&R C的標準。

 

ANSI C 和 ISO C

主条目:ANSI C

1989年,C语言被 ANSI 标准化(ANSI X3.159-1989)。标准化的一个目的是扩展K&R C。这个标准包括了一些新特性。在K&R出版後,一些新特性被非官方地加到C语言中。

  • void函数

  • 函数返回 struct或 union类型

  • void *数据类型

在ANSI标准化自己的过程中,一些新的特性被加了进去。ANSI也规定了一套标准函数库。ANSI ISO国际标准化组织)成立 ISO/IEC JTC1/SC22/WG14 工作组,来规定国际标准的C语言。通过对ANSI标准的少量修改,最终通过了 ISO 9899:1990。随后,ISO标准被 ANSI 采纳。

传统C语言到ANSI/ISO标准C语言的改进包括:

  • 增加了真正的标准库

  • 新的预处理命令与特性

  • 函数原型允许在函数申明中指定参数类型

  • 一些新的关键字,包括 const、volatile与 signed

  • 宽字符、宽字符串与字节多字符

  • 对约定规则、声明和类型检查的许多小改动与澄清

WG14工作小组之後又於1994年,对1985年颁布的标准做了两处技术修订(缺陷修复)和一个补充(扩展)。下面是 1994 年做出的所有修改:

  • 3 个新的标准库头文件 iso646.h、wctype.h 和 wchar.h

  • 几个新的记号与预定义宏,用于对国际化提供更好的支持

  • printf/sprintf 函数一系列新的格式代码

  • 大量的函数和一些类型常量,用于多字节字符宽字节字符

 

C99

在ANSI的标准确立後,C语言的规范在一段时间内没有大的变动,然而C++在自己的标准化建立过程中继续发展壮大。《标准修正案一》在1994年为C语言建立了一个新标准,但是只修正了一些C89标准中的细节和增加更多更广的国际字符集支持。不过,这个标准引出了1999年ISO 9899:1999的发表。它通常被称为C99。C99被ANSI于2000年3月采用。

在C99中包括的特性有:

  • 增加了对编译器的限制,比如源程序每行要求至少支持到 4095 字节,变量名函数名的要求支持到 63 字节(extern 要求支持到 31)。

  • 增强了预处理功能。例如: 

    巨集支持取可变参数 #define Macro(...) __VA_ARGS__

    使用巨集的时候,允许省略参数,被省略的参数会被扩展成空串。

    支持 // 开头的单行注释(这个特性实际上在C89的很多编译器上已经被支持了)

  • 增加了新关键字 restrict, inline, _Complex, _Imaginary, _Bool 

    支持 long long, long double _Complex, float _Complex等类型

  • 支持不定长的数组,即数组长度可以在运行时决定,比如利用变量作为数组长度。声明时使用 int a[var]的形式。不过考虑到效率和实现,不定长数组不能用在全局,或 struct与 union里。

  • 变量声明不必放在语句块的开头,for 语句提倡写成 for(int i=0;i<100;++i)的形式,即i只在 for语句块内部有效。

  • 允许采用(type_name){xx,xx,xx}类似于 C++ 的构造函数的形式构造匿名的结构体。

  • 初始化结构的时候允许对特定的元素赋值,形式为: 

    structtest{inta[3],b;}foo[]= {[0].a={1},[1].a=2};
    structtest{inta,b,c,d;}foo = {.a=1,.c=3,4,.b=5} // 3,4 是对 .c,.d 赋值的
  • 格式化字符串中,利用 \u支持 unicode 的字符。

  • 支持 16 进制的浮点数的描述。

  • printf scanf 的格式化串增加了对 long long int类型的支持。

  • 浮点数的内部数据描述支持了新标准,可以使用 #pragma 编译器指令指定。

  • 除了已有的 __line__ __file__以外,增加了 __func__得到当前的函数名。

  • 允许编译器化简非常数的表达式。

  • 修改了 / %处理负数时的定义,这样可以给出明确的结果,例如在C89中-22 / 7 = -3, -22 % 7 = -1,也可以-22 / 7= -4, -22 % 7 = 6。 而C99中明确为 -22 / 7 = -3, -22 % 7 = -1,只有一种结果。

  • 取消了函数返回类型默认为 int的规定。

  • 允许 struct定义的最后一个数组不指定其长度,写做 [](flexible array member)。

  • const const int i将被当作 const int i处理。

  • 增加和修改了一些标准头文件,比如定义 bool 的 <stdbool.h> ,定义一些标准长度的 int 的 <inttypes.h> ,定义复数的 <complex.h> ,定义宽字符的 <wctype.h> ,类似于泛型的数学函数 <tgmath.h>, 浮点数相关的 <fenv.h>。 在<stdarg.h> 增加了 va_copy 用于复制 ... 的参数。<time.h> 里增加了 struct tmx ,对 struct tm 做了扩展。

  • 输入输出对宽字符以及长整数等做了相应的支持。

但是各个公司对C99的支持所表现出来的兴趣不同。当GCC和其它一些商业编译器支持C99的大部分特性的时候[1]微软Borland却似乎对此不感兴趣。

 

C11

2011年12月8日,ISO正式发布了新的C语言的新标准C11,之前被称为C1X,官方名称为ISO/IEC 9899:2011。

新的标准提高了对C++的兼容性,并增加了一些新的特性。这些新特性包括:

  • 对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符, aligned_alloc函数以及<stdalign.h>头文件

  • _Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。

  • _Generic 关键字。

  • 多线程(Multithreading)支持,包括:_Thread_local存储类型标识符,<threads.h>头文件,里面包含了线程的创建和管理函数。

  • 增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>.

  • 删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。

  • 增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。

  • 增加了更多浮点处理宏。

  • 匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。

  • 静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。

  • 新的 fopen() 模式,(“…x”)。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。

  • 新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。

  • _Atomic类型修饰符和<stdatomic.h>头文件。

posted on 2012-09-17 12:05  竞击  阅读(625)  评论(0编辑  收藏  举报