C99中最有用的新function是什么?
C99已经有十多年了,但是对它的支持一直很慢,所以大多数开发者都坚持使用C89。 即使在今天,当我遇到C代码中的C99特性时,我也有些惊讶。
现在大多数主要的编译器都支持C99(MSVC是一个明显的例外,而且一些embedded式编译器也落后了),我觉得和C一起工作的开发人员应该知道C99可用的function。 其中一些特性是从未标准化过的常用特性(例如snprintf
),或者从C ++(灵活的variables声明放置或单行//
注释)中熟悉,但是一些新特性首先在C99和许多程序员都不熟悉。
你觉得C99中最有用的新function是什么?
作为参考, C99标准 (标记为草稿,但与更新的标准相同,据我所知), 新function列表和GCC C99实施状态 。
每个答案的一个function,请; 随时留下多个答案。 鼓励演示新function的简短代码示例。
我很习惯打字
for (int i = 0; i < n; ++i) { ... }
在C ++中,我不得不说,使用非C99编译器是一件痛苦的事情
int i; for (i = 0; i < n; ++i ) { ... }
stdint.h
,它定义了int8_t
, uint8_t
等等。不需要对整数的宽度做出不可移植的假设。
uint32_t truth = 0xDECAFBAD;
我认为新的初始化机制是非常重要的。
struct { int x, y; } a[10] = { [3] = { .y = 12, .x = 1 } };
好 – 不是一个引人注目的例子,但是符号是准确的。 您可以初始化数组的特定元素以及结构的特定成员。
也许一个更好的例子是这样的 – 虽然我承认这并不是非常有吸引力:
enum { Iron = 26, Aluminium = 13, Beryllium = 4, ... }; const char *element_names[] = { [Iron] = "Iron", [Aluminium] = "Aluminium", [Beryllium] = "Beryllium", ... };
支持以//
开头的单行注释。
可变长度数组:
int x; scanf("%d", &x); int a[x]; for (int i = 0; i < x; ++i) a[i] = i * i; for (int i = 0; i < x; ++i) printf("%d\n", a[i]);
能够在块的开始以外的位置声明variables。
可变macros。 使用无限数量的参数生成样板代码变得更容易。
snprintf()
– 严重的是,能够安全地格式化string是值得的。
灵活的arrays成员。
6.7.2.1结构和联合规范
作为特殊情况,具有多个名称成员的结构的最后一个元素可能具有不完整的数组types; 这被称为灵活的数组成员 。 除了两个例外,灵活的数组成员被忽略。 首先,结构的大小应该等于另一个相同结构的最后一个元素的偏移量,用一个未指定长度的数组代替灵活的数组成员
.
(或->
)运算符的左操作数是指向具有灵活数组成员的结构的指针,右操作数指定该成员,它的行为就好像该成员被replace为最长的数组(具有相同的元素types)不会使结构大于被访问的对象; arrays的偏移量应保持为灵活arrays成员的偏移量,即使这与arraysreplacearrays不同。 如果这个数组没有元素,就像它有一个元素一样,但是行为是不确定的,如果试图访问那个元素或者生成一个超过它的指针。
例:
typedef struct { int len; char buf[]; } buffer; int bufsize = 100; buffer *b = malloc(sizeof(buffer) + sizeof(int[bufsize]));
复合文字。 逐个设置结构是'89;)
您也可以使用它们来获取指向具有自动存储持续时间的对象的指针,而不会声明不必要的variables,例如
foo(&(int){ 4 });
insteand的用法和样例:
int tmp = 4; foo(&tmp);
布尔types。
你现在可以做这样的事情:
bool v = 5; printf("v=%u\n", v);
将打印
1
支持inline
函数。
复合文字,已经提到,但这里是我引人注目的例子:
struct A *a = malloc(sizeof(*a)); *a = (struct A){0}; /* full zero-initialization */ /* or */ *a = (struct A){.bufsiz=1024, .fd=2}; /* rest are zero-initialized. */
即使它在堆上,也是一种清楚的方式来初始化数据。 没有办法忘记零初始化的东西。
restrict
关键字。 特别是当你紧缩数字…
Unicode转义序列支持:
printf("It's all \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC to me.\n");
甚至,字面Unicode字符:
printf("日本語\n");
(注意:根据您的语言环境可能无法正常工作;对不同编码的便携式支持将需要更多的工作)
hex浮点常量( 0x1.8p0f
)和转换说明符( %a
, %A
)。 如果您经常处理低级别的数字细节,这是对十进制文字和转换的巨大改进。
在为algorithm指定常量时,它们避免了四舍五入的担忧,对于debugging低级浮点代码非常有用。
就我个人而言,我喜欢IEC 60559:1989 (微处理器系统的二进制浮点algorithm)和更好的浮点支持。
以类似的方式,设置和查询浮点舍入模式,检查Nan / Infinity /低于正常的数字等是非常有用的。