代码和执行
#include <stdio.h>
void fun();
int main(void)
{
{
void fun()
{
printf("Message from main!\n");
}
fun();
}
fun();
return 0;
}
void fun()
{
printf("Message from fun!\n");
}
执行结果如下:
Message from main!
Message from fun!
反汇编目标文件结果如下:
test.o: 文件格式 elf64-x86-64
Disassembly of section .text:
0000000000000000 <fun.2287>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 4c 89 55 f8 mov %r10,-0x8(%rbp)
c: bf 00 00 00 00 mov $0x0,%edi
11: e8 00 00 00 00 callq 16 <fun.2287+0x16>
16: 90 nop
17: c9 leaveq
18: c3 retq
0000000000000019 <main>:
19: 55 push %rbp
1a: 48 89 e5 mov %rsp,%rbp
1d: 48 83 ec 10 sub $0x10,%rsp
21: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
28: 00 00
2a: 48 89 45 f8 mov %rax,-0x8(%rbp)
2e: 31 c0 xor %eax,%eax
30: 48 8d 45 f7 lea -0x9(%rbp),%rax
34: 49 89 c2 mov %rax,%r10
37: b8 00 00 00 00 mov $0x0,%eax
3c: e8 bf ff ff ff callq 0 <fun.2287>
41: b8 00 00 00 00 mov $0x0,%eax
46: e8 00 00 00 00 callq 4b <main+0x32>
4b: b8 00 00 00 00 mov $0x0,%eax
50: 48 8b 55 f8 mov -0x8(%rbp),%rdx
54: 64 48 33 14 25 28 00 xor %fs:0x28,%rdx
5b: 00 00
5d: 74 05 je 64 <main+0x4b>
5f: e8 00 00 00 00 callq 64 <main+0x4b>
64: c9 leaveq
65: c3 retq
0000000000000066 <fun>:
66: 55 push %rbp
67: 48 89 e5 mov %rsp,%rbp
6a: bf 00 00 00 00 mov $0x0,%edi
6f: e8 00 00 00 00 callq 74 <fun+0xe>
74: 90 nop
75: 5d pop %rbp
76: c3 retq
结论
从反汇编和执行的结果看可以得到这样一个结论:GCC允许在函数中定义一个函数,而该函数的可见行和变量的一样,只能在当前代码块中可见。
备注
现在还不知道为何会允许这样,但这似乎和C语言标准不符。而这种用法在GRUB2的源代码中出现了,文件为grub-core/kern/i386/pc/init.c
下面为代码部分:
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t,
grub_memory_type_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
grub_memory_type_t type)
{
/* Avoid the lower memory. */
if (addr < 0x100000)
{
if (size <= 0x100000 - addr)
return 0;
size -= 0x100000 - addr;
addr = 0x100000;
}
/* Ignore >4GB. */
if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE)
{
grub_size_t len;
len = (grub_size_t) ((addr + size > 0xFFFFFFFF)
? 0xFFFFFFFF - addr
: size);
add_mem_region (addr, len);
}
return 0;
}
grub_machine_mmap_iterate (hook);
更新
更深入的讨论见下面两篇文章
gcc官方文档
gcc官方文档中文解释