Dubbio sulle costanti numeriche

di Nippolo il
8 risposte

Ciao, volevo sapere se esiste un tipo di default per le costanti numeriche (intere) o comunque qual è la regola generale in questi casi.

Per esempio il seguente codice:

#include <stdio.h>
#include <inttypes.h>

int main()
{
    uint64_t a = 12345678987654321;
    uint64_t b = 1 << 32;
    printf("%" PRIu64 "\n", a);
    printf("%" PRIu64 "\n", b);
    return 0;
}

mi restituisce un warning:

left shift count >= width of type [-Wshift-count-overflow]

Invece se modifico la dichiarazione di b in:

uint64_t b = (uint64_t)1 << 32;

va bene.

Ciò mi fa ipotizzare che il compilatore utilizzi in modo automatico il tipo intero di dimensioni minime o comunque sufficienti a contenere quella costante numerica. E' più o meno così?

8 Risposte

  • Considerato quanto segue

    27/01/2024 - Nippolo ha scritto:


    Ciò mi fa ipotizzare che il compilatore utilizzi in modo automatico il tipo intero di dimensioni minime o comunque sufficienti a contenere quella costante numerica. E' più o meno così?

    The type of the integer literal is the first type in which the value can fit …

    avresti anche potuto dire “sì, dai un'occhiata qui per approfondire”…

    In ogni caso grazie tante per il link!

  • Ciao Nippolo.

    In C, scrivere uint64_t b = 1 << 32; non cambia il tipo della costante 1 da int a uint64_t, è trattata come un intero a 32 bit.

    Usa 1ULL che è già una versione a 64 bit di 1.

    uint64_t b = 1ULL << 32;

     Fare come hai fatto te è corretto, ma dipende dal compilatore che usi, potrebbe darti errore o un risultato sbagliato.

  • Sì è così: è il più piccolo tra int, long e long long in cui il compilatore riesce a farcelo star dentro. Standard C99 capitolo 6.4.4.

    Il compilatore ha le mani legate. Però chi ha scritto il compilatore sa che la scelta ovvia nel tuo codice sarebbe unsigned long long e giustamente ti ha messo il warning

  • Grazie per i chiarimenti.

    Ipotizzo che

    (uint64_t)1

    e

    1ULL

    siano perfettamente equivalenti, giusto? O esiste qualche motivo per cui uno sarebbe da preferire all'altro?

  • 27/01/2024 - Nippolo ha scritto:


    Grazie per i chiarimenti.

    Ipotizzo che

    (uint64_t)1

    e

    1ULL

    siano perfettamente equivalenti, giusto? O esiste qualche motivo per cui uno sarebbe da preferire all'altro?

    Si, però è preferibile 1ULL, perchè con alcuni compilatori potrebbe eseguire prima l'operazione di shift dandoti un risultato differente dalle aspettative.

  • 27/01/2024 - systemred32 ha scritto:


    Si, però è preferibile 1ULL, perchè con alcuni compilatori potrebbe eseguire prima l'operazione di shift dandoti un risultato differente dalle aspettative.

    Il casting non ha una precedenza maggiore rispetto agli operatori di shift? Com'è possibile che un compilatore ignori le regole di precedenza?

  • Di fatto sono equivalenti. In linea di principio ci potrebbero essere differenze su alcune architetture tra impostare su un registro una costante a 32 bit castata a 64 e impostare una costante a 64 bit, ma non su quelle attuali 

Devi accedere o registrarti per scrivere nel forum
8 risposte