-2

So I'm learning C, and I would like to ask whether my statements are correct or not.

  1. Array names are converted to pointers except two cases: at the use of sizeof or & operators

  2. The array name is a pointer to the first element of the array, so for example

int array[10];
int* pointer = array; // int* pointer = &array[0]; is the same

Here are two arrays and some expressions (use as lvalue expressions). I'm interested the expressions return type is correct or not?

int B[2][3];

3.  &B[0] type is int (*)[3]
4.  &B type is int (*)[2][3]
5.  sizeof(B) here B type is int[2][3]
6.  B+1 type is int (*)[3]
7.  *(B+1) type is int[3] // 8. here th type int[3] and int* is not the same right?
8.  *(B+1) + 2 type is int*
9.  *(*B+1) type is int
10.  &(*B+1) type is int (**)[3]
11.  **B type is int

int c[3][2][5];

12.  &c[0] type is int (*)[2][5]
13.  *c type is int[2][5]
14.  *(*c+1) type is int[5]
15.  &*c type is int (*)[2][5]
16.  &**c type is int (*)[5]

I would really appreciate if you would correct if I'm wrong.

user2148758
  • 335
  • 1
  • 2
  • 10
  • What does a fully augmented (i.e. all warnings enabled) compiler say? – too honest for this site Feb 29 '16 at 21:13
  • I tried in C++ with typeid(), most of was correct, but I'm not sure because C and C++ are not the same. – user2148758 Feb 29 '16 at 21:17
  • Don't conclude from C++ to C or vice versa! My point still stands. Sorry, this is no tutorial site. – too honest for this site Feb 29 '16 at 21:19
  • "Don't conclude from C++ to C or vice versa! My point still stands." Yes, this is the reason why I'm asking, because I cant check these in C. – user2148758 Feb 29 '16 at 21:30
  • 1
    Possible duplicate of [C / C++ MultiDimensional Array Internals](http://stackoverflow.com/questions/7784758/c-c-multidimensional-array-internals) – Bo Persson Feb 29 '16 at 21:36
  • "So I'm learning C" - How without being able to compiler C code? First thing is to get a C compiler, then write the code and compile! – too honest for this site Feb 29 '16 at 21:54
  • @Olaf a C compiler doesn't tell you the type of arbitrary expressions – M.M Mar 01 '16 at 02:32
  • @M.M: I assume you know that I know. But that is not what I meant. You can simply try to assign to an object of the corresponding type and see if you get a warning or error. That's why I wrote "all wanings enabled". – too honest for this site Mar 01 '16 at 02:37
  • There's always implicit conversions to consider. Anyway there's no rule on here that questions cannot be posted if they are answerable by a compiler. In most cases the answer given by a compiler is incomplete, insufficiently general, or maybe even wrong. – M.M Mar 01 '16 at 02:43
  • Now thank you for all your comment. I tried what Olaf said: int B[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; int temp[3] = *(B + 1); With GCC --all-warnings it gives error: invalid initializer. Even with int A1[10]; int A2[10] = A1; is also the same. But works for example with int B[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; int* temp = *(B + 1) + 2; – user2148758 Mar 01 '16 at 19:19
  • About the &*E: int main() { int variable = 10; int* pointer; pointer = &variable; if( &*pointer == 10 ) printf( "true" ); return 0; } I see &*pointer is a int*, because it causes warning: comparison between pointer and integer. With if( &*pointer == NULL ) printf( "true" ); the warning message didnt appear. Anyway, I got answers to my questions, thank you. – user2148758 Mar 01 '16 at 19:25

1 Answers1

1

Points 1 and 2 would be better stated that when an expression consists of the name of the array, then the value of the expression is a pointer to the first element of the array (except for the handful of noted situations).

All of your points 3-14 are correct, except Point 10 is ill-formed. *B + 1 is not an lvalue so you cannot take the address of it.


Point 15 is slightly interesting. In the C11 standard, section 6.5.3.2/3 says:

The unary & operator yields the address of its operand. [...] If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.

At first sight this appears to specify that &*c should behave the same as c, i.e. have type int[3][2][5]. (C99 did not have this text).

On the other hand, one of the Constraints for the * operator is:

The operand of the unary * operator shall have pointer type.

Since the constraints "still apply", perhaps we should actually conclude that &*E is equivalent to the decayed-E and not the original E, when E has array type. This interpretation is also in line with 6.3.2.1/3 which specifies the array-pointer conversion. Perhaps it would have been clearer if 6.5.3.2/3 explicitly mentioned that value conversion is applied to E for the expression &*E.

M.M
  • 138,810
  • 21
  • 208
  • 365