Массив размера 1 по отношению к указателю на структуру
Скажем, у меня есть функция, которая берет массив структур, определенных так:
void Foo(struct MyStruct *s, int count) {
for (int i = 0; i < count; ++i) {
// Do something with s[i]
}
}
Являются ли эти следующие два фрагмента гарантией одинакового поведения?
struct MyStruct s;
s.x = 0;
s.y = 0;
Foo(&s, 1);
против.
struct MyStruct s[1]; // stack-allocated array of size 1
s[0].x = 0;
s[0].y = 0;
Foo(s, 1);
Ответы
Ответ 1
Ответ да, они фактически одинаковы. Во-первых, массивы передаются как указатель на его первый элемент, когда они используются в аргументах функции. Фактически, все объекты в C можно рассматривать как массив одного элемента этого типа с точки зрения хранения.
Ответ 2
Они идентичны; доказательство - я скомпилировал и сохранил код сборки, сгенерированный как MSVC 2015, так и GCC 4.9.3 для этих двух образцов кода:
// 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;
}
Замечу, что операции в foo
являются случайными и не имеют отношения к тесту; они просто не позволяют компилятору оптимизировать метод.
// 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;
}
В сгенерированных файлах сборки на GCC они точно идентичны, а в MSVC буквально единственные отличия:
- Имена переменных в комментариях (s vs as)
- Номера строк, на которые ссылаются (поскольку разные версии без комментариев в каждой версии).
Поэтому можно с уверенностью предположить, что эти два метода идентичны.
Ответ 3
Да. Обе опции распределены по стекам и создают ровно один "экземпляр" struct MyStruct
. Ожидается, что ваш компилятор выдаст один и тот же машинный код для обеих параметров. См. эта ссылка (C) и эта ссылка (С++) для более подробной информации.