C'è qualche motivo tecnico per digitare typedef void? [chiuso]

2

Nessuna opinione, per favore. C'è qualche ragione tecnica per typedef void?

La mia azienda corrente e il mio ultimo entrambi hanno typedef void XYZ_void; dove XYZ è il nome del progetto.

Posso capire un typedef per XYZ_INT , ma vuoto?

Qualcuno ha paura che la dimensione del vuoto possa essere diversa su un'altra architettura?!

    
posta Mawg 05.07.2016 - 09:28
fonte

1 risposta

3

Espansione del mio commento.

Ecco la lingua dello standard C online :

6.2.5 Types
...
19     The void type comprises an empty set of values; it is an incomplete object type that cannot be completed.
...
6.3.2.2 void

1     The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
...
6.5.3.4 The sizeof and _Alignof operators
...
1     The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member. The _Alignof operator shall not be applied to a function type or an incomplete type.

Quindi, in sostanza, void implica il valore no e la dimensione no (che non è uguale alla dimensione 0 ). Non puoi avere oggetti di tipo void . Quindi, la piattaforma non ha alcun ruolo qui.

Ora, void * potrebbe essere un problema diverso: la dimensione e la rappresentazione di un void * possono variare tra le implementazioni e in passato ho typedef d void * per scopi di astrazione.

Si noti che il dereferenziazione a void * ti lascia con un'espressione void , che come detto sopra non ha valore né dimensione; questo è il motivo per cui non puoi eseguire l'aritmetica del puntatore su void * e perché devi convertirlo in un tipo di puntatore diverso prima di tentare di dereferenziarlo.

Ora che ci penso, è un motivo tecnico per cui dovresti creare un void typedef - se hai bisogno di supportare sia un 1 antico Implementazione di K & R e implementazione post-C89. Il tipo di dati void non è stato introdotto fino allo standard del 1989; prima di allora, dovresti digitare una funzione per restituire int (o fare affidamento sulla digitazione implicita) e ignorare il valore restituito:

foo()  /* implicit int type */
{
  /* do something interesting */
  return 0;
}

bar() /* implicit int type */
{
  ...
  foo(); /* return value is ignored */
  return 0;
}

Quindi, supponiamo che tu voglia supportare quel codice su entrambe le piattaforme K & R e ANSI e vuoi essere buono e utilizzare la parola chiave void dove è disponibile, quindi il tuo codice ANSI viene letto come

void foo( void ) /* takes no parameters, returns no values */
{
  /* do something interesting */
}

void bar( void )
{
  ...
  foo();
  ...
}

Tranne che questo codice non verrà compilato sull'implementazione di K & R, poiché non riconosce la parola chiave void . Ancora peggio, void ha più significati nel codice sopra; indica che la funzione non restituisce un valore, e che non richiede parametri. Non possiamo semplicemente fare typedef int void , perché ciò spezzerebbe la dichiarazione dei parametri di funzione. Abbiamo anche bisogno del return 0 nel codice K & R, poiché una funzione int deve restituire un valore int .

Quindi, dovremmo fare qualcosa di simile:

#if !defined( __STDC__ ) || !defined( __STDC_VERSION__) /* Assume K&R implementation */
  typedef int XYZ_void;
  #define void 
  #define XYZ_void_return return 0
#else
  typedef void XYZ_void;
  #define XYZ_void_return
#endif

                               /* K&R equivalent      ANSI equivalent  */
XYZ_void foo( void )           /* int foo( )          void foo( void ) */
{                              /* {                   {                */
  ...                          /*   ...                 ...            */
  XYZ_void_return;             /*   return 0;                          */
}                              /* }                   }                */
                               /*                                      */
XYZ_void bar( void )           /* int bar( )          void bar( void ) */
{                              /* {                   {                */
  ...                          /*   ...                 ...            */
  foo();                       /*   foo();              foo();         */
  XYZ_void_return;             /*   return 0;                          */
}                              /* }                   }                */

Ho mostrato come viene elaborato il codice per entrambe le implementazioni K & R e ANSI. Ancora una volta, questo è il caso di utilizzo solo a cui riesco a pensare per creare un typedef per void .

  1. Almeno 27 anni.

risposta data 06.07.2016 - 18:22
fonte

Leggi altre domande sui tag