web-dev-qa-db-ja.com

この場合、Cはsizeof(...)とsizeof ...を正しく処理しますか?

次のコードでは、test関数と_test2_関数は同等ですか?

_typedef int rofl;

void test(void) {
    rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
}

void test2(void) {
    rofl * rofl = malloc(sizeof *rofl); // Is the final rofl here the VARIABLE?
}
_

言い換えると:

  1. かっこがあるため、sizeof(rofl)roflrofltypeを正しく選択しますか?
  2. _sizeof *rofl_のroflは、括弧がlackであるため、roflvariableを正しく選択しますか?

注:これはばかげているように見える例ですが、実際には変数名と同じ型名を持っている場合があります。したがって問題。

38
ccoder987

どちらの場合も、最後のroflは変数名です。変数名は、表示されるとすぐにスコープに入ります。現在のスコープの残りの部分では、通常のコンテキストでの識別子(*)は常に変数名を意味します。

sizeof演算子は、名前ルックアップの特別なケースを導入しません。実際、識別子の隠された意味を使用する言語構造はありません。

実際には、型と変数名に同じ識別子を使用しないことをお勧めします。


(*)識別子には、ラベル名、構造体タグ、構造体メンバーの3つの特別なコンテキストがあります。ただし、他のすべてのコンテキストでは、すべての識別子が共通の名前空間を共有します。型名、変数名、関数名などに固有の識別子名前空間はありません。

これは不自然な例です:

typedef int A;      // "A" declared as ordinary identifier, meaning a type name

struct A { A A; };  // "A" declared as struct tag and member name -- OK as these are three different name spaces. Member type is "int"

A main()            // int main() - ordinary context
{
    struct A A();   // "A" declared as ordinary identifier, meaning a function name; hides line 1's A
    // A C;         // Would be error: ordinary A is a function now, not a typedef for int
    struct A B;     // OK, struct tags have separate name space
    A:+A().A;       // OK, labels and struct members have separate name space, calls function
    goto A;         // OK, label name space
}
27
M.M

この宣言では

rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?

変数の名前roflはtypedef名roflを隠します。したがって、sizeof演算子では、式がint *型であるポインタroflが使用されます。

同じことがこの宣言にも当てはまります

rofl * rofl = malloc(sizeof *rofl); 

ただし、typedef名roflの型、つまりroflの型を持つ逆参照ポインタintを含む式が使用されています。

このC文法の定義が原因で混乱が生じているようです

sizeof unary-expression
sizeof ( type-name )

ただし、unary-expressionは、括弧で囲まれた式である1次式にすることができます。

C標準から(6.5.1一次式)

primary-expression:
    ( expression )
    //...

したがって、たとえば、xが変数の名前である場合、次のいずれかを記述できます。

sizeof x 

または

sizeof( x )

わかりやすくするために、sizeof演算子と1次式の間に空白を挿入できます

sizeof    ( x )
operator  primary expression

比較のために、別の単項演算子、単項プラスを検討してください。あなたは例えば書くことができます

+ x

または

+ ( x )

ここで、単項プラスを別の単項演算子sizeofに置き換えます。

名前の非表示に関しては、名前にタグのキーワードが含まれているため、構造体、共用体、および列挙体の問題は解決できます。

例えば

typedef struct rofl { int x; } rofl;

void test(void) {
    rofl * rofl = malloc(sizeof( struct rofl));
}

Sizeof演算子を使用したこの関数では、type-name struct roflが使用されています。

この機能にいる間

typedef struct rofl { int x; } rofl;

void test(void) {
    rofl * rofl = malloc(sizeof( rofl));
}

sizeof演算子では、変数roflを持つ1次式が使用され、タイプはstruct rofl *です。

13

「選択」または「選択」は含まれません。どちらの場合も、スコープルールにより、各rofl呼び出しで参照されるsizeofは、型ではなく変数です。変数は内部スコープで宣言されるため、型名をオーバーライドします。 sizeof演算子への引数の括弧は関係ありません。

幸運を祈ります。