Как составные литералы работают в этом коде?
У меня есть следующий код, в котором я написал две функции. Оба предназначены для получения одинакового результата. Но функция g()
У которого цикл имеет другой результат, чем я ожидал, как показано ниже.
#include <stdio.h>
struct S { int i; };
void f(void)
{
struct S *p;
int i = 0;
p = &((struct S) {i});
printf("%p\n", p);
i++;
p = &((struct S) {i});
printf("%p\n", p);
}
void g(void)
{
struct S *p;
for (int i = 0; i < 2; i++)
{
p = &((struct S) {i});
printf("%p\n", p);
}
}
int main()
{
printf("Calling function f()\n");
f();
printf("\nCalling function g()\n");
g();
}
Выход:
Calling function f()
0023ff20
0023ff24
Calling function g()
0023ff24
0023ff24
Как получается адрес p
то же самое в случае g()
когда это называлось?
2 ответа
Ну, я не знаю точно, что вы пытаетесь достичь, но здесь происходит следующее:
(struct S){i}
нотация в C99 создаст новую структуру данных в стеке- эта структура данных автоматически уничтожается в конце области, в которой она была создана
Так в f()
На самом деле, вы создаете ДВЕ различные структуры в области действия всей функции (даже если вы назначаете их адреса одному и тому же указателю) - следовательно, два разных адреса.
void f(void)
{
struct S *p;
int i = 0;
p = &((struct S) {i}); // <- first data structure, let's call it A
printf("%p\n", p); // <- address of the structure A printed
i++;
p = &((struct S) {i}); // <- second data structure, let's call it B
printf("%p\n", p); // <- address of the structure B printed
} // <- both A and B destroyed
Но в g()
функционировать p
создается и уничтожается во внутреннем блоке for
block, и поэтому случается, что p снова и снова размещается в одной и той же позиции в стеке, давая всегда один и тот же адрес.
void g(void)
{
struct S *p;
for (int i = 0; i < 2; i++)
{
p = &((struct S) {i}); // <- data structure A created
printf("%p\n", p); // <- data structure A's address printed
} // <- data structure A destroyed
}
Вы должны проверить код сборки, чтобы быть уверенным, но я предполагаю, что, так как p
назначается локально в области видимости цикла с адресом автоматически распределенной переменной (которая выделяется в стеке), он просто повторно использует то же пространство в стеке.
В f()
он не делает этого, потому что обе структуры сосуществуют в одной области, в то время как в g()
Компилятор уверен, что в конце первой итерации вы не сможете использовать &((struct S) {0})
,
Просто пытался из любопытства с -O2
на gcc4.2, чтобы увидеть, если что-то меняется:
Calling function f()
0x7fff5fbff388
0x7fff5fbff380
Calling function g()
0x7fff5fbff390
0x7fff5fbff390