char* xyz vs. char xyz[] -- same?

Are these the same?

1
2
extern "C" char* xyz;
extern "C" char  xyz[];


And in each case are these the same?

1
2
&xyz[6]
xyz+6


I see both groups as the same. Before I report a compiler bug I need to know if the problem is sitting behind my keyboard.


Basically, yes. The same.

There's argument to be had over the exact terminology, but &xyz[6] and xyz+6 are pointers that point at the exact same memory location.
Are these the same?
1
2
extern "C" char* xyz;
extern "C" char  xyz[];

No. An array is not the same thing as a pointer.


And in each case are these the same?
1
2
&xyz[6]
xyz+6

Almost, but not quite. For &xyz[6] to be valid xyz[6] must refer to a valid element in the array. xyz+6 is allowed to point to the position that comes after the last element.

This is for C++. I assume the rules are similar in C but I'm not sure.
Last edited on
For &xyz[6] to be valid xyz[6] must refer to a valid element in the array.
Are you absolutely sure that's true? Address-of, as I understand it, works by preventing the dereference of its operand. So for example &*(int *)nullptr should never crash.
It was my impression, but no, I'm not absolutely sure. There seems to be arguments in both directions.

This "active issue" seems to treats it as UB and suggests a change to the wording to make it valid, but it seems like it has not been adopted.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
Last edited on
Just to clarify, are these the same once the compiler has processed either statement?
1
2
extern "C" char* xyz;
extern "C" char  xyz[];


As peter87 points out, #1 is a pointer, an address of a character. But after digestion by the compiler, #2 also becomes the address of a character, although the latter form implies an array or character string.

Oh, wait…

The more I look at this the more I start to think that looking at the actual xyz memory location one should find not something like “ABCDEF…” but the _address_ of a string of characters.

My reason for asking is that an older IAR ARM compiler may have messed up when passing the xyz address to an extern "C" function when xyz was defined in form #1. My guess now is that the problem was sitting behind my keyboard.

This is why I like assembly.
> #1 is a pointer, an address of a character.

Yes.


> #2 also becomes the address of a character, although the latter form implies an array

No. #2 is an array of unknown bound (an incomplete type)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

extern "C" char* foo ; // declares 'pointer to char' with C language linkage
extern "C" char  bar[] ; // declares 'array of unknown bound' with C language linkage
                         // at this point, bar is an incomplete type
int main()
{
    std::cout << sizeof(foo) << '\n' ; // fine: size of pointer to char
    // std::cout << sizeof(bar) << '\n' ; // *** error: can't get size of incomplete type
}

extern "C" char* foo ; // redeclares foo; this adds nothing
extern "C" char  bar[20] ; // redeclares bar as an array of known size;
                           // bar is no longer an incomplete type
void baz()
{
    std::cout << sizeof(foo) << '\n' ; // fine: size of pointer to char
    std::cout << sizeof(bar) << '\n' ; // fine: size of array of 20 char (20)
}



Topic archived. No new replies allowed.