关于结构体内存的分配与赋值
最近项目中使用了很多结构体,其中有如下关于结构体的赋值问题:
设结构体 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
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>头文件。