Posted at

[C] max()関数をいろいろ作る

More than 1 year has passed since last update.


はじめに

C言語でいろいろなmax()関数を作ります.


  • キーワード


    • 条件演算子

    • 配列

    • 可変長引数

    • マクロ




普通に書いてみる


main.c

#include <stdio.h>


int max1(int a, int b) {
if (a > b)
return a;
else
return b;
}

int main(void) {
printf("%d\n", max1(10, 20)); // 出力は20
return 0;
}


if文を使って値が大きい引数を返します.


コードを短くする


main.c

#include <stdio.h>


int max1(int a, int b) { return a > b ? a : b; }

int main(void) {
printf("%d\n", max1(10, 20)); // 出力は20
return 0;
}


条件演算子(三項演算子)を使うことで,max()関数のコードを6行から1行に短縮できました.


配列に対応する


main.c

#include <stdio.h>


int max2(int len, int *nums) {
int i, _max = nums[0];
for (i = 1; i < len; i++) {
if (nums[i] > _max)
_max = nums[i];
}
return _max;
}

int main(void) {
int a[] = {20, 40, 10, 30};
printf("%d\n", max2(4, a)); // 出力は40
return 0;
}


一つ目の引数に配列の長さ,二つ目の引数に配列のアドレスを渡すことで配列の最大値を返します.


可変長引数を使う

四つの変数abcdの最大値を求めたい場合では,max1()関数,max2()関数を次のように使います.


max1()関数の利用

// 何らかの処理でa, b, c, dの値を取得

printf("%d\n", max1(a, max1(b, max1(c, d))));


max2()関数の利用

int array[4];

// 何らかの処理でa, b, c, dの値を取得

array[0] = a;
array[1] = b;
array[2] = c;
array[3] = d;
printf("%d\n", max2(4, array));


どちらもいまいちですね.max1()関数では入れ子が多くなり見づらく,max2()関数では配列の生成が面倒です.そこで,可変長引数を利用した新しいmax3()関数を作ってみます.


main.c

#include <stdio.h>

#include <stdarg.h>

int max3(int len, ...) {
int i, _max, num;
va_list ap;
va_start(ap, len);

_max = va_arg(ap, int);
for (i = 1; i < len; i++) {
num = va_arg(ap, int);
if (num > _max)
_max = num;
}
va_end(ap);
return _max;
}

int main(void) {
int a = 20, b = 40, c = 10, d = 30;
printf("%d\n", max3(4, a, b, c, d)); // 出力は40
return 0;
}


<stdarg.h>ヘッダで定義されているva_list型,va_startマクロ,va_argマクロ,va_endマクロを利用することで,関数の引数の個数を可変にすることが出来ます.関数の呼び出し部分が次のように非常にシンプルになりました.


max3()関数の利用

// 何らかの処理でa, b, c, dの値を取得

printf("%d\n", max3(4, a, b, c, d));


マクロで書いてみる


main.c

#include <stdio.h>

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main(void) {
printf("%d\n", MAX(10, 20)); // 出力は20
printf("%f\n", MAX(0.1, 0.2)); // 出力は0.2
return 0;
}

型を指定しないため,int型やdouble型など複数の型に対応が出来ますが,副作用を伴う演算では意図しない動作をするため注意が必要です.


意図しない動作

int a = 1;

printf("%d\n", MAX(2, ++a)); // 出力は3

これはMAX(2, ++a)がプリプロセッサによって((2) > (++a) ? (2) : (++a))に置換され,++aが二回評価されてしまうために起こる現象です.


おわりに

3種類のmax()関数+1種類のマクロを作成しました.

用途によって使い分けることが大切です.