【C言語】
三項演算子(はてな?)の推奨する使い方と避けるべき使い方

三項演算子 はてな?

■if文を使って最大値/最小値を見つける

#include <limits.h>
#include <stdio.h>
int main(void){
	int 配列[] = {3,-1,4,-1,5,-9,2,-6,5,-3,5};
	int 最大値 = INT_MIN ;
	int 最小値 = INT_MAX ;

	const size_t 要素数 = sizeof(配列)/sizeof(配列[0]); 
	for(size_t i = 0 ; i < 要素数 ; i++){ 
		if(	最大値 < 配列[i]) {
			最大値 = 配列[i];
		}
		if(	最小値 > 配列[i]){
			最小値 = 配列[i];
		}
	}
	
	printf("配列内の最大値 = %d\n",最大値);
	printf("配列内の最小値 = %d\n",最小値);
}

■三項演算子を使って最大値/最小値を見つける

#include <limits.h>
#include <stdio.h>
int main(void){
	int 配列[] = {3,-1,4,-1,5,-9,2,-6,5,-3,5};
	int 最大値 = INT_MIN ;
	int 最小値 = INT_MAX ;

	const size_t 要素数 = sizeof(配列)/sizeof(配列[0]); 
	for(size_t i = 0 ; i < 要素数 ; i++){ 
		最大値 = 最大値 < 配列[i] ? 配列[i] : 最大値;
		最小値 = 最小値 > 配列[i] ? 配列[i] : 最小値;
	}
	
	printf("配列内の最大値 = %d\n",最大値);
	printf("配列内の最小値 = %d\n",最小値);
}

ちょっとゲシュタルト崩壊しそうですね。


■三項演算子のマクロを使って最大値/最小値を見つける(推奨)

#include <limits.h>
#include <stdio.h>

#define 大きい方(a,b)		(((a)>(b))?(a):(b))
#define 小さい方(a,b)		(((a)<(b))?(a):(b))

int main(void){
	int 配列[] = {3,-1,4,-1,5,-9,2,-6,5,-3,5};
	int 最大値 = INT_MIN ;
	int 最小値 = INT_MAX ;

	const size_t 要素数 = sizeof(配列)/sizeof(配列[0]); 
	for(size_t i = 0 ; i < 要素数 ; i++){ 
		最大値 = 大きい方(最大値,配列[i]);
		最小値 = 小さい方(最小値,配列[i]);
	}
	
	printf("配列内の最大値 = %d\n",最大値);
	printf("配列内の最小値 = %d\n",最小値);
}

簡潔で読みやすくないですか?。


■三項演算子を使って三つの整数を大きい順に並べる

//3つの整数を大きい順に並べる
#include 	<stdio.h>
#include 	<stdlib.h>
#define 	大きい方(a,b)	((a)>(b)?(a):(b))
#define 	小さい方(a,b)	((a)<(b)?(a):(b))
int main(void){
	char 	buf[BUFSIZ];
	puts("整数を3つ入力してね");
	fgets(buf,BUFSIZ,stdin);
	int 	x,y,z;
	int 	ret = sscanf(buf,"%d %d %d",&x,&y,&z);
	if(ret != 3){
		puts("整数を3つ入力してね");
		exit(1);
	}
	int 	大 = 大きい方(大きい方(x,y),z);
	int 	小 = 小さい方(小さい方(x,y),z);
	int 	中 = (x+y+z) - (大+小);
	printf("大(%d) >= 中(%d) >= 小(%d)\n",大,中,小); 
}


■三項演算子は適度に改行すると読みやすいかも

#include <stdio.h>
#include <time.h>
static inline int うるう年ですか(int y) 
{
    return  (y%4==0 && y%100!=0) || y%400==0 ;
}
int main(void)
{
    int    西暦;
    
    puts("西暦入れてね");
    scanf("%d",&西暦);

    printf("%d年は%s\n",
        西暦,
        うるう年ですか(西暦)?
            "うるう年です":
            "うるう年ではありません"
    );
}

適度に改行すると
if文より簡潔で理解しやすくないですか?


複雑な式に三項演算子を使うのは避けるべき

int f(int flg) {//NG
    int x = 0x80 | (flg == 0) ? 0 : 0xFF00 ;
    return x;
}

0x80 | (flg == 0) ? 0 : 0xFF00 ;は、コンパイラによって
(0x80 | (flg == 0)) ? 0 :0xFF00 ;と解釈されるので、
flg の値に無関係に(0x80 | (flg == 0)) は真と評価されます。

筆者の経験では以下の場合に三項演算子を使うと同僚から嫌われます。
(1) ネストした三項演算子の中の三項演算子
(2) 高速化と称して何でも三項演算子
(3) 演算子の結合順位が分からない三項演算子


■複雑な式は素直にif文で書こう

int g(int flg) {  
    if(flg == 0)  
        return 0x80;
    else           
        return 0xFF00 | 0x80;
}