SQLite Forum

Off-by-one in testing.html

Off-by-one in testing.html

(1) By anonymous on 2020-12-27 11:29:21 [link] [source]

https://sqlite.org/testing.html says:

Examples of undefined and implementation-defined behavior in ANSI C include:

  • Shifting an N-bit integer by more than N bits.

While the above excerpt is correct as being an example and therefore not covering all cases, it would sound more precise to state:

  • Shifting an N-bit integer by N or more bits.

See C11, 6.5.7p3.

(2) By Warren Young (wyoung) on 2020-12-28 18:21:07 in reply to 1 [link] [source]

The same section (§6.5.7, p.84) in the relevant C standard (C99) agrees: "If the value of the right operand is…greater than or equal to the width of the promoted left operand, the behavior is undefined."

I do want to know which C compiler/host platform gives nonzero for the case of shift width equal to word width, though. :)

(3) By Richard Damon (RichardDamon) on 2020-12-28 19:05:46 in reply to 2 [source]

There are many processors the shift instructions only uses some of the bits in the shift word, and ignores higher order bits in the shift count.

Most processors in the x86 family only use the bottom 5 bits (6 bits for 64 bit mode), and ARM processors only use the bottom 8 bits, so a shift of 32 would zero the register, but a shift of 256 wouldn't.

(4.1) By Keith Medcalf (kmedcalf) on 2020-12-28 21:36:21 edited from 4.0 in reply to 3 [link] [source]

Your predicate is correct but your conclusion is incorrect.

On a processor only using the bottom 5 bits of the shift-count register that contained the value of 32, the shift would be 0. On a processor using at least 6 bits of the shift-count register and where the target register is 32-bits, and the shift is unsigned (the sign is not preserved or extended) then the result would be 0. Mutatis mutandis for other bit lengths.

Note that a shift of count 32 bits on a 64-bit register would not result in 0. Note also that it depends on the particularities of the shift operation -- is it a shift that does not affect the sign bit or is sign extending or is it a strictly binary (unsigned) shift? Is it shifting though the carry bit?

Since the compiler has to be able to implement shift operation on the target platform, and the target platform is variable, the definition of a low-level language like C cannot define what will happen in such circumstances.

This limitation does not apply to most High Level Languages such as FORTRAN or COBOL or PL/1, for example, because the language definition is at a High Level and it is the job of the compiler to "make it so" on whatever CPU claims to support the language.

C and its derivatives, however, are merely a symbolic representation of machine code and the compiler does not really do very much of anything at all. Once you get into High Level Languages you have gobs of runtime library support to get around differences. This is the primary reason why COBOL and FORTRAN are the most portable languages ever created.