11

Let's say I have a function which takes an array of structs, defined like so:

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

Are these following two snippets guaranteed to behave the same way?

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
  • 1
    godbolt.org/g/3iq38U you can see they generated same machine code Commented Apr 29, 2016 at 3:21

3 Answers 3

7

The answer is yes, they are effectively the same. First, arrays are passed as pointer to its first element, when used in function arguments. Actually, all objects in C can be treated as a array of one element of that type in terms of storage.

Sign up to request clarification or add additional context in comments.

Comments

3

Yes. Both options are stack-allocated and create exactly one 'instance' of struct MyStruct. Your compiler is expected to output the same machine code for both options. See this link (C) and this link (C++) for more details.

2 Comments

The op was asking about C, the link is about C++ and Java.
Not exactly... it explains how stack allocation works in C++ and how it relates to Java - even though it compares C++ to Java, it explains how stack allocation works. I just added another link which explains stack allocation for pure C as well.
3

They are identical; proof - I compiled and saved the assembly code generated by both MSVC 2015 and GCC 4.9.3 for these two code samples:

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

I note that the operations in foo are random and not really relevant to the test; they are just to prevent the compiler from optimizing out the method.

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

In the generated assembly files, on GCC they are exactly identical, and in MSVC, literally the only differences are:

  1. The variable names in the comments (s vs as)
  2. The line numbers referenced (since different ones are uncommented in each version).

Therefore, it is safe to assume that these two methods are identical.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.