Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array of size 1 vs. pointer to struct

Tags:

arrays

c

pointers

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);
like image 955
Andrew Sun Avatar asked Apr 29 '16 03:04

Andrew Sun


People also ask

Why do some structures end with an array of size 1?

Some Windows structures are variable-sized, beginning with a fixed header, followed by a variable-sized array. When these structures are declared, they often declare an array of size 1 where the variable-sized array should be.

What is the size of a pointer to an array?

The pointer ptr, and all pointers, are 8 bytes, because they hold addresses, which are 8 bytes, or 64 bits. Assigning any address to an array variable is not allowed.

How do you determine the size of a struct array?

foo=sizeof(para)/sizeof(para[0]);

What is meant by array length 1?

length -1 means, specifically the -1 part. When using a for loop over an array we have something like this: for (i = 0; i < array. length; i++) {...}


2 Answers

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.

like image 176
fluter Avatar answered Oct 12 '22 17:10

fluter


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.

like image 29
Govind Parmar Avatar answered Oct 12 '22 17:10

Govind Parmar