【问题标题】:What is the difference between "void function()" and "void *function()"?“void function()”和“void *function()”有什么区别?
【发布时间】:2017-12-05 04:20:39
【问题描述】:

我知道void *function() 是指向函数的指针,但我不知道它们的工作方式有何不同以及我们何时使用void *function()? 我在组装方面做了一些研究,以比较它们在幕后的工作方式,看起来它们是一样的。 这是c++代码:

void *bar(){
        std::cout << "bar" << std::endl;
}

void foo(){
        std::cout << "foo" << std::endl;
}

int main(void){
        foo();
        bar();

        return 0;
}

这是我从 objdump 收到的汇编指令

void *bar(){
  400846:       55                      push   %rbp
  400847:       48 89 e5                mov    %rsp,%rbp
        std::cout << "bar" << std::endl;
  40084a:       be 84 09 40 00          mov    $0x400984,%esi
  40084f:       bf 60 10 60 00          mov    $0x601060,%edi
  400854:       e8 b7 fe ff ff          callq  400710 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
  400859:       be 30 07 40 00          mov    $0x400730,%esi
  40085e:       48 89 c7                mov    %rax,%rdi
  400861:       e8 ba fe ff ff          callq  400720 <_ZNSolsEPFRSoS_E@plt>
}
  400866:       90                      nop
  400867:       5d                      pop    %rbp
  400868:       c3                      retq   

0000000000400869 <_Z3foov>:

void foo(){
  400869:       55                      push   %rbp
  40086a:       48 89 e5                mov    %rsp,%rbp
        std::cout << "foo" << std::endl;
  40086d:       be 88 09 40 00          mov    $0x400988,%esi
  400872:       bf 60 10 60 00          mov    $0x601060,%edi
  400877:       e8 94 fe ff ff          callq  400710 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
  40087c:       be 30 07 40 00          mov    $0x400730,%esi
  400881:       48 89 c7                mov    %rax,%rdi
  400884:       e8 97 fe ff ff          callq  400720 <_ZNSolsEPFRSoS_E@plt>
}
  400889:       90                      nop
  40088a:       5d                      pop    %rbp
  40088b:       c3                      retq   

000000000040088c <main>:

int main(void){
  40088c:       55                      push   %rbp
  40088d:       48 89 e5                mov    %rsp,%rbp
        foo();
  400890:       e8 d4 ff ff ff          callq  400869 <_Z3foov>
        bar();
  400895:       e8 ac ff ff ff          callq  400846 <_Z3barv>

        return 0;
  40089a:       b8 00 00 00 00          mov    $0x0,%eax
}
  40089f:       5d                      pop    %rbp
  4008a0:       c3                      retq   

【问题讨论】:

  • bar 返回一个 void 指针,而 foo 什么也不返回。如果这本身还不够不同,那么您需要在继续之前阅读一本好书。
  • 哦,如果你声明一个函数返回一些东西,你必须返回一些东西或者你有未定义的行为
  • 你应该得到类似warning: control reaches end of non-void function [-Wreturn-type]
  • @DuyVu -Wall -Wextra -Werror -pedantic 适用于任何 gcc/clang 编译器链。
  • 你的测试没有任何意义,因为你什么也没返回。

标签: c++ pointers assembly


【解决方案1】:

重复你已经在 cmets 中得到的答案,区别在于返回的类型

void foo() { ... }

是一个什么都不返回的函数,而

void *bar() { ... }
void* bar() { ... } // Identical

返回一个void 指针。在* 之前或之后交换空格位置在这里没有区别,但它可能会更清楚返回类型是什么。当然,请确保在 bar 函数的情况下实际返回某些内容,否则您至少会收到编译器警告和未定义的行为。

所以基本上这只是要记住的关键字void 的两个稍微不同的含义。如果您不熟悉 C++,那么也有大量易于阅读的书籍可以帮助您。

【讨论】:

    【解决方案2】:

    void 不返回任何内容。

    void* 返回一个指向未知类型的指针。它是你通常不想返回的东西,而是你想要返回的对象的类型以保证类型安全。您想使用void* 作为返回类型的唯一地方是在处理原始内存时。例如mallocnew 返回一个void*,因为它们的返回值没有类型(这取决于mallocnew 的调用者)。

    您的bar 函数错误,因为返回类型是void*,但您没有返回任何内容。

    【讨论】:

      【解决方案3】:

      void 不返回任何东西

      void * 返回指针

      不要浪费时间阅读反汇编列表 - 而是正确学习 C

      不要忽视警告!!!!!!

      void *bar(){
              std::cout << "bar" << std::endl;
      }
      

      你有同样的警告吗?没有吗?

      我知道 void *function() 是指向函数的指针

      现在你不知道。它不是函数指针。首先学习 C 或 C++。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-07
        • 1970-01-01
        • 2012-07-12
        • 2012-07-16
        相关资源
        最近更新 更多