【C言語】
if文で範囲指定を正しく行う方法と成績判定プログラムの実例

warning: comparisons like ‘X<=Y<=Z’ do not have their mathematical meaning

warning: result of comparison of constant X with boolean expression is always true

警告:if(X<=Y<=Z)に数学的意味はありません

[-Wtautological-constant-out-of-range-compare]
[-Wparentheses]

■この記事の概要

この記事では、C言語のif文で範囲指定を正しく行う方法について解説しています。

間違った書き方で生じる警告や動作不良の原因を説明し、推奨される記述方法やGCCの拡張機能を使った簡便な範囲指定の例を提供しています。


■if(X<=Y<=Z)で範囲の指定はできない

#include <stdio.h>
const char  *grade(int x){
    if(0    <= x <= 9)     return  "不可";
    if(10   <= x <= 59)    return  "可";
    if(60   <= x <= 79)    return  "良";
    if(80   <= x <= 100)   return  "優";
    return  "採点不能";
}
int main(void){
    for(int i = -1 ; i<=101;i++){
        printf("%3d点は%s\n",i,grade(i));
    }
}

自然言語に近い表現ですが
意図した動きをしません。

if(0 <= x <= 9)

if((0<=x)<=9

if(論理式<=9)

if(真<=9)かif(偽<=9)になる

if(1<=9)かif(0<=9)の
どちらかになるが、
どちらも必ず成立する。


■数直線を意識した範囲の指定(推奨)

#include <stdio.h>
const char  *grade(int x){
    if(0    <= x && x <= 9)     return  "不可";
    if(10   <= x && x <= 59)    return  "可";
    if(60   <= x && x <= 79)    return  "良";
    if(80   <= x && x <= 100)   return  "優";
    return  "採点不能";
}
int main(void){
    for(int i = -1 ; i<=101;i++){
        printf("%3d点は%s\n",i,grade(i));
    }
}

意図した動きをします。
自然言語に近く数直線に近いイメージで
読みやすいと思います。


gccの拡張機能を使った範囲の指定

#include <stdio.h>
const char  *grade(int x){
    switch(x){
    case 0 ...   9: return  "不可";
    case 10 ... 59: return  "可";
    case 60 ... 79: return  "良";
    case 80 ... 100:return  "優";
    default:        return  "採点不能";
    }
}
int main(void){
    for(int i = -1 ; i<=101;i++){
        printf("%3d点は%s\n",i,grade(i));
    }
}

自然言語に一番近い分かりやすい表現ですが、
gcc/clangの拡張機能です。

拡張機能は
使用が禁止されている業界もあります。

参考:

EXP13-C. 関係演算子および等価演算子は、結合則が成り立たないものとして扱う