C言語で絶対値を求めるときは、整数と浮動小数点で使う関数が異なります。
本記事では、abs・labs・llabs・fabsの4種類を「どの型で使うか」「どのヘッダを読むか」「オーバーフローは大丈夫か」まで丁寧に整理します。
初心者の方でも安全に使えるよう、注意点や実行例を交えて解説します。
絶対値の基本
絶対値とは
絶対値とは、数値の符号(プラス・マイナス)を取り除いた大きさのことです。
例えば -3 の絶対値は 3、3 の絶対値は 3 になります。
絶対値は「0からどれだけ離れているか」を表す量であり、距離や誤差の評価で頻繁に使われます。
4つの関数と対応する型
C言語の標準ライブラリには、次の4つの絶対値関数があります。
整数にはabs・labs・llabs、小数にはfabsを使います。
関数名と対応する型は次の通りです。
| 関数 | 引数の型 | 戻り値の型 | 主な用途 | 宣言ヘッダ |
|---|---|---|---|---|
| abs | int | int | 通常の整数(int)の絶対値 | <stdlib.h> |
| labs | long | long | long型の絶対値 | <stdlib.h> |
| llabs | long long | long long | long long型(64bit相当)の絶対値 | <stdlib.h> |
| fabs | double | double | 小数(double)の絶対値 | <math.h> |
補足として、小数にはfloat版のfabsf、long double版のfabslもありますが、本記事ではfabs(double)を中心に説明します。
ヘッダファイル
abs・labs・llabsは<stdlib.h>に宣言されています。fabsは<math.h>に宣言されています。- 定数の最小値/最大値を扱うときは
<limits.h>が、浮動小数点の範囲や特性を知るときは<float.h>が役立ちます。
最小限のインクルード例は次の通りです。
// 最小限のインクルード例
#include <stdlib.h> // abs, labs, llabs
#include <math.h> // fabs
#include <limits.h> // INT_MIN, LONG_MIN, LLONG_MIN
#include <float.h> // DBL_MAX など
オーバーフローに注意
整数の最小値(INT_MINなど)に対して絶対値を計算すると、結果が同じ型に収まらず未定義動作になることがあります。
例えば多くの環境でINT_MINは-2147483648で、その正の値+2147483648はintに収まりません。
abs(INT_MIN)、labs(LONG_MIN)、llabs(LLONG_MIN)は未定義動作です。
必要なら、より広い型に拡張してから計算するか、事前にチェックして別処理に分けると安全です。
整数の絶対値を求める
abs(int) の使い方
absはint専用の絶対値関数です。
基本的な使い方は次のとおりです。
ただしINT_MINは未定義動作になるため、そのときは処理を分けます。
// ファイル名: abs_int_example.c
#include <stdio.h>
#include <stdlib.h> // abs
#include <limits.h> // INT_MIN
int main(void) {
int values[] = { -123, 0, 456, INT_MIN };
size_t n = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < n; ++i) {
int x = values[i];
if (x == INT_MIN) {
// INT_MINはabs(x)が未定義動作になる可能性がある
// より広い型(long long)に拡張してから符号反転して安全に扱う
long long widened = (long long)x; // 拡張
long long safe_abs = widened < 0 ? -widened : widened;
printf("abs(INT_MIN) は未定義なのでスキップ。安全な幅での絶対値: %lld\n",
safe_abs);
} else {
// 通常の範囲なら安全にabsを使える
int a = abs(x);
printf("abs(%d) = %d\n", x, a);
}
}
return 0;
}
abs(-123) = 123
abs(0) = 0
abs(456) = 456
abs(INT_MIN) は未定義なのでスキップ。安全な幅での絶対値: 2147483648
labs(long) の使い方
labsはlong専用です。
環境によってlongのビット幅が異なる(Windowsでは多くの場合32bit、LinuxやmacOSでは多くの場合64bit)点に注意してください。
// ファイル名: labs_long_example.c
#include <stdio.h>
#include <stdlib.h> // labs
#include <limits.h> // LONG_MIN
int main(void) {
long a = -1234567890L;
long b = 0L;
long c = 987654321L;
printf("labs(%ld) = %ld\n", a, labs(a));
printf("labs(%ld) = %ld\n", b, labs(b));
printf("labs(%ld) = %ld\n", c, labs(c));
// LONG_MINの場合は未定義動作になり得るので注意
if (LONG_MIN < 0) {
long m = LONG_MIN;
// labs(m); // これは未定義動作になる可能性があるので避ける
printf("LONG_MINの絶対値は同じlongに収まらないため、labs(LONG_MIN)は未定義です\n");
}
return 0;
}
labs(-1234567890) = 1234567890
labs(0) = 0
labs(987654321) = 987654321
LONG_MINの絶対値は同じlongに収まらないため、labs(LONG_MIN)は未定義です
llabs(long long) の使い方
llabsはlong long専用です。
64bit整数の絶対値を取りたいときに使います。
// ファイル名: llabs_ll_example.c
#include <stdio.h>
#include <stdlib.h> // llabs
#include <limits.h> // LLONG_MIN
int main(void) {
long long x = -9223372036854775807LL; // LLONG_MINは避ける
long long y = 1234567890123LL;
printf("llabs(%lld) = %lld\n", x, llabs(x));
printf("llabs(%lld) = %lld\n", y, llabs(y));
// LLONG_MINは未定義動作になり得る
printf("LLONG_MINの絶対値はllabsでは未定義動作になります\n");
return 0;
}
llabs(-9223372036854775807) = 9223372036854775807
llabs(1234567890123) = 1234567890123
LLONG_MINの絶対値はllabsでは未定義動作になります
型に合わせて選ぶ
絶対値関数は「引数の型」と「戻り値の型」が一致するペアを選ぶのが基本です。
intにabs、longにlabs、long longにllabsというように、無理なキャストを挟まずに素直に対応付けるとミスが減ります。
例えばlong longの値にabsを使うと、引数がintに変換され情報が失われる場合があるため危険です。
最小値に注意
INT_MIN・LONG_MIN・LLONG_MINの絶対値は同じ型では表現できないため、該当する可能性があるときは次のいずれかを行います。
- 事前に最小値かどうかを判定して別処理にする。
- より広い型に拡張してから絶対値を求め、広い型のまま扱う。
例として、intについて安全に処理するひな形を示します。
// INT_MINを安全に扱う例
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void) {
int x = INT_MIN;
if (x == INT_MIN) {
// より広い型(long long)に拡張してから絶対値を求める
long long ax = (long long)x;
long long safe = ax < 0 ? -ax : ax;
printf("INT_MINは未定義動作を避け、long longで扱う: %lld\n", safe);
} else {
printf("abs(%d) = %d\n", x, abs(x));
}
return 0;
}
INT_MINは未定義動作を避け、long longで扱う: 2147483648
より汎用に安全対策をしたい場合は<inttypes.h>のintmax_tとimaxabsも検討できます。
浮動小数点の絶対値を求める
fabs(double) の使い方
小数(浮動小数点)の絶対値はfabsを使います。
負のゼロ(-0.0)はfabsで+0.0になります。
また、fabs(INFINITY)はINFINITY、fabs(NAN)はNANを返します。
// ファイル名: fabs_double_example.c
#include <stdio.h>
#include <math.h> // fabs, INFINITY, NAN
#include <float.h> // DBL_MAX (参考)
#include <fenv.h> // 例外制御(今回は未使用)
int main(void) {
double vals[] = { -3.14, 0.0, -0.0, INFINITY, -INFINITY, NAN };
size_t n = sizeof(vals) / sizeof(vals[0]);
for (size_t i = 0; i < n; ++i) {
double x = vals[i];
double ax = fabs(x);
// %gでNaN/Infも表示しやすい
printf("fabs(%g) = %g\n", x, ax);
}
return 0;
}
fabs(-3.14) = 3.14
fabs(0) = 0
fabs(-0) = 0
fabs(inf) = inf
fabs(-inf) = inf
fabs(nan) = nan
表記(cst-code>infやnan)は処理系により少し異なることがあります。
小数にはfabsを使う
小数にabsを使うのは間違いです。
absはint用なので、doubleを渡すと整数へ変換され、小数点以下が失われます。
// 誤用の例: absにdoubleを渡すと整数に丸められてしまう
#include <stdio.h>
#include <stdlib.h> // abs
#include <math.h> // fabs
int main(void) {
double d = -3.7;
// 誤り: absはint用。-3.7は-3に変換される可能性が高い
int wrong = abs(d); // 実質的にabs(-3)と同等になりがち
double right = fabs(d); // 正しい
printf("誤用: abs(-3.7) -> %d (小数が失われる)\n", wrong);
printf("正解: fabs(-3.7) -> %.1f\n", right);
return 0;
}
誤用: abs(-3.7) -> 3 (小数が失われる)
正解: fabs(-3.7) -> 3.7
小数にはfabsを使う、これが鉄則です。
floatならfabsf、long doubleならfabslもあります。
ヘッダとビルド
- ヘッダ:
fabsは<math.h>にあります。 - リンクオプション: Unix系(GCC/Clang)では数学ライブラリへのリンクが必要になることがあります。
-lmを付けましょう。
ビルド例:
# GCC/Clang (Unix系): fabsを使う場合は -lm を付ける
gcc -std=c17 -Wall -Wextra fabs_double_example.c -lm -o fabs_example
# absのみなら -lm は不要
gcc -std=c17 -Wall -Wextra abs_int_example.c -o abs_example
# WindowsのMSVCは通常 -lm 不要
cl /std:c17 /W4 fabs_double_example.c
abs・labs・llabs・fabsの使い分けガイド
型で選ぶ早見
「変数の型 = 使う関数」の対応が基本ルールです。
| 変数の型 | 関数 | 戻り値の型 | ヘッダ |
|---|---|---|---|
| int | abs | int | <stdlib.h> |
| long | labs | long | <stdlib.h> |
| long long | llabs | long long | <stdlib.h> |
| double | fabs | double | <math.h> |
floatにはfabsf、long doubleにはfabslが対応します。
ヘッダの違いで迷わない
- 整数の絶対値(
abs/labs/llabs)は<stdlib.h>。 - 浮動小数点の絶対値(
fabs)は<math.h>。 - 数学関数を使うときは、GCC/Clangでは-lmが必要なことがある点に注意。
よくあるミス
- doubleに
absを使ってしまい、小数部分が落ちる。小数はfabs。 - 最小値(INT_MIN/LONG_MIN/LLONG_MIN)に対して絶対値を取り、未定義動作を起こす。事前チェックか、より広い型へ拡張してから処理。
#includeを間違える。整数は<stdlib.h>、小数は<math.h>。- GCC/Clangで
-lmを付け忘れ、リンクエラー。数学関数を使うときは忘れずに。 - 自作マクロで絶対値を実装し、副作用やオーバーフローを見落とす。標準関数の利用が安全。
まとめ
絶対値は「型によって関数が異なる」ことが最大のポイントです。
整数にはabs/labs/llabs、小数にはfabsを使い分け、ヘッダは<stdlib.h>と<math.h>を間違えないことが大切です。
さらに、最小値(INT_MINなど)への絶対値は未定義動作になるため、より広い型へ拡張するか事前チェックで安全に回避しましょう。
この記事のサンプルを土台に、用途と型に合った正しい絶対値の取り方を身につけてください。
