コンパイラコースのセマンティック分析を行っているときに、紛らわしいケースに遭遇しました。
#include <stdio.h>
int a = "abcd"[2];
int main()
{
char b = "abcd"[2];
printf("%d\n%c\n", a, b);
return 0;
}
GCCは、変数「a」に対して「エラー:初期化要素が定数ではありません」と言います。
どうして?
C言語では、グローバル変数の初期化子が定数式である必要があります。この背後にある動機は、コンパイラがコンパイル時に式を計算し、計算された値を生成されたオブジェクトファイルに書き込むことができるようにすることです。
C標準は、定数式とは何かに関する特定の規則を提供します。
- 整数定数式117)は整数型であり、整数定数、列挙定数、文字定数、
sizeof
結果が整数定数である_Alignof
式、式、およびキャストの直接のオペランドである浮動定数であるオペランドのみを持つものとします。整数定数式のキャスト演算子は、sizeof
or_Alignof
演算子のオペランドの一部を除いて、算術型を整数型にのみ変換します。- イニシャライザの定数式には、より広い範囲が許可されます。このような定数式は、次のいずれかであるか、評価されます。
- 算術定数式、
- ヌルポインタ定数、
- アドレス定数、または
- 完全なオブジェクトタイプのアドレス定数プラスまたはマイナス整数定数式。
ご覧のとおり、配列アクセス式またはポインター逆参照を含むケースはありません。したがって"abcd"[2]
、標準による定数式としての資格はありません。
現在、標準には次のようにも書かれています。
- 実装は、他の形式の定数式を受け入れる場合があります。
したがって"abcd"[1]
、定数式として許可することは標準に違反しませんが、許可されることも保証されません。
したがって、コンパイラで許可するかどうかはあなた次第です。どちらの方法でも標準に準拠します(ただし、isConstantExpression
チェックで別のケースが必要であり、コンパイル時に式を実際に評価できる必要があるため、許可するとより多くの作業が必要になるため、許可しないことにします)。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加