ISO C各版本中,非静态零大小数组函数形参是否合法?
函数形参中的零大小数组在ISO C中是否合法?
依据ISO C任意版本的规定,指定零大小数组作为函数形参是否合法?标准定义看似模糊:虽然零大小数组本身无效,但函数的数组形参存在特殊性。
C23::6.7.6.3/6条款:
将形参声明为“type数组”时,应调整为“指向type的限定指针”,其中类型限定符(若有)是数组类型推导的[和]中指定的限定符。若数组类型推导的[和]中还出现static关键字,则函数每次调用时,对应实参的值必须能访问到一个数组的首元素,该数组的元素数至少不小于大小表达式指定的数量。
按照对该条款的理解,只要不使用static关键字,[]中指定的大小会被实际忽略,编译器不能对指针做出任何假设。那以下代码应该符合标准,对吗?
void h(char *start, char past_end[0]); #define size 100 void j(void) { char dst[size]; h(dst, dst+size); }
我用past_end[0]作为指向末尾后一位的标记指针(而非传递大小,某些场景下更便捷)。[0]能明确表示这是末尾后一位,而非实际末尾,避免读者将其与普通指针混淆(实际末尾会用end[1]标记)。
但GCC认为该代码不符合标准:
$ gcc -Wall -Wextra -Wpedantic -pedantic-errors -std=c17 -S ap.c ap.c:1:26: error: ISO C forbids zero-size array ‘past_end’ [-Wpedantic] 1 | void h(char *start, char past_end[0]); | ^~~
Clang也持相同观点:
$ clang -Wall -Wextra -Wpedantic -pedantic-errors -std=c17 -S ap.c ap.c:1:30: warning: zero size arrays are an extension [-Wzero-length-array] void h(char *start, char past_end[0]); ^ 1 warning generated.
若不启用严格ISO C模式,GCC仍会给出不同的警告,而Clang则无警告:
$ cc -Wall -Wextra -S ap.c ap.c: In function ‘j’: ap.c:7:9: warning: ‘h’ accessing 1 byte in a region of size 0 [-Wstringop-overflow=] 7 | h(dst, dst+size); | ^~~~~~~~~~~~~~~~ ap.c:7:9: note: referencing argument 2 of type ‘char[0]’ ap.c:1:6: note: in a call to function ‘h’ 1 | void h(char *start, char past_end[0]); | ^ ap.c:7:9: warning: ‘h’ accessing 1 byte in a region of size 0 [-Wstringop-overflow=] 7 | h(dst, dst+size); | ^~~~~~~~~~~~~~~~ ap.c:7:9: note: referencing argument 2 of type ‘char[0]’ ap.c:1:6: note: in a call to function ‘h’ 1 | void h(char *start, char past_end[0]); | ^
$ clang -Wall -Wextra -S ap.c
我已向GCC反馈该问题,但各方存在分歧。
后续疑问
- 函数的零大小数组形参是否需要遵循与普通数组相同的要求?
- 若上述结论成立,以下代码的合法性该如何判定?
在严格ISO C模式下,编译器是否有权仅因使用数组语法(未使用void f(size_t sz, char arr[sz]);static)就假设数组至少包含一个元素?若如此,这是否属于语言的退化?
内容的提问来源于stack exchange,提问作者alx - recommends codidact
相关产品推荐
相关产品推荐

