foo(void)とfoo(void *)


9

機能的および構文的に言えば、プロトタイプの関数とには違いがint foo(void)ありint foo(void *)ますか?

私は、例えば、違いを知って、int bar(int)そしてint bar(int *)-そのうちの一つがintを探している、と他のはint型のポインタを探しています。void同じように動作?


関連する質問への回答:stackoverflow.com/a/1043209/434551
R Sahu


何より面白いかもしれすることとの間の差であるfoo(void)foo()
Maxim Egorushkin

回答:


10

ソフトウェアエンジニアリングに関するこの回答 から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がキャストを明示的に呼び出すのは、キャストが定義により明示的な変換であるため、冗長です。
eerorika

C / C ++の違いを反映して更新されました。お知らせいただきありがとうございます。
Nick Reed

4

foo(void) -パラメータなしの関数

foo(void *)- void *パラメータが1つの関数

なにvoid *?これは、型が指定されていないデータへの単なるポインタです。他のポインタ型にキャストできます

unsigned add(void *arr)
{
   unsigned *uarr = arr;
   return uarr[0] + uarr[1];
}

本質的な答えなので、それが最高の答えです。voidは実際には型ではない(type) vs. (type *)ので、これがカップルユニバースの例外であることを強調しておきます。
Roberto Caboni

2

機能的および構文的に言えば、プロトタイプがint foo(void)とint foo(void *)の関数には違いがありますか?

違いがあります:

int foo(void) 引数を受け入れない関数を宣言します。

int foo(void *)型の単一の引数を受け入れる関数を宣言しますvoid*

C ++では、int foo(void)と同等int foo()です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.