次のコードでは、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?
}
_
言い換えると:
sizeof(rofl)
のrofl
はrofl
typeを正しく選択しますか?sizeof *rofl
_のrofl
は、括弧がlackであるため、rofl
variableを正しく選択しますか?注:これはばかげているように見える例ですが、実際には変数名と同じ型名を持っている場合があります。したがって問題。
どちらの場合も、最後の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
}
この宣言では
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 *
です。
「選択」または「選択」は含まれません。どちらの場合も、スコープルールにより、各rofl
呼び出しで参照されるsizeof
は、型ではなく変数です。変数は内部スコープで宣言されるため、型名をオーバーライドします。 sizeof
演算子への引数の括弧は関係ありません。
幸運を祈ります。