foo (vuoto) vs foo (vuoto *)


9

Funzionalmente e sintatticamente, c'è una differenza tra una funzione il cui prototipo è int foo(void)eint foo(void *) ?

Conosco la differenza tra, per esempio, int bar(int)e int bar(int *)- uno di loro sta cercando un int e l'altro sta cercando un puntatore int. Si voidcomporta allo stesso modo?


Una risposta a una domanda correlata: stackoverflow.com/a/1043209/434551 .
R Sahu,


Ciò che potrebbe essere più interessante è la differenza tra foo(void)e foo().
Maxim Egorushkin,

Risposte:


10

Da questa risposta sull'ingegneria del software, void viene trattato in modo speciale a seconda di come viene utilizzato. In Ce C++, voidè usato per indicare un'assenza di un tipo di dati, mentre void *è usato per indicare un puntatore che punta ad alcuni dati / spazi in memoria che non hanno un tipo. void *non può essere dereferenziato da solo e deve essere prima lanciato su un altro tipo. Questo cast non deve essere esplicito in C, ma deve essere esplicito in C++. (Ecco perché non lanciamo il valore di ritorno di malloc, che è void *.)


Se utilizzato con una funzione come parametro, voidindica l'assenza totale di qualsiasi parametro ed è l'unico parametro consentito. Il tentativo di utilizzare void come un tipo variabile o includere altri argomenti provoca un errore del compilatore:

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

Allo stesso modo è impossibile dichiarare una variabile con 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;

voidcome valore di ritorno per una funzione indica che non verranno restituiti dati. Poiché è impossibile dichiarare una variabile di tipo void, è impossibile catturare il valore di ritorno di una voidfunzione, anche con un puntatore vuoto.

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

Il senza nome void *è un caso diverso. Un puntatore vuoto indica un puntatore a una posizione in memoria, ma non indica il tipo di dati in quel puntatore. (Questo è usato per ottenere il polimorfismo in C , come con la funzione qsort () .) Questi puntatori possono essere difficili da usare, tuttavia, poiché è molto facile lanciarli accidentalmente nel tipo sbagliato. Il codice seguente non genera errori del compilatore C, ma comporta un comportamento indefinito:

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

Il seguente codice, tuttavia, è perfettamente legale; il cast da e verso un puntatore vuoto non cambia mai il valore che contiene.

#include <stdio.h>

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

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

47.200000

Come parametro di funzione, void *indica che il tipo di dati sul puntatore in cui si sta passando non è noto e spetta a te, il programmatore, gestire correttamente tutto ciò che si trova in quella posizione di memoria. Come valore restituito, void *indica che il tipo di dati restituiti non è noto o non è tipizzato e deve essere gestito dal programma.

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 in un prototipo di funzione significa "nessun dato" e indica nessun valore di ritorno o nessun parametro, void *in un prototipo di funzione significa "i dati nel puntatore a cui viene fornita questa funzione non hanno un tipo noto" e indica un parametro o un valore di ritorno il cui puntatore deve essere castato su un tipo diverso prima di poter utilizzare i dati sul puntatore.


void * ... must be cast to another type first, but may be done so without an explicit cast.Non vero in C ++. In C ++ il modulo di conversione void*deve essere esplicito. PS che chiama un cast esplicito è ridondante poiché il cast è per definizione una conversione esplicita.
Eerorika,

Aggiornato per riflettere le differenze C / C ++, grazie per avermelo fatto notare!
Nick Reed,

4

foo(void) - funzione senza parametri

foo(void *)- funzione con un void *parametro

Che cosa è void *? È solo il puntatore ai dati senza un tipo specificato. Può essere trasmesso a qualsiasi altro tipo di puntatore

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

Risposta essenziale, quindi è la migliore. Vorrei solo sapere come questa sia un'eccezione nell'universo delle (type) vs. (type *)coppie perché il vuoto non è in realtà un tipo.
Roberto Caboni,

2

Funzionalmente e sintatticamente, c'è una differenza tra una funzione il cui prototipo è int foo (void) e int foo (void *)?

C'è una differenza:

int foo(void) dichiara una funzione che non accetta argomenti.

int foo(void *) dichiara una funzione che accetta un singolo argomento di tipo void* .

In C ++, int foo(void)è equivalente a int foo().

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.