foo (batal) vs foo (batal *)

9

Secara fungsional dan sintaksis, apakah ada perbedaan antara fungsi yang prototipe-nya int foo(void)dan int foo(void *)?

Saya tahu perbedaan antara, misalnya, int bar(int)dan int bar(int *)- salah satunya mencari int, dan yang lainnya mencari pointer int. Apakah voidberperilaku dengan cara yang sama?

Nick Reed
sumber
Jawaban untuk pertanyaan terkait: stackoverflow.com/a/1043209/434551 .
R Sahu
Yang mungkin lebih menarik adalah perbedaan antara foo(void)dan foo().
Maxim Egorushkin

Jawaban:

10

Dari jawaban ini di Rekayasa Perangkat Lunak, void diperlakukan khusus tergantung pada bagaimana itu digunakan. In Cdan C++, voiddigunakan untuk menunjukkan tidak adanya tipe data, sedangkan void *digunakan untuk menunjukkan pointer yang menunjuk ke beberapa data / ruang dalam memori yang tidak memiliki tipe. void *tidak dapat disereferensi sendiri, dan harus dilemparkan ke tipe lain terlebih dahulu. Pemeran ini tidak perlu eksplisit dalam C, tetapi harus eksplisit dalam C++. (Inilah sebabnya kami tidak memberikan nilai pengembalian malloc, yaitu void *.)


Ketika digunakan dengan fungsi sebagai parameter, voidberarti tidak adanya parameter apa pun, dan hanya parameter yang diizinkan. Mencoba menggunakan kekosongan seperti tipe variabel atau menyertakan argumen lain menghasilkan kesalahan kompilator:

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);
             ^

Tidak mungkin untuk mendeklarasikan variabel dengan tipe 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;

voidsebagai nilai balik untuk fungsi menunjukkan tidak ada data yang akan dikembalikan. Karena tidak mungkin untuk mendeklarasikan variabel tipe void, tidak mungkin untuk menangkap nilai balik suatu voidfungsi, bahkan dengan pointer kosong.

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);
    ^ ~~~~~~

Jenis void *yang berbeda adalah kasus yang berbeda. Pointer batal menunjukkan pointer ke lokasi di memori, tetapi tidak menunjukkan tipe data pada pointer itu. (Ini adalah yang digunakan untuk mencapai polimorfisme dalam C , seperti dengan fungsi qsort () .) Pointer ini bisa rumit untuk digunakan, karena sangat mudah untuk secara tidak sengaja melemparkannya ke tipe yang salah. Kode di bawah ini tidak akan memasukkan kesalahan kompilator C, tetapi menghasilkan perilaku yang tidak terdefinisi:

#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);
}

Namun, kode berikut ini sepenuhnya legal; casting ke dan dari void pointer tidak pernah mengubah nilai yang dimilikinya.

#include <stdio.h>

int main(void) {
  double foo = 47.2;
  void *bar = &foo;
  double *baz = bar;

  fprintf(stdout, "%f\n", *baz);
}

47.200000

Sebagai parameter fungsi, void *menunjukkan bahwa tipe data pada pointer yang Anda lewati tidak diketahui, dan terserah Anda, pemrogram, untuk menangani dengan baik apa pun yang ada di lokasi memori itu. Sebagai nilai balik, void *menunjukkan bahwa jenis data yang dikembalikan tidak diketahui atau tidak bertipe, dan harus ditangani oleh program.

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.

tl; dr void dalam prototipe fungsi berarti "tidak ada data" dan menunjukkan tidak ada nilai balik atau tidak ada parameter, void *dalam prototipe fungsi berarti "data pada penunjuk fungsi ini diberikan tidak memiliki tipe yang dikenal" dan menunjukkan parameter atau nilai balik penunjuk yang harus dilemparkan ke jenis yang berbeda sebelum data di penunjuk dapat digunakan.

Nick Reed
sumber
void * ... must be cast to another type first, but may be done so without an explicit cast.Tidak benar dalam C ++. Dalam C ++ bentuk konversi void*harus eksplisit. PS yang memanggil pemain eksplisit tidak ada karena pemain menurut definisi adalah konversi eksplisit.
eerorika
Diperbarui untuk mencerminkan perbedaan C / C ++, terima kasih telah memberi tahu saya!
Nick Reed
4

foo(void) - berfungsi tanpa parameter

foo(void *)- berfungsi dengan satu void *parameter

Apa void *? Ini hanya pointer ke data tanpa tipe yang ditentukan. Itu dapat dicor ke jenis pointer lainnya

unsigned add(void *arr)
{
   unsigned *uarr = arr;
   return uarr[0] + uarr[1];
}
P__J__
sumber
Jawaban penting, jadi itu yang terbaik. Saya hanya ingin melihat bagaimana ini merupakan pengecualian di (type) vs. (type *)alam semesta pasangan karena kekosongan sebenarnya bukan tipe.
Roberto Caboni
2

Secara fungsional dan sintaksis, apakah ada perbedaan antara fungsi yang prototipenya adalah int foo (void) dan int foo (void *)?

Ada perbedaan:

int foo(void) mendeklarasikan fungsi yang tidak menerima argumen.

int foo(void *)mendeklarasikan fungsi yang menerima argumen tipe tunggal void*.

Dalam C ++, int foo(void)sama dengan int foo().

eerorika
sumber