Verschil tussen sizeof(char) en sizeof(char *)

Ik vraag me af of er een verschil is tussen sizeof(char) en sizeof(char *) :

char *s;
s = malloc(sizeof(char*)*len + 1);
char *s;
s = malloc(sizeof(char)*len + 1);

Is dit hetzelfde?


Antwoord 1, autoriteit 100%

charis een teken en sizeof(char)is gedefinieerd als 1. (N15706.5.3.4 De grootte van en _Alignof-operators, paragraaf 4)

char*is een pointer naareen teken en sizeof(char*)is afhankelijk van de omgeving. Het is meestal 4 in een 32-bits omgeving en 8 in een 64-bits omgeving.

In een typische omgeving waar sizeof(char*) > sizeof(char), malloc(sizeof(char*)*len + 1)zal (in ieder geval proberen) meer geheugen toe te wijzen dan malloc(sizeof(char)*len + 1)als lenklein genoeg is om geen integer overflow te veroorzaken.


Antwoord 2

Ze zijn niet hetzelfde. char*is een verwijzing naar een char. Je interpreteert char*op zichzelf verkeerd als een “type”.

charis grootte 1 en char*, wat een pointer is, kan 4 zijn op 32-bits systemen en 8 op 64-bits systemen (op voorwaarde dat het is gecompileerd volgens het systeem ).


Antwoord 3

Allereerst is het een goed voorbeeld dat laat zien dat mallocgecast moet wordenin C.

Overweeg dit codefragment

char *s;
s = malloc(sizeof(char*)*len + 1);

Bij het lezen is het niet duidelijk wat de auteur van de code ging doen. Wilde hij een tekenreeks van het type char[sizeof( char * ) *len + 1]toewijzen of wilde hij een reeks van het type char *[len + 1]of char *[len]maar een fout gemaakt?

Het is duidelijk dat een dergelijke uitdrukking in de malloc malloc(sizeof(char*)*len + 1)lezers in verwarring brengt en foutgevoelig is.

Maar als de auteur bijvoorbeeld schreef

s = ( char ** )malloc(sizeof(char*)*len + 1);

dan zou de compiler een diagnostisch bericht rapporteren. Of als hij schreef

s = ( char * )malloc(sizeof(char*)*len + 1);

dan zou het duidelijker zijn over de bedoeling van de auteur.

Bovendien kunnen er tussen de pointer-declaratie en de instructie waaraan het geheugen is toegewezen veel schermen met regels van de code zijn en in het slechtste geval kan de declaratie zich in het ene bestand bevinden terwijl de toewijzingsinstructie in het andere bestand.

char *s;
//....
//....
s = malloc(sizeof(char*)*len + 1);

Zonder de mallocte casten, is het erg tijdrovend om zo’n code te lezen.

Wat betreft de vraag. sizeof( char )is altijd gelijk aan 1 en is niet afhankelijk van de gebruikte omgeving. Terwijl sizeof( char * )implementatie-gedefinieerd is en gelijk kan zijn aan bijvoorbeeld 2, 4 of 8 bytes of zelfs iets anders.

Dus deze uitdrukking in de malloc malloc(sizeof(char)*len + 1)is volledig gelijk aan de uitdrukking in deze aanroep malloc( len + 1)Nogmaals het is niet duidelijk om deze verklaring te zien

s = malloc(len + 1);

welk type objecten dynamisch wordt toegewezen. Of er nu een reeks tekens is toegewezen of bijvoorbeeld een tweedimensionale reeks tekens zoals char ( * )[2]en len + 1– is een even getal en 1 wordt toegevoegd aan lenomdat lenoneven of even is, er is een object van een ander type toegewezen.

Dus het is veel beter om te schrijven

s = ( char * )malloc(sizeof(char)*len + 1);
    ^^^^^^^^^

Deze code is zelf gedocumenteerd en maakt het gemakkelijk te lezen.

Dus het verschil tussen deze twee uitspraken

s = malloc(sizeof(char)*len + 1);
s = malloc(sizeof(char*)*len + 1);

is dat de eerste instructie een geheugenuitbreiding van len + 1bytes toewijst, terwijl de tweede instructie een omvang van sizeof( char * ) * len + 1bytes toewijst waar sizeof( char * )is behalve in zeer en zeer zeldzame gevallen groter dan 1.

Other episodes