【C言語】
うるう年を判定する
関数版,マクロ版,inline版

うるう年判定式

warning: suggest parentheses around ‘&&’ within ‘||’

警告:X&&Y||Zは(X&&Y)||Zと丸括弧を付けて
[-Wparentheses]


■閏年判定関数版

#include <stdio.h>
int isleap(int year)   {
    if (year % 4 == 0) {
        if (year % 100 == 0) {
            if (year % 400 == 0) {
                return 1;//"閏年です";
            } else {
                return 0;//"閏年ではありません";
            }
        } else {
            return 1;//"閏年です";
        }
    } else {
        return 0;//"閏年ではありません";
    }
}
int main(void){
    for(int year = 1582 ; year <= 2038 ;year++){
        if(isleap(year)){
            printf("%d年は閏年です\n",year);
        } else {
            printf("%d年は閏年ではありません\n",year);
        }
    }
}

記述量が多いので非推奨です。


■閏年判定論理式版

#include <stdio.h>
int main(void){
    for(int year = 1582 ; year <= 2038 ;year++){
        if((year%4==0 && year%100!=0) || year%400==0){
            printf("%d年は閏年です\n",year);
        } else {
            printf("%d年は閏年ではありません\n",year);
        }
    }
}

論理式一行if文中に書いたので
行が長くなります。


■閏年判定マクロ版

#include <stdio.h>
#define isleap(Y) (\
    ((Y)%4==0 && (Y)%100!=0) || (Y)%400==0\
)
int main(void){
    for(int year = 1582 ; year <= 2038 ;year++){
        if(isleap(year)){
            printf("%d年は閏年です\n",year);
        } else {
            printf("%d年は閏年ではありません\n",year);
        }
    }
}

丸括弧がうるさいのであまり推奨しません。


■閏年判定inline関数版

#include <stdio.h>
static inline int isleap(int y) {
    return  (y%4==0 && y%100!=0) || y%400==0 ;
}
int main(void){
    for(int year = 1582 ; year <= 2038 ;year++){
        if(isleap(year)){
            printf("%d年は閏年です\n",year);
        } else {
            printf("%d年は閏年ではありません\n",year);
        }
    }
}

このスタイルを一番推奨します。


■gccの警告

聖典プログラミング言語Cで閏年判定は
leap = year%4==0 && year%100!=0 || year%400==0と紹介されています。

でもこのスタイルは
gccやclangに丸括弧を付けてと警告されます。

ちょっと簡略化けして
leap = (x&&Y)||Z;と
leap = X&&(Y||Z);は、
どちらが正しいでしょうか?

この閏年判定の論理式の場合
どちらも正しいとWikipedia
説明されています。

丸括弧の位置で動作が変わる論理式もあるので
丸括弧を付けるようにしましょう。


参考:

C-FAQ 20.32

isleap