warning: iteration 1024 invokes undefined behavior
警告:ループカウンタ 1024 で未定義動作
[-Waggressive-loop-optimizations]
■失敗例1.<と<=を間違える
static int ary[1024];
int main(void){
for(int i = 0 ; i <= 1024 ;i++){//★NG
ary[i] = 0 ;
}
}
●修正例1.<に変更する
static int ary[1024];
int main(void){
for(int i = 0 ; i < 1024 ;i++){
ary[i] = 0 ;
}
}
■失敗例2.要素数とサイズを間違える
#include <stdint.h>
static char aryC[1024];
static int aryI[1024];
int main(void){
//たまたま上手くいく例
for(uint32_t i = 0 ; i < sizeof(aryC) ;i++){
aryC[i] = 0 ;
}
//配列の要素数とサイズは違う
for(uint32_t i = 0 ; i < sizeof(aryI) ;i++){//★NG
aryI[i] = 0 ;
}
}
要素数はサイズではありません。
sizeof(ary) != 1024
sizeof(ary) == sizeof(int)*1024
です。
このコードではLP64モードの場合、4096回転するので
配列の領域外破壊が発生します。
●修正例2.
#include <stdint.h>
static char aryC[1024];
static int aryI[1024];
int main(void){
const uint32_t maxC = sizeof(aryC)/sizeof(aryC[0]);
for(uint32_t i = 0 ; i < maxC ;i++){
aryC[i] = 0 ;
}
const uint32_t maxI = sizeof(aryI)/sizeof(aryI[0]);
for(uint32_t i = 0 ; i < maxI ;i++){
aryI[i] = 0 ;
}
}
配列の要素数を求める定石 sizeof(配列)/sizeof(配列[0])を使います。
■失敗例3.添え字の掛け算で桁あふれ
//gcc loop.c -fsanitize=address,undefine
#include <stdio.h>
#include <stdint.h>
int main(void){
for (int i = 0; i < 4; i++){
int64_t j = i * 0x40000000 ;
printf("%lx\n",j);
}
}
i * 0x40000000の計算式でiが3の時、
INT_MAXで収まらないので桁溢れしてしまいます。
●修正例3.接尾子Lを使ってlong型演算を行う
//gcc loop.c -fsanitize=address,undefine
#include <stdio.h>
#include <stdint.h>
int main(void){
for (int i = 0; i < 4; i++){
int64_t j = i * 0x40000000L ;
printf("%lx\n",j);
}
}