WebHU - Programozási kérdések és válaszok

while(foo) vs while(foo != NULL)

Valaki el tudná magyarázni, hogy a while(foo) vs while(foo != NULL) egyenértékűek? Is:

while(!foo) vs while(foo == NULL)

Tudom ! nem, de nagyjából ennyit tudok.

30.03.2015


Válaszok:


1

Feltételezve, hogy foo mutató típusú, a while (foo) és while (foo != NULL) pontosan egyenértékűek. Mindkettő egyenértékű a while (foo != 0)-vel is. (Véleményem szerint while (foo != NULL) egyértelműbben fejezi ki a szándékot.)

Bármilyen feltételt igénylő kontextusban (if(), while(), néhány másik), a kifejezés igazként lesz kezelve, ha a feltétel nem egyenlő nullával, hamisként, ha egyenlő nulla.

A NULL egy makró, amely megvalósítás által meghatározott null pointer konstansra bővül. A mutató értékének összehasonlítása a NULL értékkel valódi értéket ad a null mutatóhoz, hamis értéket minden nem nulla mutatóhoz.

A 0 konstans egy nulla mutatókonstans [*]. (Ez nem jelenti azt, hogy a nullmutatónak a 0x00000000 vagy valami hasonló bitjei megegyeznek, bár gyakran előfordul; ez azt jelenti, hogy a forráskódban egy konstans 0 nullmutatót jelölhet.) elvárható, hogy a mutató értékének egy null mutató állandóval való összehasonlítása megmondja, hogy a mutató nullmutató-e vagy sem. A while (foo)-ban a nullával való összehasonlítás implicit, de továbbra is teszteli, hogy a foo nullmutató-e vagy sem.

Általánosabban, a while (foo) összehasonlítja a foo-ot 0-el, ami egyenértékű a megfelelő típusú "nullával" való összehasonlítással. A while (foo) mindig egyenértékű a while (foo != 0) értékkel. Lebegőpontos érték esetén ez egyenértékű a while (foo != 0.0) értékkel is. Karakterérték esetén ez egyenértékű a while (foo != '\0') értékkel. És, amint láttuk, a mutató értéke while (foo != NULL)-nek felel meg.

(C-ben az összehasonlító operátor mindig int 0 értéket ad, ha a feltétel hamis, 1 értéket, ha igaz -- de a nullától eltérő értéket igaznak tekinti a nullához való implicit egyenlőtlenség-összehasonlítás révén.)

[*] A null pointer konstans egy 0 értékű egész szám konstans kifejezés, vagy egy ilyen kifejezés void* értékre öntve. A null mutatókonstans nem feltétlenül mutató típusú, de konvertálása mutató típusúvá nulla mutatóértéket eredményez. A mutató értékének 0-hoz való összehasonlítása azt eredményezi, hogy a 0 implicit módon mutatótípussá alakul, így az összehasonlítás elvégezhető.

