Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

c99 - Why are compound literals in C modifiable

One does usually associate 'unmodifiable' with the term literal

char* str = "Hello World!";
*str = 'B';  // Bus Error!

However when using compound literals, I quickly discovered they are completely modifiable (and looking at the generated machine code, you see they are pushed on the stack):

char* str = (char[]){"Hello World"};
*str = 'B';  // A-Okay!

I'm compiling with clang-703.0.29. Shouldn't those two examples generate the exact same machine code? Is a compound literal really a literal, if it's modifiable?

EDIT: An even shorter example would be:

"Hello World"[0] = 'B';  // Bus Error!
(char[]){"Hello World"}[0] = 'B';  // Okay!
See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

A compound literal is an lvalue and values of its elements are modifiable. In case of

char* str = (char[]){"Hello World"};
*str = 'B';  // A-Okay!  

you are modifying a compound literal which is legal.

C11-§6.5.2.5/4:

If the type name specifies an array of unknown size, the size is determined by the initializer list as specified in 6.7.9, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue.

As it can be seen that the type of compound literal is a complete array type and is lvalue, therefore it is modifiable unlike string literals

Standard also mention that

§6.5.2.5/7:

String literals, and compound literals with const-qualified types, need not designate distinct objects.101

Further it says:

11 EXAMPLE 4 A read-only compound literal can be specified through constructions like:

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}   

12 EXAMPLE 5 The following three expressions have different meanings:

"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}

The first always has static storage duration and has type array of char, but need not be modifiable; the last two have automatic storage duration when they occur within the body of a function, and the first of these two is modifiable.

13 EXAMPLE 6 Like string literals, const-qualified compound literals can be placed into read-only memory and can even be shared. For example,

(const char []){"abc"} == "abc"

might yield 1 if the literals’ storage is shared.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...