tags:

views:

180

answers:

5

Please see the following statements:

char a[5]="jgkl"; // let's call this Statement A
char *b="jhdfjnfnsfnnkjdf"; // let's call this Statement B , and yes i know this is not an Array
char c[5]={'j','g','k','l','\0'}; // let's call this Statement C

Now, is there any difference between Statements A and C? I mean both should be on Stack dont they? Ony b will be at Static location. Someone said:


---- Edit: Removing the Quotation of the Person, since the Question has been answered. ----


So wouldn't that make "jgkl" exist at the static location for the entire life of the program? Since it is supposed to be read-only/constant? Please clarify.

+2  A: 

If a[] is static then so is c[] - the two are equivalent, and neither is a string literal. The two could equally well be declared so that they were on the stack - it depends where and how they are declared, not the syntax used to specify their contents.

anon
C99 says this under Initialization section :An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.So the Standard states it is a string literal.
strut
@strut No - they are not, they are both arrays who's contents can be altered after initialisation, wheeas the contents of b cannot be modified. You are misunderstanding what you are reading.
anon
The C++ Programming Language, Third Edition by Bjarne Stroustrup, says, The type of a string literal is ‘‘array of the appropriate number of const characters".... here the array is not const... ?? So does that still make Statement A string literal??I think No!! :) Thanks
strut
@strut In `a[] = "foo"`, a is an array, "foo" is a literal.
anon
Well that is what i had been thinking all this while when i quoted the standard and said :" So the Standard states it is a string literal.":|
strut
A: 

C-Literals always are read-only.

  • a) allocates 5 bytes memory and store the CONTENT from literal incl. '\0' in it
  • b) allocates sizeof(size_t) bytes memory and store the literal-address in it
  • c) allocates 5 bytes memory and store the 5 character-values in it
Only b refers to a string literal. and is thus "read-only".
anon
In (a), there is no literal. You can never take the address of anything to find a `char *` to "jgkl" as a string literal in that case.
Heath Hunnicutt
@Heath, right, that's what I was trying to say.
AShelly
+2  A: 

the value "jgkl" may never be loaded into working memory. Before main is ever called, a function (often called cinit) is run. One of the things this function does is initialize static and file-scope variables. On the DSP compiler I use, the initial values are stored in a table which is part of the program image. The table's format is unrelated to the format of the variables that are being initialized. The initializer table remains part of the program image and is never copied to RAM. Simply put, there is nowhere in memory that I can reliably access "jgkl".

Small strings like a might not even be stored in that table at all. The optimizer may reduce that to the equivalent (pseudoinstruction) store reg const(152<<24|167<<16|153<<8|154)

I suspect most compilers are similar.

AShelly
+4  A: 

No, because the characters "jgkl" from Statement A are used to initialize a, it does not create storage in the executable for a character string (other than the storage you created by declaring a). This declaration creates an array of characters in read-write memory which contain the bytes {'j','g','k','l','\0'}, but the string which was used to initialize it is otherwise not present in the executable result.

In Statement B, the string literal's address is used as an initializer. The variable char *b is a pointer stored in read-write memory. It points to the character string "jhdfjnfnsfnnkjdf". This string is present in your executable image in a segment often called ".sdata", meaning "static data." The string is usually stored in read-only memory, as allowed by the C standard.

That is one key difference between declaring an array of characters and a string constant: Even if you have a pointer to the string constant, you should not modify the contents.

Attempting to modify the string constant is "undefined behavior" according to ANSI C standard section 6.5.7 on initialization.

Heath Hunnicutt
Thank you so much :)The information you provided can you please tell me which book can give me such details regarding .sdata ,etc. Please do help.
strut
@Heath: string literals in C are actually *not* `const` qualified (for mainly historical reasons). Nevertheless, the program is not allowed to write to them.
Gilles
@Giles: Thanks for that important correction, which is now incorporated to my answer.
Heath Hunnicutt
@strut: The book with the most important information is the ANSI C Standard, but you have to read every word of it carefully. With regards to `.sdata`, I recommend you to experiment with the compiler and linker. In particular, mixing assembly language with C leads to understanding how these things work.
Heath Hunnicutt
I disagree with your "not that common" about read-only string literals. In my experience *most* compilers place string literals in read-only memory.
Zan Lynx
@Zan - I just did a few experiments and found you are correct. It has been a while since I "tested" that in any compiler I use -- like about 20 years. ;)
Heath Hunnicutt
Also can someone please explain a statement like this: printf("You know what this is\n");What we pass here in printf, is this a String Literal?? If not then what?
strut
Yes, that is a string literal. In particular, it is the _address_ of this string literal which is passed to `printf()`.
Heath Hunnicutt
"jgkl" in Statement A is indeed a string literal. It is a string literal because it is a sequence of characters between double quotes. The string literal is used as an initializer of the array `a`. When a string literal is used as an initializer, its contents are copied into the array. Concerning the last sentence of the answer, the behavior is not implementation-defined. The behavior is undefined if you attempt to modify a string literal (see §6.4.5/6 and §6.7.8/32).
James McNellis
Ok another doubt:The C++ Programming Language, Third Edition by Bjarne Stroustrup, says,The type of a string literal is ‘‘array of the appropriate number of const characters"....here the array is not const... ?? So does that still make Statement A string literal??
strut
@strut, James is right that it is a string literal in the vocabulary of the standard, that was my mistake. I am correct that the string literal defined to initialize your array does not become part of your executable, which is what I meant by "not a string literal." It is a string literal for the parser, but not for the code generator. As for the Bjarne Stroustrup comment about const, that is C++, so who knows? You asked about C. Regarding James' citations, he seems to be using the C99 standard. My citations are to the ANSI standard.
Heath Hunnicutt
@James, I incorporated your corrections. Maybe I should only try to answer subjective question such as "Should I reimplement isalpha()?" so that I can "be right" rather than "be helpful."
Heath Hunnicutt
@Heath: I didn't think your answer was unhelpful; it was just slightly wrong with respect to a few details, so I thought I'd try to be helpful and recommend a few corrections. +1 for the corrected post, certainly.
James McNellis
+1  A: 

A and C are exactly equivalent. The syntax used in A is an abbreviation for the syntax in C.

Each of the objects named a and c is an array of bytes of length 5, stored at a certain location in memory which is fixed during execution. The program can change the element bytes at any time. It is the compiler's responsibility to decide how to initialize the objects. The compiler might generate something similar to a[0] = 'j'; a[1] = 'g'; ..., or something similar to memcpy(a, static_read_only_initialization_data[1729], 5), or whatever it chooses. The array is on the (conceptual) stack if the declaration occurs in a function, or in global writable memory if the declaration occurs at file scope.

The object named b is a pointer to a byte. Its initial value is a pointer to string literal memory, which is read-only on many implementations that have read-only memory, but not all. The value of b could change (for example to point to a different string, or to NULL). The program is not allowed to change the contents of jhdfjnfnsfnnkjdf", though as usual in C the implementation may not enforce this.

Gilles