30.03.2015
  • @chux: Frissítve. (A 0 egy int típusú kifejezés és egy nulla mutatókonstans; látom, hogy ez zavart okozhat.) 30.03.2015
  • Igen, nekem bevált, és élvezem a varjú ebédjét. Kiderült, hogy #define NULL 0 ugyanúgy érvényes lehet, mint #define NULL ((void*)0). Ez utóbbinak vannak előnyei, de mindkettő megfelel az előírásoknak. 30.03.2015
  • @chux: Van egy homályos érv, hogy a #define NULL ((void*)0) nem érvényes. (Az N1570 6.5.1p5 nem mondja ki, hogy a zárójelben szereplő nullmutató állandó nullamutató állandó.) A gyakorlatban azonban minden bizonnyal érvényesnek kell lennie. 30.03.2015

  • 2
    while(foo);
    

    és

    while(foo != NULL)
    

    Egyenértékűek egyszerűen azért, mert a NULL egy makró, amely 0-ra, (void*)0-re vagy 0L-re bővül, mivel C-ben a 0 hamisra (és minden nullától eltérő szám igazra) értékelődik.

    while(foo); //while foo isn't 0
    while(foo != NULL) //expands to while(foo != 0) < while foo isn't 0
    
    30.03.2015
  • A foo típusától függ. Tekintsük double foo. A while(foo); rendben van, de a while(foo != NULL) nem fordítja le: érvénytelen operandusok binárissá != attól függően, hogy a NULL hogyan van definiálva, ami nulla mutatókonstans kell, hogy legyen, és nem 0, ahogy itt javasoltuk. 30.03.2015
  • @chux Persze, ha feltételezzük, hogy a foo vagy egy mutató, vagy egy int, de a NULL garantáltan egyenlő 0-val, a gyakorlatban szerintem a legtöbb implementáció 0-t használ NULL-ként. 30.03.2015
  • A legtöbb megvalósítás 0-t használ, mint NULL Nem értek egyet, a My gcc 4.9.2 a #define NULL ((void *)0) értéket használja. MS Visual 2010, amikor a C a #define NULL ((void *)0) értéket használja. Talán arra gondol, hogyan van definiálva a NULL egy másik nyelvben, például a C++. 30.03.2015
  • @chux Azt mondtam, hogy a válaszomban a NULL egy makró, amely 0-ra, vagy (void*)0-ra vagy 0L-re bővül 30.03.2015
  • Azt állítom, hogy NULL lehet (void*)0, de nem 0 és 0L sem. Válasza szerint 0, or (void*)0 or 0L lehet. Az Ön megjegyzése a legtöbb implementáció 0-t használ NULL-ként, nem támasztja alá egyetlen példa sem, szemben a megadott 2 számláló példával. 30.03.2015
  • @chux mit értettem azon, hogy használd a 0-t mint. A NULL használja a 0 valamilyen formáját, vagy (void*)0, 0 vagy 0L NULL-ként, olvassa el a c-faq.com/null/long0.html, mivel a legtöbb megvalósításnál 0-t használnak NULL-ként, ezt soha nem próbáltam kemény tényként átadni 30.03.2015
  • Az a3f-vel folytatott csevegés során NULL lehet 0 vagy (void *)0 - helyesbítve. 30.03.2015

  • 3

    míg (expression) megismétli a befoglaló blokkot mindaddig, amíg a expression bármely nullától eltérő értékre kiértékelődik. Amikor a expression értéke 0, a while ciklus véget ér.

    Ha a mutató értéke nem std::nullptr vagy NULL, a expression, amely mutatótípus, nem 0-nak minősül.

    A ! operátor egy logikai not operátor.

    Ebből adódóan

     while (foo)
    

    És

     while (foo != NULL)
    

    logikailag egyenértékűek egymással. Ezért a kettő logikai inverze is ekvivalens egymással.

    30.03.2015
  • A std::nullptr egy c++ dolog. [c] kérdésben vagyunk. 30.03.2015

  • 4

    A NULL egy szimbolikus állandó, egyfajta helyettesítő szövegként is felfogható. A NULL csak valami, amit a fordító később nullára cserél, így a while (foo != NULL) írása ugyanaz, mint a while (foo != 0). Ne feledje, hogy az == igent mond, ha a tőle balra lévő egyenlő azzal, ami tőle jobbra van, míg a != igent mond, ha a tőle balra lévő NEM egyenlő azzal, ami tőle jobbra van.

    C-ben a 0 szám mindig hamis, minden más szám pedig igazat jelent. Tehát a while (foo != 0) ugyanaz, mint azt mondani, hogy "Futtassa a kódot ebben a ciklusban, miközben a foo igaz". A while (1) például ugyanaz, mint azt mondani, hogy "Futtassa a kódot ebben a ciklusban örökre", mert az 1 egy olyan szám, amely mindig különbözik a nullától, és ezért mindig igaz.

    C-ben, ha csak a foo értéket használja, ahol igaz vagy hamis típusú értéket várunk, ez ugyanaz, mintha foo != 0-et mondanánk, ez olyan, mint egy használható parancsikon. A ! azt jelenti, hogy "nem", tehát a !foo megkérdezése megegyezik azzal a kérdéssel, hogy "a foo NEM igaz?", más szóval "hamis a foo?". Ez azt jelenti, hogy a while (!foo) ugyanaz, mint a "Futtassa a kódot ebben a ciklusban, miközben a foo false", ami ugyanaz, mint a while (foo == 0), mivel a nulla hamis, ami ugyanaz, mint a while (foo == NULL), mivel a NULL nullát jelent.

    Képzeld el a következőképpen: a ciklusban lévő kód csak akkor fut le, ha a zárójelben szereplő igaz (azaz nem nulla). Tehát a while (foo)-ben a számítógép megkérdezi, hogy "a foo nem nulla?", ha igen, a ciklus folytatódik. Most, ha while (!foo) van, a számítógép megkérdezi, hogy "a foo NOT nem nulla?", ha igen, a ciklus folytatódik. A ciklus csak akkor áll le, ha a zárójelben lévő kifejezés false értéket eredményez.

    A NULL számos szabványos fejlécfájlban van definiálva, ez nem olyan kulcsszó, mint a if és while, használatához tartalmaznia kell egy fejlécfájlt, amely meghatározza azt. Az ötlet az, hogy amikor egy mutató a nulla címre mutat, azt "null pointernek" hívják, ezért hívják NULL-nek, és akkor használják, ha azt akarjuk mondani, hogy "nulla a cím", nem pedig pusztán "nulla a szám".

    Szerkesztés: Ahogyan Matt McNabb helyesen rámutatott, a NULL definíciója lehet 0 vagy (void *)0. A kétségek elkerülése végett a C11 szabványt idézem:

    A 0 értékű egész konstans kifejezést, vagy a void * típusba öntött kifejezést null pointer konstansnak nevezzük.

    És később

    A NULL makró a ‹stddef.h› fájlban (és más fejlécekben) null mutatókonstansként van definiálva; lásd 7.19.

    Ezután a 7.19. szakaszban:

    3 A makrók

    NULL

    amely kibővül egy megvalósítás által definiált null mutató állandóvá; és

    eltolás (típus, tagjelölő)

    ami kibővül...

    És a szöveg megy tovább. Tehát a (void *)0 és a 0 érvényes implementáció által meghatározott nullmutató konstansok.

    30.03.2015
  • NULL lehet 0 vagy (void *)0. 30.03.2015
  • @Matt McNabb Lehet NULL 0? Ahogy olvasom a C spec-et, a NULL egy null mutató állandó. A 0 egy int. Talán ugyanaz az érték, de eltérő típusok és méretek. 30.03.2015
  • @chux ezután továbbmegy, és meghatározza a null pointer constant értéket egy egész szám állandóként, amely nullával egyenlő, vagy ugyanazt a void*-re vetített értéket. 30.03.2015
  • @a3f Az implementáció által meghatározott nulla mutatókonstanssá bővülő NULL-re vonatkozó hivatkozásom a C11 forma, §7.19 3. Hol van a ...on nullával egyenlő egész konstans...? 30.03.2015
  • @chux C11 n1570: §6.3.2.3p3. Természetesen az implementáció szabadon választhat egy értéket a nulla bitektől eltekintve, hogy NULL képviselje, de szükséges, hogy a 0 egész számot NULL-ként kezelje mutatókontextusban. 30.03.2015
  • @a3f Egyetért azzal, hogy az 0 egész számot NULL-ként kezelje mutatókontextusban, de ez nem jelenti azt, hogy a null pointer constant (NULL) egész szám állandó a korábbi megjegyzésében. Az egyértelműség kedvéért a NULL-nek nem csak értéke van, hanem típusa is. Ahogy olvastam a C specifikációt, ez a típus valami mutató, a 0 pedig nem mutató. 30.03.2015
  • "An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant" == "defines null pointer constant on being an integer constant that equals zero or the same cast to void*", legalábbis nekem. 30.03.2015
  • Folytassuk ezt a beszélgetést a chatben. 30.03.2015
  • @danieltm64 Ha az a3f-el azt a következtetést vontuk le, hogy Matt McNabb helyes a NULL értékkel, az 0 vagy (void *)0 lehet. 30.03.2015

  • 5

    a while ciklus így futhat:

    while(1) //This will run forever.
    
    while(true) //This will run forever.
    

    A NULL olyan, mint a 0, tehát ha van while(foo != NULL), akkor ez azt jelenti, hogy a while (foo nem egyenlő 0-val, tehát míg egyenlő 1-gyel vagy valami mással) futtassa.

    30.03.2015
    Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..