sizeof(int)が正しいのに、sizeof intが間違っているのはなぜですか?


96

私たちは、それが知っているsizeof任意のデータ型と式のサイズを計算するために使用される演算子であり、かつオペランドが式の場合は、括弧を省略することができます。

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

sizeof他の人が正しい間、の最初の使用法は間違っています。

gccを使用してコンパイルすると、次のエラーメッセージが表示されます。

main.c:5:9: error: expected expression before int

私の質問は、C標準がこの種の操作を許可しない理由です。ウィルsizeof int任意のあいまいさを引き起こしますか?


5
おかしなことに、括弧なしですべての式が受け入れられるわけではありませんsizeof (int)a
Fred Foo

2
@MikkelK .: OPは、マークされた回答で言及されている引用をすでに知っている標準的な引用の背後にある推論を求めています。
Alok Save

2
@Lundin:実際にコンパイルsizeof +(int)aする*&よりも優れています;-)
Steve Jessop

2
@SteveJessopああ、それは左辺値ではありません。Embarcadero C ++でコンパイルされましたが、奇妙なことに十分です。とにかく、たった今、単項+演算子の使用法を見つけたと思います!これは、Cプログラミングの歴史の中で初めてのことです:)
Lundin

2
@Lundin:まだ単項に注意する必要があり+ます。たとえば、sizeof +(char)a == sizeof(int)整数の昇格のため、サイズを取得しようとしている式についてまったく心配がない場合は、括弧を入れるだけでエラーが発生しにくくなります。それで、私はそれを「使用」と呼ぶかどうかはわかりませんが、使用したことは認めます...
Steve Jessop

回答:


101

以下はあいまいになる可能性があります。

sizeof int * + 1

つまり(sizeof (int*)) + 1、または(sizeof(int)) * (+1)

明らかに、C言語は曖昧さを解決するためのルールを導入できたかもしれませんが、なぜそれが気にならなかったのか想像できます。現状の言語では、型指定子が式で「ネイキッド」に表示されることはないため、その秒*が型または算術演算子の一部であるかどうかを解決するためのルールは必要ありません。

既存の文法は、の潜在的な曖昧さをすでに解決していますsizeof (int *) + 1。それは(sizeof(int*))+1ありません sizeof((int*)(+1))

C ++には、関数スタイルのキャスト構文で解決するためのやや類似した問題があります。あなたは書くことができint(0)、あなたは書くことができますが、あなたは書くtypedef int *intptr; intptr(0);ことができませんint*(0)。その場合の解決策は、「ネイキッド」タイプは単純なタイプ名でなければならないということです。スペースが含まれている可能性のある古いタイプIDや末尾の句読点だけではありません。たぶんsizeof、同じ制限で定義されたのかもしれませんが、私にはわかりません。


1
C ++はnew int*(X)、新しい演算子が型である可能性のある最長の文字列を取ることをC ++が指定しなかった場合、あいまいになります。したがって、C ++では、sizeofで同じにすることができたと思います。しかし、C ++ではsizeof int()、どちらが曖昧だったと言えるでしょう(型または値がintで初期化されていますか?)。
Johannes Schaub-litb 2012年

@ JohannesSchaub-litb:うーん、おそらくC ++では、解析が可能な場合は型が優先され、そうでない場合は式であると言えるでしょう。あいまいさは解決されますが、sizeof int()形式が正しくないoperator()ため(「いいえsize_t」)、これは歓迎されないと思います!
スティーブジェソップ2012年

32

C99標準から

6.5.3.4.2 オペレータは、発現またはタイプの括弧名前であってもよい、そのオペランドのサイズ(バイト単位)をもたらします。
sizeof

あなたの場合int、式も括弧で囲まれた名前もありません。


10
なぜこれが7つの賛成票を獲得するのか理解できません。削除された3つの回答と同様に、ルールが存在する理由を説明するのではなく、ルールを繰り返します。
Fred Foo

7
@larsmans、はい、同意します。それはルールを繰り返し続けていますが、少なくとも、それは承認された読書の一部を提供します。
Yishu Fang

3
@larsmans C99で下されたすべての決定を正当化しようと試み始めたら、一年中ここにいるでしょう。標準を引用することは、この議論を締めくくるのと同じくらい良い方法です。
ペリー

1
@ペリー:この種の質問が気に入らない場合は、投票して質問をクローズすることができます。
Fred Foo

4
C ++の非実践者として、私もこの答えを理解していますが、英語を読んで理解できるのであれば、何が問題なのかわかりません。
ケブ2012年

6

Cでsizeof演算子を使用するには2つの方法があります。構文は次のとおりです。

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

タイプをオペランドとして使用する場合は常に、言語の構文定義によって括弧が必要です。式でsizeofを使用する場合は、括弧は必要ありません。

C標準は、式でそれを使用する場合の1つの例を示しています。

sizeof array / sizeof array[0]

ただし、一貫性を保つため、および演算子の優先順位に関連するバグを回避するために、状況に関係なく常に()を使用することをお勧めします。


@ JohannesSchaub-litb C標準委員会がC90標準を指定したときにC標準委員会がどのように推論したかについての根拠は提供しないことに同意します。質問する必要があります...根拠なしで回答しますが、構文は6.5.3で指定されているため、Cでは許可されません。OPはまた違いに気づいていないように見えたsizeof expressionし、sizeof(type)この答えで説明されています、。
2012年

(記録のために、私はC90とC11の両方の根拠を読んだだけで、どちらも説明を提供していませんでした。)
Lundin

必要な理由はないのではないかと思います。これは、元のCデザイナーが決定した方法にすぎません。たぶん、それは初期のパーサーにとって物事をより簡単にしました。typedefと変数が同じ名前空間を共有するという事実についての回答を投稿しようとしましたが、これは最初の構文を許可することを妨げるものではありません。かっこがない場合は変数を優先し、存在する場合は型を優先し、名前が曖昧でない場合はどちらの形式でも使用できるという構文解析ルールが必要です。変更する必要がないので、標準化委員会はそれをそのままにしました。
Barmar 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.