2
votes

From 6.3.2.1 (emphasis mine)

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.

That means, that if the automatic object could not be declared with the register storage class (have it's address taken):

int x; 

printf("just a dummy pointer print %p", &x);  //taking the address to break 6.3.2.1 UB condition

if (x == 2)
{
    print("x uninitialized value: %d", x);
} 

Than according to 6.3.2.1 there is no undefined behavior in if (x == 2) where I use the value of the uninitialized object. If that is true, and there is no UB here, than what is the defined behaviour? what should I expect in x according to the standard?

2
Maybe we could give objective answers if you were to put the quoted section in context? For example, what does 'the behavior' refer to? - Adrian Mole
@Adrian it's the C standard, not some exotic book. - Federico klez Culloca
Than 6.3.2.1 is not relevant So? That doesn't preclude undefined behavior for other reasons. That's like telling the police officer that pulled you over for running a red light, "But I didn't exceed the speed limit!". - Andrew Henle
Note that you don't need to print the pointer. Just a do-nothing statement like &x; suffices to meet the condition for it not to be UB. - R.. GitHub STOP HELPING ICE
It might be normally for you and many other absolute pros to know what you mean with "6.3.2.1 (emphasis mine)" but can you give an absolute reference to what you are referingto? Is it the ANSI-C implementation? - RobertS supports Monica Cellio

2 Answers

2
votes

In this case, because x has had it's address taken, the behavior is not strictly undefined. The value of x at this point is indeterminate. This means the value is either a trap representation or unspecified.

If x happens to contain a trap representation then the behavior is undefined, otherwise the value is unspecified which means that any valid value could be printed.

Also, most systems you're likely to come across don't have any padding bits in integer types, meaning there are no trap representations on that implementation and the value will always be unspecified.

The relevant passages from the C standard:

Section 3.19:

3.19.2

1 indeterminate value either an unspecified value or a trap representation

3.19.3

1 unspecified value valid value of the relevant type where this International Standard imposes no requirements on which value is chosen in any instance

2 NOTE An unspecified value cannot be a trap representation.

3.19.4

1 trap representation an object representation that need not represent a value of the object type

Section 6.7.9p10:

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.

0
votes

The Standard uses the term "Undefined Behavior", among other things, to describe general situations where the vast majority of implementations would behave in the same predictable general fashion, but where some particular implementations might serve their customers better by behaving differently.

Consider the following function:

struct foo { unsigned char dat[256]; };

struct foo x,y;

void test(int a, int b)
{
  struct foo temp;
  temp.dat[a] = 1;
  temp.dat[b] = 2;
  x=temp;
  y=temp;
}

I don't think the authors of the Standard wanted to require that programmers fully initialize temp before storing it, but I also don't think they wanted to forbid implementations from simply writing to x.dat[a], y.dat[a], x.dat[b], and y.dat[b], while leaving other elements of those structures holding whatever they'd held previously. Rather than trying to characterize exactly what sorts of optimizations should be allowed, they simply assumed that implementations would seek to best serve their customers' needs.