Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
506 views
in Technique[技术] by (71.8m points)

c - Equivalence of p[0] and *p for incomplete array types

Consider the following code (it came about as a result of this discussion):

#include <stdio.h>

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

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

GCC 4.3.4 complains with the error message:

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

Same error message in GCC 4.1.2, and seems to be invariant of -std=c99, -Wall, -Wextra.

So it's unhappy with the expression p[0], but it's happy with *p, even though these should (in theory) be equivalent. If I comment out line 5, the code compiles and does what I would "expect" (displays 6).

Presumably one of the following is true:

  1. My understanding of the C standard(s) is incorrect, and these expressions aren't equivalent.
  2. GCC has a bug.

I'd place my money on (1).

Question: Can anyone elaborate on this behaviour?

Clarification: I'm aware that this can be "solved" by specifying an array size in the function definition. That's not what I'm interested in.


For "bonus" points: Can anyone confirm that MSVC 2010 is in error when it rejects line 10 with the following message?

1><snip>prog.c(10): warning C4048: different array subscripts : 'int (*)[]' and 'int (*)[3]'
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Section 6.5.2.1 of n1570, Array subscripting:

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’’.

So the standard forbids the expression p[0] if p is a pointer to an incomplete type. There is no such restriction for the indirection operator *.

In older versions/drafts of the standard, however, (n1256 and C99), the word "complete" is absent in that paragraph. Not being involved in any way in the standard procedure, I can only guess whether it's a breaking change or the correction of an omission. The behaviour of the compiler suggests the latter. That is reinforced by the fact that p[i] is per the standard identical to *(p + i) and the latter expression doesn't make sense for a pointer to an incomplete type, so for p[0] to work if p is a pointer to an incomplete type, an explicit special case would be needed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...