2016-04-29 23 views
11

Diciamo Ho una funzione che prende un array di struct, definito in questo modo:array di dimensione 1 puntatore a struct vs.

void Foo(struct MyStruct *s, int count) { 
    for (int i = 0; i < count; ++i) { 
     // Do something with s[i] 
    } 
} 

Sono questi due seguenti frammenti garantiti a comportarsi nello stesso modo?

struct MyStruct s; 
s.x = 0; 
s.y = 0; 
Foo(&s, 1); 

vs.

struct MyStruct s[1]; // stack-allocated array of size 1 
s[0].x = 0; 
s[0].y = 0; 
Foo(s, 1); 
+1

https://godbolt.org/g/3iq38U è possibile vedere hanno generato lo stesso codice macchina –

risposta

6

La risposta è sì, sono effettivamente uguali. Innanzitutto, gli array vengono passati come puntatori al primo elemento, quando vengono utilizzati negli argomenti della funzione. In realtà, tutti gli oggetti in C possono essere trattati come una matrice di un elemento di quel tipo in termini di spazio di archiviazione.

2

Sì. Entrambe le opzioni sono allocate allo stack e creano esattamente una "istanza" di struct MyStruct. Il compilatore dovrebbe produrre lo stesso codice macchina per entrambe le opzioni. Vedere this link (C) e this link (C++) per ulteriori dettagli.

+0

L'op stava chiedendo di C, il collegamento è su C++ e Java. – fluter

+0

Non esattamente ... spiega come funziona l'allocazione dello stack in C++ e come si relaziona con Java - anche se confronta C++ con Java, spiega come funziona l'allocazione dello stack. Ho appena aggiunto un altro link che spiega l'allocazione dello stack anche per C pura. – LordCapybara

+0

Giusto. Sembra buono – fluter

3

Sono identici; prova - ho compilato e salvato il codice assembly generato sia da MSVC 2015 e GCC 4.9.3 per questi campioni a due code:

// Case 1: Pass by reference to single struct 
typedef struct _mystruct 
{ 
    int x; 
    int y; 
} mystruct; 

void foo(mystruct *s, int count) 
{ 
    int i; 
    for(i = 0; i < count; i++) 
    { 
     (*(s + i)).x = 5; 
     (*(s + i)).y = 7; 
    } 
} 

int main() 
{ 
    mystruct ps; 

    //mystruct as[1]; 


    foo(&ps, 1); 
    //foo(as, 1); 
    return 0; 
} 

faccio notare che le operazioni di cui foo sono casuali e non realmente rilevanti per la prova; servono solo a impedire al compilatore di ottimizzare il metodo.

// Case 2: 1-length array 
typedef struct _mystruct 
{ 
    int x; 
    int y; 
} mystruct; 

void foo(mystruct *s, int count) 
{ 
    int i; 
    for(i = 0; i < count; i++) 
    { 
     (*(s + i)).x = 5; 
     (*(s + i)).y = 7; 
    } 
} 

int main() 
{ 
    //mystruct ps; 

    mystruct as[1]; 


    //foo(&ps, 1); 
    foo(as, 1); 
    return 0; 
} 

Nei file assembly generato, il GCC sono esattamente identici, e in MSVC, letteralmente le uniche differenze sono:

  1. I nomi delle variabili nei commenti (s vs AS)
  2. I numeri di riga di riferimento (poiché quelli diversi sono non commentati in ogni versione).

Pertanto, è lecito ritenere che questi due metodi siano identici.

Problemi correlati