warning: using integer absolute value function ‘abs’ when argument is of floating-point type ‘double’
警告:
引数が浮動小数点型 ‘double’ であるのに
引数が整数の絶対値関数 ‘abs’ を使用している。
[-Wabsolute-value]
■この記事の概要
この記事では、C言語で整数の絶対値を求めるabs関数と浮動小数点用のfabs関数の違いや使用時の注意点が詳しく解説されています。#includeの要件や未定義動作への対応方法も紹介しています。
■整数の絶対値を求めるabs関数
#include <stdio.h>
//abs関数使用時必要
#include <stdlib.h>
int main(void){
int x = -1234;
printf("整数の絶対値 %d->%d\n",
x,
abs(x)
);
}
引数が整数の時は
abs()関数を使用してください。
abs()を使う時は
#include <stdlib.h>を忘れないでください。
■浮動小数点の時abs関数は使えない
#include <stdio.h>
#include <stdlib.h>
int main(void){
double x = -12.34;
printf("浮動小数点の絶対値?? %f->%d\n",
x,
abs(x) //ダメ
);
}
引数が浮動小数点の場合abs()は使えません。
■浮動小数点の絶対値を求めるfabs関数
#include <stdio.h>
//数学関数ヘッダが必要
#include <math.h>
//コンパイル環境によって -lm が必要
//gcc f3.c -fno-builtin -lm
int main(void){
double x = -12.34;
printf("浮動小数点の絶対値 %f->%f\n",
x,
fabs(x) //良い
);
}
引数が浮動小数点の場合abs()ではなくて、
適切な関数fasb()を使用してください。
fabs()を使う時は
(1)#include <math.h>を忘れないでください。
(2)コンパイル環境によっては数学関数ライブラリをリンクするため-lm オプションが必要です。
■狭い型を絶対値化する時の注意
#include <stdio.h>
#include <stdlib.h>
int main(void){
signed char x = -128 ;
if(x < 0){
x = -x;
printf("負値のまま %d\n",x);
}
signed char y = -128 ;
if(y < 0){
y = abs(y);
printf("負値のまま %d\n",y);
}
signed char z = -128 ;
printf("期待した結果 %d\n",abs(z));
}
signed char の
最大値は 127
最小値は -128
なので
signed char で -(-128)=128は表現できません。
■abs(INT_MIN)に注意
runtime error: negation of -2147483648 cannot be represented in type ‘int’; cast to an unsigned type to negate this value to itself
警告:最大の負整数の絶対値は、定義されていない。
[-fsanitize=undefined]
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
//gcc -fsanitize=undefined
int main(void){
int x = INT_MIN ;
if(x < 0){
x = -x;
printf("負値のまま %d\n",x);
}
printf("負値のまま %d ➡ %d\n",
INT_MIN,
abs(INT_MIN) //絶対値にならない
);
}
(1) abs(INT_MIN)の動作はマニュアルによると決まっていないそうです。(未定義の動作?)
gccの場合
INT_MAX= 2147483647
INT_MIN=-2147483648
なので INT_MIN の絶対値 2147483648 はint で表現できないため。
(2) -INT_MINの計算は未定義の動作となり、
gcc -fsanitize=undefined (未定義動作検出オプション)でコンパイルし走らせると
x=-xで異常終了します。