What aspects of a signed left shift are undefined with GCC?

Basically I am asking for translation:

GCC does not use the latitude indicated on C99, only to handle certain aspects of the signed `<<as undefined, but this can be changed.

( GCC Manual 4.8.1, Clause 4.5 )

What is latitude? What are certain aspects?

+6
source share
3 answers

Other answers have already indicated which aspects of << are undefined. I assume that you want to "translate" gcc into a common language.

If the behavior of the C standard is undefined, compiler developers can take the “latitude” to do whatever suits them if such a case occurs. In particular, they do not need to diagnose or detect this case, and they may pretend that this will never happen. It is the responsibility of the programmer to write his program in such a way that its behavior is always determined.

In the case of a left shift, this means that the compiler would not need to check for overflow and may pretend that a loop like

 for (int i = 1; i > 0; i <<= a) { .... change a in some complicated way ... } 

will never end.

The sentence you are quoting indicates that they do not, however, but future versions of gcc may do so.

+2
source

Information about the left shift operator in the draft C99 standard (ISO / IEC9899: TC3, aka WG14 / N1256) is rather scarce.

Section 6.5.7 (bitwise shift operators) has already been specified by Alter Mann.

Appendix J, Section J.2 (Undefined Behavior) says the following:

Undefined behavior in the following cases:
[...]

- the expression is shifted by a negative number or by an amount greater than or equal to the width of the promoted expression (6.5.7).

- an expression having a signed advanced type is shifted to the left and either the value of the expression is negative or the result of the offset will not be presented in (6.5.7).

I do not think that the implementation is allowed for some mandatory undefined behavior. If I am not mistaken, the implementation is allowed to define unspecified behavior (but this is optional) and it is required to specify the behavior defined during the implementation , but undefined cannot be specified. This does not mean that the implementation cannot choose reasonable, meaningful behavior, but it cannot allow the user to rely on it (he cannot “indicate it”).

I admit that I’m not quite sure about this. Hope this helps.

Edit: With further reflection, I think that the corresponding implementation can determine the behavior that the standard considers undefined behavior , but the resulting program cannot be called appropriate (see section 3.4.3).

+3
source

C99 §6.5.7 / 3-4 lists two specific undefined behaviors regarding the left shift operator ( << ):

3) [...] If the value of the right operand is negative or greater than or equal to the width of the advanced left operand, the behavior is undefined.

4) The result of E1 << E2 is [...]. If E1 has a signed type and a non-negative value, and E1 × 2 E2 is represented in the result type, then this is the resulting value; otherwise, the behavior is undefined.

How exactly the GCC behaves in these circumstances, I can not say. It may well give a certain behavior in these situations; however, such code will still be undefined when compiling with other compilers.

My guess is that GCC treats a signed left offset identically with an unsigned left shift - that is, if it calculates x << y as (signed)((unsigned)x << y) , performing bit offsets (potentially discarding any high bits ), and then reinterpreting the result as a signed amount. This implies that the most significant bit of the signed integer value is shifted to the sign bit; which seems a little strange from an arithmetic point of view, but it makes perfect sense from a bit-by-bit perspective.

+2
source

Source: https://habr.com/ru/post/952406/


All Articles