このステートメントは何をもたらすでしょうか?
void *p = malloc(sizeof(void));
編集:質問の延長。
GCC コンパイラで sizeof(void) が 1 を返す場合、1 バイトのメモリが割り当てられ、ポインタ p はそのバイトを指し、p++ は 0x2346 にインクリメントされますか? p が 0x2345 であるとします。*p ではなく、p について話しているのです。
このステートメントは何をもたらすでしょうか?
void *p = malloc(sizeof(void));
編集:質問の延長。
GCC コンパイラで sizeof(void) が 1 を返す場合、1 バイトのメモリが割り当てられ、ポインタ p はそのバイトを指し、p++ は 0x2346 にインクリメントされますか? p が 0x2345 であるとします。*p ではなく、p について話しているのです。
タイプvoid
にはサイズがありません。それはコンパイルエラーになります。同じ理由で、次のようなことはできません。
void n;
編集。驚いたことに、sizeof(void)
実際に実行するとGNUCでコンパイルされます。
$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out
1
ただし、C ++では、次のことは行いません。
$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out
<stdin>: In function 'int main()':
<stdin>:1: error: invalid application of 'sizeof' to a void type
<stdin>:1: error: 'printf' was not declared in this scope
GCCを使用していて、コンパイラ固有の拡張機能を削除するコンパイルフラグを使用していない場合は、sizeof(void)
1です。GCCには、それを行う非標準の拡張機能があります。
一般に、void
は不完全な型であり、不完全な型にsizeofを使用することはできません。
void
タイプの代わりになる場合もありますが、実際には値を保持できません。したがって、メモリ内にサイズはありません。aのサイズを取得することvoid
は定義されていません。
void
ポインタは、型指定されていないメモリへのポインタを意味する単なる言語構造です。
void のサイズを取得するのはGCC の拡張機能です。
sizeof()
不完全なタイプには適用できません。そしてvoid
、完成できない不完全なタイプです。
Cではsizeof(void) == 1
GCCですが、これはコンパイラに依存しているようです。
C ++では、次のようになります。
関数'intmain()': 2行目:エラー:void型への「sizeof」の無効な適用 -Wfatal-errorsが原因でコンパイルが終了しました。
質問の2番目の部分:sizeof(void *)!= sizeof(void)に注意してください。32ビットアーチでは、sizeof(void *)は4バイトであるため、それに応じてp ++が設定されます。ポインターがインクリメントされる量は、ポインターが指しているデータによって異なります。したがって、1バイト増加します。
ほとんどの C++ コンパイラは、取得しようとしたときにコンパイル エラーを発生させることを選択しましたsizeof(void)
。
C をコンパイルするとき、gcc は適合せずsizeof(void)
、1 として定義することを選択しました。奇妙に見えるかもしれませんが、理論的根拠があります。ポインター演算を行う場合、1 つの単位を追加または削除することは、サイズを指すオブジェクトを追加または削除することを意味します。したがって、1 として定義すると、バイト (型指定されていないメモリ アドレス) へのポインターとしてsizeof(void)
定義するのに役立ちます。void*
そうしないと、p+1 == p when
p isのようなポインター演算を使用して驚くべき動作をすることになりますvoid*
。このような void ポインターでのポインター演算は、c++ では許可されていませんが、gcc で C をコンパイルする場合は正常に機能します。
標準的に推奨される方法はchar*
、そのような目的 (バイトへのポインター) に使用することです。
sizeof を使用する場合の C と C++ の別の同様の違いは、次のような空の構造体を定義したときに発生します。
struct Empty {
} empty;
C コンパイラとして gcc を使用sizeof(empty)
すると 0 が返されます。g++ を使用すると、同じコードは 1 を返します。
この点で C と C++ の両方の標準が何を示しているかはわかりませんが、いくつかの空の構造体/オブジェクトのサイズを定義すると、参照管理で、異なる連続したオブジェクトへの 2 つの参照 (最初の参照が空) を回避するのに役立つと思います。同じ住所。参照がよく行われるように隠しポインタを使用して実装されている場合、異なるアドレスを確保するとそれらを比較するのに役立ちます。
しかし、これは、別の動作 (空のオブジェクト、POD でさえ少なくとも 1 バイトのメモリを消費する) を導入することによって、驚くべき動作 (参照のコーナー ケースの比較) を回避するだけです。
sizeof(void) 自体は意味をなさないかもしれませんが、ポインタ演算を行う場合は重要です。
例えば。
void *p;
while(...)
p++;
sizeof(void) が 1 と見なされる場合、これは機能します。sizeof(void) が 0 と見なされると、無限ループに陥ります。