我有一个看起来像这样的结构:
typedef struct foo {
int this;
int that;
int length;
int info[]; // legal for last element of a struct
} Foo;
当我编译它时,我收到这样的警告:
C4200 nonstandard extension used: zero-sized array in struct/union
我是否只接受警告,或者是否有一些我可以设置的属性告诉Visual Studio使用C-99?
答案 0 :(得分:2)
Visual Studio 2015 [几乎]完全实现了C99,但仍然将所有C99功能视为语言扩展(例如,禁用语言扩展也会禁用C99支持)。其中一些功能会触发您观察到的虚假警告。
只要C99支持仍处于此半官方“扩展”状态,只需忽略/禁用此类警告。
请注意,VS2015 Update 3不再针对此类C代码发出此警告。
答案 1 :(得分:1)
对于那些对零长度数组或“灵活数组”成语感到好奇的人,可能需要花一点时间来解释它们。这个成语和C本身一样古老。
假设您想传递一个由标题和可变数据量组成的结构。直到为结构分配了需要添加多少数据才知道它。
最初的习语是宣布这样的结构:
/* Variation 1 */
struct mydata {
int type;
int datalen;
char data[1];
};
然后假设我们想要返回其中一个对象:
struct mydata *
get_some_data()
{
int len;
struct mydata *rval;
len = find_out_how_much_data();
/* Allocate the struct AND enough extra space to hold the data */
rval = malloc(sizeof(*rval) + len - 1);
rval->datalen = len;
read_data(&rval->data[0], len);
return rval;
}
调用者可以像这样访问它:
void caller()
{
struct mydata *foo = get_some_data();
/* Start accessing foo->datalen bytes of data starting at
* foo->data[0]
*/
free(foo); /* And free it all */
}
这个成语的要点是char data[1]
声明是谎言,因为数据肯定会比这长,但C编译器不进行范围检查,所以一切都很酷。
但请注意malloc中的len - 1
表达式。这是必要的,因为将数据声明为长度为1会在所有内容中引入一个错误,并邀请编码人员犯错误。
因此,GNU和Microsoft都添加了一种语言扩展,允许您声明一个长度为零的数组:
/* Variation 2 */
struct mydata {
int type;
int datalen;
char data[0];
};
虽然表面上看,这是荒谬的,但它与这里使用的成语完全吻合。现在我们可以做到:
rval = malloc(sizeof(*rval) + len);
并且代码更清晰。
C99通过承认数组的长度是谎言来形式化这个成语,但是在结构的末尾有额外数据的能力非常方便。所以现在你声明:
/* Variation C99 */
struct mydata {
int type;
int datalen;
char data[];
};
并且所有内容都与Gnu / Microsoft扩展名完全相同。
不幸的是,似乎微软没有在他们的编译器中采用C99标准,因此无论你做什么,变体2和C99都会产生警告。看起来我唯一的选择是使用警告消息或添加pragma来抑制它。
Linux用户可以通过执行gr -r '\[0\]' /usr/include
并查看许多位置如何使用零长度数组来娱乐自己。这是一种非常常用的习语。
关于我自己的问题:我正在使用的结构实际上是ioctl的一部分。驱动程序已经编写,我无法更改它。我能做的最多就是将数组从零长度重新定义为灵活。不幸的是,这两个选项都没有让MSVC编译器满意。
答案 2 :(得分:0)
当你创建一个未定义长度的数组(在你的情况下是一个结构)时,不知道需要为它分配多少内存。使用变量' info'因此,不知道程序正在写入或读取的计算机的高速缓冲存储器中的何处。这可能会导致程序崩溃。通常,当您要使用未定义长度的数组时,将使用指针。当知道数组应该有多大时,可以为该指针分配内存。
编译器警告您我上面描述的问题,但允许您执行代码(至少在Microsoft Visual Studio 2013中执行)。
希望这能帮到你!