[编译环境][gcc]在函数中定义函数

代码和执行

#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官方文档中文解释

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值