Это неопределенное поведение. Но я все же попытаюсь объяснить, почему тебе здесь повезло.
Я добавил немного кода к предоставленному, и теперь он выглядит так:
/* test.c */
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* createNode(int data){
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = data;
temp->next = NULL;
// return temp
}
int main(){
struct node *temp = createNode(12);
printf("%d %x", temp->data);
}
Компиляция:
$ gcc -g test.c
Запустите его с помощью GDB, чтобы вы могли видетьdisassembly
$ gdb -q ./a.out
Reading symbols from /root/a.out...done.
Разберите функцию createNode, чтобы увидеть, где находится возвращаемое значение из malloc
(поскольку это значение мы вернем обратно к main
). Обратите внимание, что rax, который обычно содержит возвращаемое значение функции, содержит возвращаемое значение malloc (вот где вам повезло)
(gdb) disass createNode
Dump of assembler code for function createNode:
0x0000000000400580 <+0>: push %rbp
0x0000000000400581 <+1>: mov %rsp,%rbp
0x0000000000400584 <+4>: sub $0x20,%rsp
0x0000000000400588 <+8>: mov %edi,-0x14(%rbp)
0x000000000040058b <+11>: mov $0x10,%edi
0x0000000000400590 <+16>: callq 0x400480 <malloc@plt>
0x0000000000400595 <+21>: mov %rax,-0x8(%rbp) <== rax register contains the return value of malloc, value is pushed to stack
0x0000000000400599 <+25>: mov -0x8(%rbp),%rax <== rax value retrieved from stack. now rax contains the return value of malloc
0x000000000040059d <+29>: mov -0x14(%rbp),%edx
0x00000000004005a0 <+32>: mov %edx,(%rax) <== node->next assignment is done here
0x00000000004005a2 <+34>: mov -0x8(%rbp),%rax <== again rax is populated by return value of malloc
0x00000000004005a6 <+38>: movq $0x0,0x8(%rax) <== node->next is assigned to NULL here.
0x00000000004005ae <+46>: leaveq
0x00000000004005af <+47>: retq
End of assembler dump.
Разберите функцию main
, чтобы увидеть, как было createNode
называется и откуда мы получаем возвращаемое значение. Обратите внимание, что значение rax считывается в переменную temp в кадре main.
(gdb) disass main
Dump of assembler code for function main:
0x00000000004005b0 <+0>: push %rbp
0x00000000004005b1 <+1>: mov %rsp,%rbp
0x00000000004005b4 <+4>: sub $0x10,%rsp
0x00000000004005b8 <+8>: mov $0xc,%edi
0x00000000004005bd <+13>: callq 0x400580 <createNode> <== createNode called
0x00000000004005c2 <+18>: mov %rax,-0x8(%rbp) <== rax contains the malloc's return value, so we got the correct value luckily
0x00000000004005c6 <+22>: mov -0x8(%rbp),%rax
0x00000000004005ca <+26>: mov (%rax),%eax
0x00000000004005cc <+28>: mov %eax,%esi
0x00000000004005ce <+30>: mov $0x400670,%edi
0x00000000004005d3 <+35>: mov $0x0,%eax
0x00000000004005d8 <+40>: callq 0x400450 <printf@plt>
0x00000000004005dd <+45>: leaveq
0x00000000004005de <+46>: retq
End of assembler dump.
(gdb) q
Надеюсь, это объясняет, почему мы видим правильное значение в temp, даже если в createNode не было оператора return.