機能的および構文的に言えば、プロトタイプの関数とには違いがint foo(void)
ありint foo(void *)
ますか?
私は、例えば、違いを知って、int bar(int)
そしてint bar(int *)
-そのうちの一つがintを探している、と他のはint型のポインタを探しています。void
同じように動作?
foo(void)
とfoo()
。
機能的および構文的に言えば、プロトタイプの関数とには違いがint foo(void)
ありint foo(void *)
ますか?
私は、例えば、違いを知って、int bar(int)
そしてint bar(int *)
-そのうちの一つがintを探している、と他のはint型のポインタを探しています。void
同じように動作?
foo(void)
とfoo()
。
回答:
ソフトウェアエンジニアリングに関するこの回答 から、void
その使用方法に応じて特別に扱われます。C
及びC++
、void
示すために使用され、データ型が存在しないことを一方void *
示すために使用されるタイプを持っていないメモリ内の一部のデータ/スペースを指すポインタを。 void *
単独で逆参照することはできません。最初に別の型にキャストする必要があります。このキャストはで明示的である必要はありませんが、で明示的である必要C
がありますC++
。(これが、mallocの戻り値であるをキャストしない理由ですvoid *
。)
関数をパラメーターとして使用する場合、パラメーターvoid
がまったく存在しないことを意味し、許可される唯一のパラメーターです。変数型のようにvoidを使用したり、他の引数を含めようとすると、コンパイラエラーが発生します。
int foo(void, int); //trying to use "void" as a parameter
int bar(void baz); //trying to use "void" as an argument's type
main.c:1:8: error: 'void' must be the first and only parameter if specified
int foo(void, int);
^
main.c:2:14: error: argument may not have 'void' type
int bar(void baz);
^
同様に、typeで変数を宣言することは不可能ですvoid
:
int main(void) {
void qux; //trying to create a variable with type void
}
main.c:5:8: error: variable has incomplete type 'void'
void qux;
void
関数の戻り値は、データが返されないことを示します。typeの変数を宣言するvoid
ことは不可能であるため、voidポインターを使用しても、void
関数の戻り値をキャッチすることは不可能です。
void foo(int i) { return; }
int main(void) {
void *j;
j = foo(0);
return 0;
}
main.c:5:5: error: assigning to 'void *' from
incompatible type 'void'
j = foo(0);
^ ~~~~~~
タイプレスvoid *
は別のケースです。voidポインターは、メモリ内の場所へのポインターを示しますが、そのポインターのデータ型を示しません。(これは、qsort()関数などのCでポリモーフィズムを実現するために使用されます。)ただし、これらのポインターは、誤って間違った型にキャストすることが非常に簡単であるため、使用するのが難しい場合があります。以下のコードはC
、コンパイラエラーをスローしませんが、未定義の動作になります。
#include <stdio.h>
int main(void) {
double foo = 47.2; //create a double
void *bar = &foo; //create a void pointer to that double
char *baz = bar; //create a char pointer from the void pointer, which
//is supposed to hold a double
fprintf(stdout, "%s\n", baz);
}
ただし、次のコードは完全に合法です。voidポインタへのキャストやvoidポインタからのキャストによって、保持される値が変更されることはありません。
#include <stdio.h>
int main(void) {
double foo = 47.2;
void *bar = &foo;
double *baz = bar;
fprintf(stdout, "%f\n", *baz);
}
47.200000
関数パラメーターとして、void *
渡すポインターのデータ型が不明であることを示します。そのメモリー位置にあるものを適切に処理するかどうかは、プログラマー次第です。戻り値として、返さvoid *
れるデータのタイプが不明であるかタイプなしであり、プログラムで処理する必要があることを示します。
int quux(void *); //a function that receives a pointer to data whose type is not known, and returns an int.
void *quuz(int); //a function that receives an int, and returns a pointer to data whose type is not known.
void
関数プロトタイプのtl; drは、「データなし」を意味し、戻り値またはパラメーターがないことを示しvoid *
、関数プロトタイプでは、「この関数が指定されたポインターのデータには既知のタイプがない」ことを意味し、パラメーターまたは戻り値を示しますポインターのデータを使用する前に、そのポインターを別の型にキャストする必要があります。
void * ... must be cast to another type first, but may be done so without an explicit cast.
C ++では当てはまりません。C ++では、変換形式void*
は明示的でなければなりません。PSがキャストを明示的に呼び出すのは、キャストが定義により明示的な変換であるため、冗長です。
foo(void)
-パラメータなしの関数
foo(void *)
- void *
パラメータが1つの関数
なにvoid *
?これは、型が指定されていないデータへの単なるポインタです。他のポインタ型にキャストできます
unsigned add(void *arr)
{
unsigned *uarr = arr;
return uarr[0] + uarr[1];
}
(type) vs. (type *)
ので、これがカップルユニバースの例外であることを強調しておきます。