c - 不完整数组类型的 p[0] 和 *p 等价

标签 c arrays pointers gcc incomplete-type

考虑以下代码(它是 this discussion 的结果):

#include <stdio.h>

void foo(int (*p)[]) {          // Argument has incomplete array type
    printf("%d\n", (*p)[1]);
    printf("%d\n", p[0][1]);    // Line 5
}

int main(void) {
    int a[] = { 5, 6, 7 };
    foo(&a);                    // Line 10
}

海湾合作委员会 4.3.4 complains错误信息:

prog.c: In function ‘foo’:
prog.c:5: error: invalid use of array with unspecified bounds

GCC 4.1.2 中的相同错误消息,并且似乎是 -std=c99-Wall-Wextra 的不变量。

所以它对表达式 p[0] 不满意,但它对 *p 很满意,即使它们(理论上)应该是等价的。如果我注释掉第 5 行,代码将编译并执行我“预期”的操作(显示 6)。

推测以下情况之一为真:

  1. 我对 C 标准的理解不正确,这些表达式是等价的。
  2. GCC 有一个错误。

我会把钱放在 (1) 上。

问题:任何人都可以详细说明这种行为吗?

说明:我知道这可以通过在函数定义中指定数组大小来“解决”。这不是我感兴趣的。


对于“奖励”点:当 MSVC 2010 拒绝第 10 行并显示以下消息时,任何人都可以确认 MSVC 2010 是错误的吗?

1><snip>\prog.c(10): warning C4048: different array subscripts : 'int (*)[]' and 'int (*)[3]'

最佳答案

n1570 的第 6.5.2.1 节,数组下标:

Constraints

One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.

因此,如果 p 是指向不完整类型的指针,则标准禁止表达式 p[0]。对于间接运算符*则没有这样的限制。

然而,在旧版本/标准草案(n1256 和 C99)中,该段中没有“完整”一词。没有以任何方式参与标准程序,我只能猜测这是一个重大变化还是对遗漏的更正。编译器的行为表明后者。 p[i] 符合与 *(p + i) 相同的标准,并且后一个表达式对于指向的指针没有意义一个不完整的类型,所以如果 p 是一个指向不完整类型的指针,那么要让 p[0] 工作,就需要一个显式的特殊情况。

关于c - 不完整数组类型的 p[0] 和 *p 等价,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10183943/

相关文章:

c++ - 一种实用的循环展开技术

c - gdb 在使用 math.h 函数时给出奇怪的输出

android - 将字符串数组转换为整数数组

java - NullPointerException 错误,将 string[] 转换为 int[]

c - 打印语句更改字符数组输出

c++ - 如果构造函数抛出异常,如何删除对象?

c++ - 常量指针 C++ 和优化,它们更快吗?

c - 在包含字符串的 typedef 结构中使用指针

C 标准 - 函数定义是函数原型(prototype)吗?

c - 设置整数指针数组