Questo codice dà risultati diversi per -O1 e -O2:Si tratta di un bug di clang optimizer o di un comportamento non definito in C?
/*
Example of a clang optimization bug.
Mark Adler, August 8, 2015.
Using -O0 or -O1 takes a little while and gives the correct result:
47 bits set (4294967296 loops)
Using -O2 or -O3 optimizes out the loop, returning immediately with:
0 bits set (4294967296 loops)
Of course, there weren't really that many loops. The number of loops was
calculated, correctly, by the compiler when optimizing. But it got the
number of bits set wrong.
This is with:
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
*/
#include <stdio.h>
#include <inttypes.h>
/* bit vector of 1<<32 bits, initialized to all zeros */
static uint64_t vec[1 << 26] = {0};
int main(void)
{
/* set 47 of the bits. */
vec[31415927] = UINT64_C(0xb9fe2f2fedf7ebbd);
/* count the set bits */
uint64_t count = 0;
uint64_t loops = 0;
uint32_t x = 0;
do {
if (vec[x >> 6] & ((uint64_t)1 << (x & 0x3f)))
count++;
x++;
loops++;
} while (x);
printf("%" PRIu64 " bits set (%" PRIu64 " loops)\n", count, loops);
return 0;
}
Quindi questo è un bug? O c'è in qualche modo un comportamento indefinito lì dentro, che il compilatore ha i suoi diritti per dare risultati diversi?
Per quanto posso dire dallo standard C99, il ciclo do
per passare attraverso tutti i valori uint32_t
è valido poiché l'incremento del valore intero senza segno più grande è ben definito per risultare zero.
Un calcolo coinvolge operandi unsigned può mai troppopieno, perché un risultato che non può essere rappresentato dal numero intero senza segno tipo risultante viene ridotta modulo il numero che è maggiore di uno rispetto al massimo valore che può essere rappresentato dal tipo risultante.
Avete considerato la dimensione di vec eccessiva e quindi un sovraccarico di stack? – edmz
@black vec non è nello stack – Joe
'0xb9fe2f2fedf7ebbd' è troppo grande per essere un' int', dovresti aggiungere 'ULL'. – mch