2016-04-29 12 views
11

Powiedzmy Mam funkcję, która pobiera tablicę kodowanym, zdefiniowane tak:Array rozmiar 1 vs. wskaźnik do struct

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

Czy te dwa następujące fragmenty gwarantowane zachowywać się w ten sam sposób?

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 widzisz, że wygenerowali ten sam kod maszynowy –

Odpowiedz

6

Odpowiedź brzmi: tak, są one faktycznie takie same. Po pierwsze, tablice są przekazywane jako wskaźnik do pierwszego elementu, gdy są używane w argumentach funkcji. W rzeczywistości wszystkie obiekty w C mogą być traktowane jako tablica jednego elementu tego typu pod względem pamięci.

2

Tak. Obie opcje przydzielane są w stosach i tworzą dokładnie jedną "instancję" struct MyStruct. Twój kompilator ma wypisać ten sam kod maszynowy dla obu opcji. Aby uzyskać więcej informacji, zobacz this link (C) i this link (C++).

+0

Op pytał o C, link dotyczy C++ i Java. – fluter

+0

Niezupełnie ... wyjaśnia, w jaki sposób alokacja stosów działa w C++ i jak odnosi się do Javy - mimo że porównuje C++ z Javą, wyjaśnia, jak działa alokacja stosu. Właśnie dodałem kolejny link, który wyjaśnia alokację stosu dla czystego C, jak również. – LordCapybara

+0

Dobrze. Wygląda dobrze – fluter

3

Są identyczne; Dowód - skompilowany i zapisany kod montaż generowany zarówno przez MSVC 2015 i GCC 4.9.3 dla tych dwóch próbek kodu:

// 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; 
} 

Pragnę zauważyć, że operacje w foo są przypadkowe i nie bardzo odpowiednie do badania; mają one jedynie zapobiegać optymalizacji metody przez kompilator.

// 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; 
} 

w generowanych plikach montażowych, na GCC są dokładnie identyczne, a w MSVC, dosłownie jedyne różnice to:

  1. Nazwy zmiennych w komentarzach (s vs AS)
  2. Numery linii, do których się odwołano (ponieważ różne są odkomentowane w każdej wersji).

Dlatego można bezpiecznie założyć, że te dwie metody są identyczne.