Hoe groot is de leegte?

Wat zou deze verklaring opleveren?

void *p = malloc(sizeof(void));

Bewerken: een uitbreiding op de vraag.

Als sizeof(void) 1 oplevert in de GCC-compiler, dan wordt 1 byte geheugen toegewezen en wijst de pointer p naar die byte en zou p++ worden verhoogd naar 0x2346? Stel dat p 0x2345 is. Ik heb het over p en niet over *p.


Antwoord 1, autoriteit 100%

Het type voidheeft geen grootte; dat zou een compilatiefout zijn. Om dezelfde reden kun je iets niet doen als:

void n;

BEWERKEN.
Tot mijn verbazing compileert sizeof(void)eigenlijk doetin GNU C:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 
1

In C++ echter niet:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out 
<stdin>: In function 'int main()':
<stdin>:1: error: invalid application of 'sizeof' to a void type
<stdin>:1: error: 'printf' was not declared in this scope

Antwoord 2, autoriteit 69%

Als je GCC gebruikt en geen compilatievlaggen gebruikt die compilerspecifieke extensies verwijderen, dan is sizeof(void)1. GCC heeft een niet-standaard extensiedie dat doet.

Over het algemeen is voideen onvolledig type en kunt u sizeof niet gebruiken voor onvolledige typen.


Antwoord 3, autoriteit 26%

Hoewel voidop zijn plaats kan staan ​​voor een type, kan het eigenlijk geen waarde bevatten. Daarom heeft het geen grootte in het geheugen. Het verkrijgen van de grootte van een voidis niet gedefinieerd.

Een voidpointeris gewoon een taalconstructie die een verwijzing naar ongetyptgeheugen betekent.


Antwoord 4, autoriteit 23%

voidheeft geen grootte. In zowel C als C++ is de uitdrukking sizeof (void)ongeldig.

In C, onder vermelding van N15706.5 .3.4 paragraaf 1:

De operator sizeofmag niet worden toegepast op een uitdrukking die:
heeft functietype of een onvolledig type, tussen haakjes geplaatste naam van
een dergelijk type, of naar een uitdrukking die een bitveldlid aanduidt.

(N1570 is een concept van de ISO C-norm van 2011.)

voidis een onvolledig type. Deze paragraaf is een beperking, wat betekent dat elke conforme C-compiler elke overtreding ervan moet diagnosticeren. (Het diagnostische bericht kan een niet-fatale waarschuwing zijn.)

De C++ 11-standaard heeft zeer vergelijkbare bewoordingen. Beide edities werden gepubliceerd nadat deze vraag was gesteld, maar de regels gaan terug naar de ANSI C-standaard uit 1989 en de vroegste C++-standaarden. De regel dat voideen onvolledig type is waarop sizeofniet mag worden toegepast, gaat zelfs zo ver terug als de introductie van voidin de taal.

gcc heeft een extensiedie sizeof (void)behandelt als 1. gcc is standaard geen conforme C-compiler, dus in de standaardmodus waarschuwt het niet over sizeof (void). Dergelijke extensies zijn zelfs toegestaan ​​voor volledig conforme C-compilers, maar de diagnose is nog steeds vereist.


Antwoord 5, autoriteit 18%

De grootte van leegte nemen is een GCC-extensie.


Antwoord 6, autoriteit 10%

sizeof()kan niet worden toegepast op onvolledige typen. En voidis een onvolledig type dat niet kan worden ingevuld.


Antwoord 7, autoriteit 5%

In C, sizeof(void) == 1in GCC, maar dit lijkt af te hangen van je compiler.

In C++ krijg ik:

In functie 'int main()': 
Regel 2: fout: ongeldige toepassing van 'sizeof' op een void-type
compilatie beëindigd vanwege -Wfatal-fouten.

Antwoord 8

Op het tweede deel van de vraag: Merk op dat sizeof(void *)!= sizeof(void).
Op een 32-bits boog is sizeof(void *) 4 bytes, dus p++ zou dienovereenkomstig worden ingesteld. De hoeveelheid waarmee een aanwijzer wordt verhoogd, is afhankelijk van de gegevens waarnaar deze verwijst. Het wordt dus met 1 byte verhoogd.


Antwoord 9

De meeste C++-compilers kozen ervoor om een ​​compileerfout te genereren bij het ophalen van sizeof(void).

Bij het compileren van C voldoet gcc niet en koos ervoor om sizeof(void)te definiëren als 1. Het ziet er misschien vreemd uit, maar heeft een reden. Wanneer u aanwijzerberekeningen uitvoert, betekent het toevoegen of verwijderen van één eenheid het toevoegen of verwijderen van het object dat op maat is gewezen. Dus het definiëren van sizeof(void)als 1 helpt om void*te definiëren als een pointer naar byte (ongetypt geheugenadres). Anders zou je verrassend gedrag vertonen bij het gebruik van aanwijzerberekeningen zoals p+1 == p whenp void*is. Een dergelijke rekenkundige rekenkunde op void-pointers is niet toegestaan ​​in c++, maar werkt prima bij het compileren van C met gcc.

De standaard aanbevolen manier zou zijn om char*voor dat soort doeleinden te gebruiken (pointer naar byte).

Een ander soortgelijk verschil tussen C en C++ bij het gebruik van sizeof treedt op wanneer u een lege struct definieert zoals:

struct Empty {
} empty;

Gcc gebruiken als mijn C-compiler sizeof(empty)retourneert 0.
Als u g++ gebruikt, geeft dezelfde code 1 terug.

Ik weet niet zeker wat de C- en C++-normen op dit punt zijn, maar ik geloof dat het definiëren van de grootte van enkele lege structs/objecten helpt bij het beheer van referenties om te voorkomen dat twee verwijzingen naar verschillende opeenvolgende objecten, waarvan de eerste leeg is , krijg hetzelfde adres. Als verwijzingen worden geïmplementeerd met behulp van verborgen verwijzingen, zoals vaak wordt gedaan, zal het helpen om ze met verschillende adressen te vergelijken.

Maar dit is slechts het vermijden van een verrassend gedrag (vergelijking van referenties in hoekletters) door een ander te introduceren (lege objecten, zelfs POD’s verbruiken minstens 1 byte geheugen).


Antwoord 10

Hoewel sizeof(void) op zichzelf misschien geen zin heeft, is het wel belangrijk als je aanwijsberekeningen maakt.

bijv.

void *p;
 while(...)
      p++;

Als sizeof(void) als 1 wordt beschouwd, werkt dit.
Als sizeof(void) als 0 wordt beschouwd, krijg je een oneindige lus.

Other episodes