解释'空'C数组(int a = {};)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解释'空'C数组(int a = {};)相关的知识,希望对你有一定的参考价值。
我有一段代码片段定义(我相信)一个空数组,即一个不包含元素的数组:
int a[] = {};
我用gcc编译了代码片段没有问题
试图在MSVS下编译相同代码的同事进行了修改:
int* a = NULL;
不,他显然认为这是MSVS编译器可接受的等效状态。
但是,稍后在代码中我检索否。使用以下宏的数组中的元素:
#define sizearray(a) (sizeof(a) / sizeof((a)[0]))
这样做的时候:
sizearray({}) returns 0
这就像我所期望的那样,我认为是一个空数组的定义
sizearray(NULL) returns 1
我认为sizeof(NULL)/sizeof((NULL)[0]))
实际上是4/4 == 1
作为NULL == (void*)0
我的问题是:
int a[] = {};
是一种表达空数组的有效方法,或者它的编程实践是否糟糕。
此外,您是否可以在MSVS编译器中使用这样的表达式,即这是某种C99兼容性问题?
更新:
刚刚汇编了这个:
#include <stdio.h>
#define sizearray(a) (sizeof(a) / sizeof((a)[0]))
int main()
{
int a[] = {};
int b[] = {0};
int c[] = {0,1};
printf("sizearray a = %lu
", sizearray(a));
printf("sizearray b = %lu
", sizearray(b));
printf("sizearray c = %lu
", sizearray(c));
return 0;
}
使用这个Makefile:
array: array.c
gcc -g -o array array.c
我的编译器是:
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
编译没有任何投诉,输出看起来像这样:
bph@marvin:~/projects/scratch/c/array$ ./array
sizearray a = 0
sizearray b = 1
sizearray c = 2
非常好奇?它可以秘密地成为C ++编译器,而不是C编译器吗?
尝试了John Bodes关于其他编译器标志的建议,并且可以确认编译确实失败了:
gcc --std=c11 --pedantic -Wall -g -o array array.c
array.c: In function ‘main’:
array.c:7:15: warning: ISO C forbids empty initializer braces [-Wpedantic]
int a[] = {};
^
array.c:7:9: error: zero or negative size array ‘a’
int a[] = {};
^
Makefile:2: recipe for target 'array' failed
make: *** [array] Error 1
C中的空初始值设定项无效
int a = {};
是不正确的。见6.7.9 Initialization。
sizearray(NULL)
也无效。因为sizearray
宏将扩展到:
sizeof 0 /sizeof 0[0])
如果NULL
被定义为0
。这是无效的,因为0[0]
无效,因为没有涉及指针或数组(根据指针算法的要求 - 记住a[b]
相当于*(a + b)
)。
或者,它会扩展到:
(sizeof(((void *)0)) / sizeof((((void *)0))[0]))
如果NULL
是((void*)0)
。这是无效的,因为void指针上不允许指针运算。请参阅6.5.6, 2和void*
是一个不完整的类型。无论NULL
的定义在实现中是什么都存在类似的问题(C标准对空指针常量的定义是灵活的,即NULL
。参见7.19, 3)。
因此,在这两种情况下,您看到的是非标准代码的编译器特定行为。
这不是一个数组,但它也不是一个标量:它是一个语法错误。
C11草案在§6.7.9.11(初始化语义)中说:
标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式的初始值(转换后);与简单赋值相同的类型约束和转换适用,将标量的类型作为其声明类型的非限定版本。
但是大括号之间必须有一些东西,它不能是空的。
所以我认为问题是缺少某些东西,这不是实际的代码。
它不是数组,它是大括号初始化语法。
简而言之,你可以这样写:
int a = {1234};
它没有用数组初始化a
,它只分配1234.如果有2个或更多值,那就是错误。
Brace初始化禁用值截断,因此:
char b = 258; // Valid, same as b = 2
char b = {258}; // Wrong, can't truncate value in braces
空括号只是零初始化器,因此int a = {}
相当于int a = {0}
以上是关于解释'空'C数组(int a = {};)的主要内容,如果未能解决你的问题,请参考以下文章
PYTHON,Midpoint方法,TypeError:'float'对象不能解释为整数
C语言 字符数组在定义时实际长度能不能等于有效长度 不给\0留空间