オプション沼(16) ANSI-C(ISO-C)の闇? -ansiと-pedantic

Joseph Halfmoon

元より野次馬、不穏な気配のたなびくところにひかれます。前回が「小さい闇」なら、今回のは「おおきい闇」でしょうか。以前から2つのオプションに関する説明の書きぶりの「不貞腐れた感じ」が気になっていたのです。ウルセー奴らがいるから、あるいは、あんたの思っているのとは違うぜ的な。元より素人、ちょっとのぞき見してみるだけ。

※『オプション沼』投稿順indexはこちら

※動作確認に Windows11 WSL2上のUbuntu 20.04 LTS を使用しています。gccのバージョンは9.4.0です

-ansi

「堅い会社」のC言語のソースコードを拝見したときにその堅さが即座に分かるのはコメントの書き方でしょうか。//のC++式の1行コメントは使わず、伝統の

/* */

で書いてあります。多くANSI-C(ISO-C、C90もしくはC89)に準拠とな。コンパイラ依存の拡張など使わずコンパイラが変わってもソースの首尾一貫を求める姿勢じゃないかと思います。

そゆときに使われガチな -ansi オプション(-std=C90 オプションと等価だそうな)ですが、長いこと誤解してました。このオプションをつければたちまちANSI-Cのコンパイラになるのだ、と。

でもオプションの説明読めば違いました。

3.4 Options Controlling C Dialect

GCCはいろいろと「独自拡張」されている部分があり、その中のいくつかをオフするのがこのオプションの役割みたいです。先ほどの // の1行コメントなどは、その拡張機能の例の一つみたいです。-ansi をコンパイル時に指定すれば少なくとも//などはエラーにしてくれるみたいですが、完璧なANSI-Cだと思うなよ、と。

-pedantic

これまたよくわからんオプションです。名前からして不穏。「衒学的な」デス。ANSIの規格準拠に目くじらを立ててここで警告ださないのはgccは不穏当だなどと批判する人がいたのでしょうか。仕方がないので、警告だせ、と書かれているところだけ警告出してやるぜという感じ。これまた完璧なANSI-Cを保証するものにあらず。

実例2つ

元よりCコンパイラ素人、拙いながらも -ansiと-pedanticでエラーや警告が出たりでなかったりするソース2点を書いてみましたぞ。

まずオプションつけないと普通にビルドできるけど、オプションつけると差しさわりのあるサンプルソース main.c

// option -ansi test, errors found.
#include <stdio.h>
#include <stdlib.h>

#define abc(A, B) A##B

int xyz(int A, int B) {
    if (A < 0) {
        return 0;
    } else if (A < B) {
        return 1;
    }
    return B;
}

int ARY[4];
int a$b = 3;

int main(void)
{
    typeof(ARY[0]) X;
    printf("-ansi NG.\r\n");
    printf("a$b=%d\r\n", a$b);
    printf("abc=%d\r\n", abc(1, 2));
    X = xyz(1, 2);
    printf("xyz=%d\r\n", X);
    
    return 0;
}

念のため、オプションつけてもノーエラーで通るソース main_ansiok.c

/* option -ansi test, ok. */
#include <stdio.h>
#include <stdlib.h>

#define abc(A, B) A##B

int xyz(int A, int B) {
    if (A < 0) {
        return 0;
    } else if (A < B) {
        return 1;
    }
    return B;
}

int ARY[4];
int a_b = 3;

int main(void)
{
    __typeof__(ARY[0]) X;
    printf("-ansi OK.\r\n");
    printf("a_b=%d\r\n", a_b);
    printf("abc=%d\r\n", abc(1, 2));
    X = xyz(1, 2);
    printf("xyz=%d\r\n", X);
    
    return 0;
}
ビルドと実行

まずは main.c から。普通にビルド成功。ansiNGexecOK

実行結果が以下に。ansiNGexecRESULT
しかし -ansi オプションつけてみるとansiNGansi

さらに-pedanticオプションをつけてみるとansiNGansiPedantic

ピンク色の警告が追加されました。

一方、main_ansiok.c は オプション付けずに普通にビルドしたときに以下のように実行可能であることは勿論、

-ansiオプションだけつけても、ansiOKansi

さらに -pedantic オプションを追加してもノーエラー、ノー警告です。

ansiOKansiPedantic

まあ、お作法はいろいろ、オプションもいろいろ、か。

オプション沼(15) インクルードガードの闇?-Wno-import、#importは非推奨 へ戻る

オプション沼(17) どしたら差が出る?gccの-fno-builtinオプション へ進む