Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

c - Is using a structure without all members assigned undefined?

Consider this code in block scope:

struct foo { unsigned char a; unsigned char b; } x, y;
x.a = 0;
y = x;

C [N1570] 6.3.2.1 2 says “If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.”

Although a member of x has been assigned a value, no assignment to x has been performed, and its address has not been taken. Thus, it appears 6.3.2.1 2 tells us the behavior of x in y = x is undefined.

However, if we had assigned a value to every member of x, it would seem unreasonable to consider x to be uninitialized for the purposes of 6.3.2.1 2.

(1) Is there anything in the standard which, strictly speaking, causes 6.3.2.1 2 not to apply to (make undefined) the code above?

(2) Supposing we were modifying the standard or determining a reasonable modification to 6.3.2.1 2, are there reasons to prefer one of the following over the others? (a) 6.3.2.1 2 does not apply to structures. (b) If at least one member of a structure has been assigned a value, the structure is not uninitialized for purposes of 6.3.2.1 2. (c) If all named1 members of a structure have been assigned a value, the structure is not uninitialized for purposes of 6.3.2.1 2.

Footnote

1 Structures may have unnamed members, so it is not always possible to assign a value to every member of a structure. (Unnamed members have indeterminate value even if the structure is initialized, per 6.7.9 9.)

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

My opinion is that it is undefined behaviour simply because it is not explicitly defined by the standard. From 4 Conformance §2 (emphasize mine) :

...Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior.

After many reads in N1570 draft I cannot find any explicit definition of behaviour for using a partially initialized struct. On one hand 6.3.2.1 §2 says:

...If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined

so here x is automatic, has never be initialized (only one of its members), and admitedly its address is never taken so we could think that it is explicitely UB

On the other hand, 6.2.6.1 §6 says:

... The value of a structure or union object is never a trap representation, even though the value of a member of the structure or union object may be a trap representation.

As 6.2.6.1 §5 has just defined a trap representation:

Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that means 0 value for a member and an undefined value for b member. does not have character type, the behavior is undefined.50) Such a representation is called a trap representation.

we could think that it is always legal to take the value of a struct because it cannot be a trap representation

In addition, it is not clear for me if setting the value of a member of a struct actually leaves the struct in an unitialized state.

For all those reasons, I think that the standard does not clearly defines what the behaviour should be and simply for that reason it is undefined behaviour.


That being said I am pretty sure that any common compiler will accept it and will give y the current representation of x, that means 0 value for a member and an indeterminate value of same representation as the current one for x.b for the b member.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...