Perché un int lungo richiede 12 byte su alcune macchine?

26

Ho notato qualcosa di strano dopo aver compilato questo codice sulla mia macchina:

#include <stdio.h>

int main()
{
    printf("Hello, World!\n");

    int a,b,c,d;

    int e,f,g;

    long int h;

    printf("The addresses are:\n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x",
        &a,&b,&c,&d,&e,&f,&g,&h);

    return 0;
}

Il risultato è il seguente. Si noti che tra ogni indirizzo int esiste una differenza di 4 byte. Tuttavia tra l'ultimo int e il long int c'è una differenza di 12 byte:

 Hello, World!
 The addresses are:

 da54dcac 
 da54dca8 
 da54dca4 
 da54dca0 
 da54dc9c 
 da54dc98 
 da54dc94 
 da54dc88
    
posta yoyo_fun 12.09.2017 - 11:29
fonte

3 risposte

82

Non ci sono voluti 12 byte, ci sono voluti solo 8. Tuttavia, l' allineamento predefinito per un lungo 8 byte int su questa piattaforma è di 8 byte. Come tale, il compilatore aveva bisogno di spostare l'int lungo su un indirizzo divisibile per 8. L'indirizzo "ovvio", da54dc8c, non è divisibile per 8 quindi il gap di 12 byte.

Dovresti essere in grado di testarlo. Se aggiungi un altro int prima del lungo, quindi ce ne sono 8, dovresti trovare che il lungo int sarà allineato ok senza una mossa. Ora saranno solo 8 byte dall'indirizzo precedente.

Probabilmente vale la pena sottolineare che, sebbene questo test dovrebbe funzionare, non dovresti fare affidamento sulle variabili organizzate in questo modo. Un compilatore C è autorizzato a fare ogni sorta di roba funky per provare a far funzionare velocemente il tuo programma comprese le variabili di riordino (con alcune avvertenze).

    
risposta data 12.09.2017 - 12:09
fonte
9

Questo perché il compilatore genera padding extra tra le variabili per garantire che siano allineati correttamente nella memoria.

Sulla maggior parte dei processori moderni, se un valore ha un indirizzo che è un multiplo delle sue dimensioni, è più efficiente accedervi. Se avesse messo h al primo spot disponibile, il suo indirizzo sarebbe stato 0xda54dc8c, che non è un multiplo di 8, quindi sarebbe stato meno efficiente da usare. Il compilatore lo sa e aggiunge un po 'di spazio inutilizzato tra le tue ultime due variabili per assicurarti che accada.

    
risposta data 12.09.2017 - 12:03
fonte
1

Il tuo test non sta necessariamente testando ciò che pensi che sia, perché non è richiesto che la lingua colleghi l'indirizzo di una qualsiasi di queste variabili locali tra loro.

Dovresti metterli come campi in una struttura per poter dedurre qualcosa sull'allocazione dello spazio di archiviazione.

Le variabili locali non sono necessarie per condividere l'archiviazione l'una accanto all'altra in un modo particolare. Il compilatore può inserire una variabile temporanea in qualsiasi punto all'interno dello stack, ad esempio, che potrebbe trovarsi tra due qualsiasi di queste variabili locali.

Al contrario, non sarebbe permesso inserire una variabile temporanea in una struct, quindi se si stampassero gli indirizzi dei campi struct, si confronterebbero gli articoli destinati allocati dallo stesso chuck logico di memoria (la struct ).

    
risposta data 30.01.2018 - 02:54
fonte

Leggi altre domande sui tag