Hoe controleren we of een aanwijzer null-aanwijzer is?

Ik denk altijd dat ik eenvoudig if(p != NULL){..}zal de taak doen. Maar na het lezen van Deze stapel overloopvraag lijkt het niet.

Dus wat is de Canonical Way om te controleren op NULL-aanwijzers na Absorberen van alle discussie in die vraag die zegt dat NULL-aanwijzingen niet-nulwaarde kunnen hebben?


1, Autoriteit 100%

Ik denk altijd aan als (p! =
Null) {..} zal de taak doen.

het zal.


2, Autoriteit 46%

Ten eerste, om 100% duidelijk te zijn, is er NO verschil tussen C en C++
hier. En de tweede, de stack overloopt de vraag die u citeert, praat niet over null-aanwijzers; het introduceert ongeldige wijzers; wijzers die, althans voor zover de
Standaard is betrokken, veroorzaakt ongedefinieerd gedrag alleen door te proberen
vergelijk ze. Er is geen manier om in het algemeen te testen of een aanwijzer is
geldig.

Uiteindelijk zijn er drie wijdverspreide manieren om te controleren op een null-aanwijzer:

if ( p != NULL ) ...
if ( p != 0 ) ...
if ( p ) ...

Alle werk, ongeacht de weergave van een nul-aanwijzer op de
machine. En alles, op de een of andere manier, misleidend; welke jij
kies is een kwestie van het kiezen van het minste slecht. Formeel, de eerste twee
zijn inentical voor de compiler; De constante NULLof 0is geconverteerd
naar een null-aanwijzer van het type p, en de resultaten van de conversie
worden vergeleken met p. Ongeacht de weergave van een nul
wijzer.

De derde is iets anders: pwordt impliciet geconverteerd
naar bool. Maar de impliciete conversie wordt gedefinieerd als de resultaten van p
!= 0
, dus je eindigt met hetzelfde. (Wat betekent dat er is
echt geen geldig argument voor het gebruik van de derde stijl – het vertroebelt
met een impliciete conversie, zonder enig compenserend voordeel.)

Welke van de eerste twee je voorkeur heeft, is grotendeels een kwestie van stijl,
misschien gedeeltelijk gedicteerd door uw programmeerstijl elders:
afhankelijk van het betreffende idioom, zal een van de leugens hinderlijker zijn
Dan de andere. Als het alleen maar een kwestie van vergelijken was, denk ik het meest
mensen zouden de voorkeur geven aan NULL, maar in iets als f( NULL ), de
overbelasting die zal worden gekozen is f( int ), en niet een overbelasting met a
wijzer. Evenzo, als feen functiesjabloon is, zal f( NULL )
instantiëren van de sjabloon op int. (Natuurlijk, sommige compilers, zoals
g++, zal een waarschuwing genereren als NULLwordt gebruikt in een context zonder aanwijzer;
als je g++ gebruikt, zou je eigenlijk NULLmoeten gebruiken.)

In C++11is het voorkeurstaal natuurlijk:

if ( p != nullptr ) ...

, waarmee de meeste problemen met de andere oplossingen worden vermeden. (Maar het
is niet C-compatibel :-).)


Antwoord 3, autoriteit 13%

De compiler moet een consistent typesysteem bieden en een reeks standaardconversies bieden. Noch de integerwaarde 0 noch de NULL-pointer hoeft te worden weergegeven door bits die allemaal nul zijn, maar de compiler moet ervoor zorgen dat het “0”-token in het invoerbestand wordt omgezet in de juiste representatie voor integer nul, en de cast naar het pointertype moet converteren van integer naar pointer representatie.

De implicatie hiervan is dat

void *p;
memset(&p, 0, sizeof p);
if(p) { ... }

Heeft u niet gegarandeerd hetzelfde op alle doelsystemen, omdat u hier een aanname doet over het bitpatroon.

Als een voorbeeld heb ik een ingesloten platform dat geen geheugenbeveiliging heeft en houdt de onderbrekingsvectoren op adres 0, dus bij conventie, gehele getallen en aanwijzers worden gecomteerd bij 0x2000000 wanneer geconverteerd, wat (ongeldig *) 0 wordt geconverteerd Een adres dat een busfout genereert wanneer het afneemt, maar het testen van de aanwijzer met een if-verklaring het eerst terugstuurt naar gehele weergave, dat is dan ALL-ZEROS.


4, Autoriteit 8%

Blijkbaar is de draad die u verwijst, gaat over C++.

In CUw fragment zal altijd werken. Ik hou van de eenvoudigere if (p) { /* ... */ }.


5, Autoriteit 3%

De representatie van pointers is niet relevant om ze te vergelijken, aangezien alle vergelijkingen in C plaatsvinden als waardenen niet als representaties. De enige manier om de weergave te vergelijken zou iets afschuwelijks zijn als:

static const char ptr_rep[sizeof ptr] = { 0 };
if (!memcmp(&ptr, ptr_rep, sizeof ptr)) ...

Antwoord 6, autoriteit 3%

Nou, deze vraag is al in 2011 gesteld en beantwoord, maar er staat nullptrin C++11. Dat is alles wat ik momenteel gebruik.

Je kunt meer lezen van Stack Overflowen ook van dit artikel.


Antwoord 7

//Do this
int IS_NULL_PTR(char *k){
memset(&k, k, sizeof k);
if(k) { return 71; } ;
return 72;
}
int PRINT_PTR_SAFE(char *KR){
    char *E=KR;;
    if (IS_NULL_PTR(KR)==71){
        printf("%s\r\n",KR);
    } else {
        printf("%s","(null)\r\n");
    }
}
int main(int argc,char *argv[]){
    int i=0;
    char *A=malloc(sizeof(char)*9);
    ;strcpy(A,"hello world");
    for (i=((int)(A))-10;i<1e+40;i++){
        PRINT_PTR_SAFE(i);
    }
}
//Then watch the show!
//Edit as you wish. Just credit me if you really want more of this.

Other episodes