欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mr.J--C99标准之数组问题

程序员文章站 2022-04-29 09:00:09
...

 

Mr.J--C99标准之数组问题

C99标准,1999年12月1日,国际标准化组织(ISO)和国际电工委员会(IEC)旗下的C语言标准委员会(ISO/IEC JTC1/SC22/WG14)正式发布了这个标准文件 。其主要内容为:

    对编译器限制增加了,比如源程序每行要求至少支持到 4095 字节,变量名与函数名的要求支持到 63 字节 (extern 要求支持到 31)。
预编译处理增强了。例如:
支持了可变参数的宏(Variadic Macro): #define Macro(...) __VA_ARGS__
使用宏的时候,参数如果不写,宏里用 #,## 这样的东西会扩展成空串。(C89标准中会出错的)
支持 // 行注释(这个特性实际上在C89的很多编译器上已经被支持了)
增加了新关键字 restrict,inline,_Complex,_Imaginary,_Bool
支持 long long,long double _Complex,float _Complex 这样的类型
支持 <: :> <% %> %: %:%: ,等等奇怪的符号替代,D&E 里提过这个支持了不定长的数组。数组的长度就可以用变量了。声明类型的时候呢,就用 int a[*] 这样的写法。不过考虑到效率和实现,这玩意并不是一个新类型。所以就不能用在全局里,或者 struct union 里面,如果你用了这样的东西,goto 语句就受限制了。
变量声明不必放在语句块的开头,for 语句提倡这么写 for(int i=0;i<100;++i) 就是说,int i 的声明放在里面,i 只在 for 里面有效。(VC6.0没有遵守这条标准,i 在 for 外也有效;但vc2005里已经默认是i在外面不可见了,但有编译选项可以设置。)
复合字面量:当一个类似结构的东西需要临时构造的时候,可以用 (type_name){xx,xx,xx} 这有点像 C++ 的构造函数
相较于C89标准,C99标准新增了一种结构体/数组的初始化方式,名叫designated initializers [8]  ,即:
struct { int a[3], b; } w[] ={ [0].a = {1}, [1].a[0] = 2 }; [9] 
字符串里面,\u 支持 unicode 的字符
支持 16 进制的浮点数的描述
所以 printf和scanf 的格式化串增加了支持 "%lld"和"%llu",对应long long int类型和unsigned long long int类型(可以分别简写为long long和unsigned long long)。
浮点数的内部数据描述支持了新标准,这个可以用 #pragma 编译器指定
增加了一个内置的局部静态字符数组变量 __func__ ,可以用于得到当前函数的函数名 [10]  。
对于非常量的表达式,也允许编译器做化简
修改了 /% 处理负数时的定义,这样可以给出明确的结果,例如在C89中-22 / 7 = -3, -22% 7 = -1,也可 以-22 / 7= -4, -22% 7 = 6。 而C99中明确为 -22 / 7 = -3, -22% 7 = -1,只有一种结果。
取消了不写函数返回类型默认就是 int 的规定
允许 struct 定义的最后一个数组写做 [] 不指定其长度描述
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 做了扩展
输入输出对宽字符还有长整数等做了相应的支持
long double_Complex;long double_Imaginary。
<complex.h>头文件中定义了complex和imaginary宏,并将它们扩展为_Complex和_Imaginary,因此在编写新的应用程序时,应该使用<stdbool.h>头文件中的complex和imaginary宏。
C99标准中引进了long long int(-263至263 - 1)和unsigned long long int(0到264 - 1)。long long int能够支持的整数长度为64位。

在这里,我主要先说我上面红字标注的问题(我在今天重拾C Primer Plus遇到的问题):

#include<stdio.h>
#define MONTHS 12 
int main(){
		int days[MONTHS] = {31,28,[4]=31,30,31,[1]=29};
		int i;
		
		for(i=0;i<MONTHS;i++)
		printf("%2d %d\n",i+1,days[i]);
		return 0; 
} 

 

这个程序在C99标准下是可以运行的:Mr.J--C99标准之数组问题

 

  从输出结果可以看出指定初始化项目有两个重要特性。第一,  如果在一一个指定初始化项目后跟有不止一个值,例如在序列[4]=31,30,31 中这样,则这些数值将用来对后续的数组元素初始化。也就是说,  把31赋给days[4]之后,接着把30和31分别赋给days[5]和days[6]。第二,如果多次对一个元素进行初始化,则最后的一次有效。例如,前面把days[1]初始化为28,而后面的指定初始化[1]=29覆盖了前面的数值,于是days[1]的数值最终为29。

但是对于现在的C语言标准C11,这个是行不通的,我在编译之后运行,出来的结果是这样的:Mr.J--C99标准之数组问题       

这就让人非常头大。

Mr.J--C99标准之数组问题

我查询相关资料发现:① C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。sizeof返回的这
种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。② C99中,程序员声明数组时,数组的维数可以由任一有效的整型表达式确定,包括只在运行时才能确定其值的表达式,这类数组就叫做可变长数组、但是只有局部数组才可以是变长的。可变长数组的维数在数组生存期内是不变的,也就是说,可变长数组不是动态的。可以变化的只是数组的大小。可以使用*来定义不确定长的可变长数组。

Mr.J--C99标准之数组问题

在学某语言之前,请先了解一下它的标准。(It's important for youself.)刚学C语言的同学可以看看这个:请点击链接查看

相关标签: bi'a bian