tags:

views:

298

answers:

4

Recently i saw this piece of code. Shouldnt this line be a compile error?char arr[4]="Abc";

What happens here? Is arr a pointer? is the char* copied into an array on stack? is this legal in all version of C++ (and what about C?). I tested and seen this works in VS and code pad which i believe uses gcc

-edit- Just for fun I tried replacing "Abc" with a static const char *. It gave me an invalid initializer error.

int main()
{
    int j=97;
    char arr[4]="Abc";
    printf(arr,j);
    getch();
    return 0;
}
+3  A: 

It is equivalent to

char arr[4] = {'A', 'b', 'c', 0};

which is in turn equivalent to:

char arr[4];
arr[0] = 'A';
arr[1] = 'b';
arr[2] = 'c';
arr[3] = 0;
Thomas O
check my edit :)
Thomas O
That should be `'\0'`, strictly speaking that doesn't have to be 0.
GMan
No, '\0' means 0. It is the character #0, which has the numeric value of 0.
Thomas O
@Thomas: Whether or not `'\0'` is zero depends on character encoding. It isn't necessarily so. Or maybe not. Looking...
GMan
I'm convinced that @GMan is about to discover that he is wrong on this one.
Charles Bailey
@Charles: Ha, yup. I remember getting a scolding from someone reputable on SO a long time ago when I used 0 instead of `'\0'`, and they said it might not be the same. I can't remember who, but they were wrong. The null-terminator does indeed have to be 0, as it should. Bah, didn't know how to check things back then.
GMan
@GMan: no, '\0' equals 0, no matter which character encoding you use.
Thomas O
The '\0' is actually an octal escape sequence. It is literally the octal number 0. From n1336 See Appendix A.1.5 Section (6.4.4.4) character constants
Martin York
@Martin: How did that become a de facto method of NIL instead of just 0?
GMan
One possibility: Because zero is a logic false. This lets you do stuff like while(*str++) which loops until the character '\0' is reached.
Thomas O
@Thomas: I mean why do people also use `'\0'` instead of just 0?
GMan
@GMan: '\0' means its a char of the escape \0 (which AFAIK is legal in char and string quotes). \VALUE is a oct value unless it starts with \xVALUE. It says so here http://www.open-std.org/jtc1/sc22/open/n2356/lex.html search `escape-sequence:` which shows simple, oct and hex escapes. I dont know how ppl thought it was something other then oct or hex. I never heard of 'encoding' on a hard escape before ;P
acidzombie24
@acid: Once again, I reiterate the question: How did '\0' become a de facto method of acquiring 0 for strings, instead of just directly doing 0? I'm not asking how escapes work.
GMan
Because it allows you to do this: "Hello, world!\0", even though the "\0" is explicit in C. And it makes it obvious to the reader that you intend to compare the value in the string against NUL, not just '0'.
Thomas O
@Thomas: Ah, I see, good one. Thanks.
GMan
@GMan: Maybe because 0 is an int so there is an implicit conversion. While '\0' is a char.
Martin York
+1  A: 

Character arrays can be initialized with string literals, it just assigns each element character by character. It's just a language feature.


And no, arr is not a pointer. It's an array. "Abc" is a string literal, which is also a character array.

GMan
Arrays *are* pointers, are they not?
Thomas O
Arrays are not pointers. Arrays are arrays. Pointers are pointers. Arrays are a collection of contiguous elements, pointers point.
GMan
@Thomas: they are not. `typeid(int*) != typeid(int[10])` Arrays are convertible to pointers though.
ybungalobill
An array has an implicit conversion to a pointer. An `int` has an implicit conversion to `double`. Would you therefore say that an `int` IS a `double`?
Ben Voigt
Ah, I must be getting confused. An array refers to an "array" of memory, but the actual variable points to the first item. That's why arr[x] is equivalent to *(arr + x) - right?
Thomas O
GMan
@Thomas O: Incorrect. Array variable *is* the entire block. There's no pointer there of any kind. `arr[x]` is equivalent to `*(arr + x)` because `arr` can be *implicitly converted* to a pointer "on the fly", not because it itself is a pointer. It is not.
AndreyT
@Thomas it was the whole point of arrays that they are *not* pointers which caused them to be adopted in C. If array variables were pointers, you couldn't stick arrays into structs and map them to external resources. After all, what you would map would be the 4/8 bytes of the pointer only. See http://cm.bell-labs.com/cm/cs/who/dmr/chist.html for details (scroll to "Embryonic C").
Johannes Schaub - litb
+8  A: 

array = ptr is not a legal assignment (if array has an array type and ptr has the corresponding pointer type). In the code you have shown, though, the = introduces an initializer as it is part of a declaration. It is not an assignment.

It is legal to initialize an array of char with a string constant.

Charles Bailey
so this is an array on the stack?
acidzombie24
@acidzombie24: Yes.
Martin York
@acidzombie24: From a language point of view `array` has automatic storage duration so it lives until the end of the scope in which it is declared. Colloquially, it's on the stack.
Charles Bailey
I didnt think of trying this but heres some code showing it is using the stack http://codepad.org/wTZvSYEZ
acidzombie24
@acid: How does that show it's on the stack?
GMan
@GMan: If it was a pointer then the function called the 2nd time would print Azb in the first printf getting the output AbcAzcA**z**cAzc. However in VS i get a access violation error at runtime and codepad seems to ignore writes to const char* http://codepad.org/4vs0B43f
acidzombie24
@acid: The line `arr[1] = 'z';` invokes undefined behavior. You cannot draw any conclusions from this program, at all.
GMan
+3  A: 

String literal is not a pointer. String literal is an character array. So, what you have in your example is an array = array initialization, not an array = pointer as you seem to believe.

Yet in general it is indeed illegal to initialize one array with another array, in both C and C++.

However, in both C and C++ there's one exception from that rule: character arrays can be initialized with string literals. (Note: initialization is allowed; assignment won't work). Each element of the array gets initailized with the corresponding character from the literal (which also implicitly include a terminating zero character at the end). In C++ it is required that the recipient array's size has enough space for the terminating zero. In C the terminating zero is allowed to "fall off", if the recipient array is one character short.

Also, you are not required to specify the array size explicitly. You can do

char arr[] = "Abc";

and the compiler will automatically figure out that you need a 4 element array.

AndreyT