zoukankan      html  css  js  c++  java
  • 为什么C++函数调用前必须声明

    一、习惯性问题
    刚从C++转到C开发的时候,觉得C里面一些函数调用不用声明函数原型,也不用定义,当时觉得很神奇。后来在C语言下开发久了,发现调用的函数没有声明导致编译错误,又觉得很神奇。看来很多东西习惯了就见鬼不怪了。
    二、测试的代码
    [tsecer@Harry GccTest]$ cat MustDec.c 
    int foo()
    {
        return NeitherDecNorDef(1);
    }
    [tsecer@Harry GccTest]$ gcc MustDec.c -c
    [tsecer@Harry GccTest]$ g++ MustDec.c -c
    MustDec.c: In function ‘int foo()’:
    MustDec.c:3: error: ‘NeitherDecNorDef’ was not declared in this scope
    [tsecer@Harry GccT_
    三、为什么C++必须声明
    因为C++支持函数过载。也就是说同样一个函数名,可以带不同的参数,从而形成不同的函数,它们可以并存并且不至于出现连接错误。这一切都要归功于C++名字粉碎的功劳,也就是mangling。
    例如,在C++中,下面的代码可以编译通过
    [tsecer@Harry gccg++]$ cat HappyCoexist.c
    int foo(int arg)
    {
    return arg * arg;
    }
    int foo(short arg)
    {
    return arg / arg;
    }
    /*short foo(short arg)
    {
    return arg + arg;
    }*/
    可以看到,第一个和第二个函数的参数一个short,一个是int,但是可以共存。但是最后一个返回值和第二个不同却无法通过。
    这一点因为很多函数调用的时候,可能并没有使用返回值,所以只是从函数返回值并不能确定调用处真正希望使用的是哪个函数,所以是一个二义语法。
    看一下刚才生成的.o文件中的符号信息
    [tsecer@Harry gccg++]$ nm HappyCoexist.o 
    00000000 T _Z3fooi
    0000000c T _Z3foos
    可见,里面并不是单单的foo那么简单,而是添加了参数信息到符号名中。所以对于最开始的测试例子
    foo(1)
    来说,如果没有声明,就不知道调用的是哪一个函数,从而在目标文件中也无法准确生成将要被重定位的符号名称。
    四、另一个细节
    gcc编译的时候,如果文件后缀为c,则认为是c文件;如果后缀为cxx或者cpp,则认为是c++文件,g++将所有文件当做c++文件
    [tsecer@Harry gccg++]$ cat HappyCoexist.cpp 
    int foo(int arg)
    {
    return arg * arg;
    }
    int foo(short arg)
    {
    return arg / arg;
    }
    /*short foo(short arg)
    {
    return arg + arg;
    }*/
    [tsecer@Harry gccg++]$ gcc HappyCoexist.cpp -c -v
    Using built-in specs.
    Target: i686-redhat-linux
    Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
    Thread model: posix
    gcc version 4.4.2 20091027 (Red Hat 4.4.2-7) (GCC) 
    COLLECT_GCC_OPTIONS='-c' '-v' '-E' '-mtune=generic' '-march=i686'
     /usr/libexec/gcc/i686-redhat-linux/4.4.2/cc1plus -E -quiet -v -D_GNU_SOURCE HappyCoexist.cpp -mtune=generic -march=i686
    ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.4.2/include-fixed"
    ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../i686-redhat-linux/include"
    #include "..." search starts here:
    #include <...> search starts here:
     /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2
     /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/i686-redhat-linux
     /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/backward
     /usr/local/include
     /usr/lib/gcc/i686-redhat-linux/4.4.2/include
     /usr/include
    End of search list.
    COMPILER_PATH=/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/
    LIBRARY_PATH=/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../:/lib/:/usr/lib/
    COLLECT_GCC_OPTIONS='-c' '-v' '-E' '-mtune=generic' '-march=i686'
    Using built-in specs.
    Target: i686-redhat-linux
    Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
    Thread model: posix
    gcc version 4.4.2 20091027 (Red Hat 4.4.2-7) (GCC) 
    COLLECT_GCC_OPTIONS='-c' '-v' '-o' '/home/tsecer/.ccache/tmp.hash.Harry.16477.o' '-mtune=generic' '-march=i686'
     /usr/libexec/gcc/i686-redhat-linux/4.4.2/cc1plus -fpreprocessed /home/tsecer/.ccache/HappyCoexi.tmp.Harry.16477.ii -quiet -dumpbase HappyCoexi.tmp.Harry.16477.ii -mtune=generic -march=i686 -auxbase-strip /home/tsecer/.ccache/tmp.hash.Harry.16477.o -version -o /tmp/ccaTdru8.s
    GNU C++ (GCC) version 4.4.2 20091027 (Red Hat 4.4.2-7) (i686-redhat-linux)
        compiled by GNU C version 4.4.2 20091027 (Red Hat 4.4.2-7), GMP version 4.3.1, MPFR version 2.4.1.
    GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128396
    Compiler executable checksum: 1654075adcfd832dfb7b0208272c8238
    COLLECT_GCC_OPTIONS='-c' '-v' '-o' '/home/tsecer/.ccache/tmp.hash.Harry.16477.o' '-mtune=generic' '-march=i686'
     as -V -Qy -o /home/tsecer/.ccache/tmp.hash.Harry.16477.o /tmp/ccaTdru8.s
    GNU assembler version 2.19.51.0.14 (i686-redhat-linux) using BFD version version 2.19.51.0.14-34.fc12 20090722
    COMPILER_PATH=/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/
    LIBRARY_PATH=/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../:/lib/:/usr/lib/
    COLLECT_GCC_OPTIONS='-c' '-v' '-o' '/home/tsecer/.ccache/tmp.hash.Harry.16477.o' '-mtune=generic' '-march=i686'
    [tsecer@Harry gccg++]$ g++ HappyCoexist.cpp -c -v
    Using built-in specs.
    Target: i686-redhat-linux
    Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
    Thread model: posix
    gcc version 4.4.2 20091027 (Red Hat 4.4.2-7) (GCC) 
    COLLECT_GCC_OPTIONS='-c' '-v' '-E' '-shared-libgcc' '-mtune=generic' '-march=i686'
     /usr/libexec/gcc/i686-redhat-linux/4.4.2/cc1plus -E -quiet -v -D_GNU_SOURCE HappyCoexist.cpp -mtune=generic -march=i686
    ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.4.2/include-fixed"
    ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../i686-redhat-linux/include"
    #include "..." search starts here:
    #include <...> search starts here:
     /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2
     /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/i686-redhat-linux
     /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/backward
     /usr/local/include
     /usr/lib/gcc/i686-redhat-linux/4.4.2/include
     /usr/include
    End of search list.
    COMPILER_PATH=/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/
    LIBRARY_PATH=/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../:/lib/:/usr/lib/
    COLLECT_GCC_OPTIONS='-c' '-v' '-E' '-shared-libgcc' '-mtune=generic' '-march=i686'
    Using built-in specs.
    Target: i686-redhat-linux
    Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
    Thread model: posix
    gcc version 4.4.2 20091027 (Red Hat 4.4.2-7) (GCC) 
    COLLECT_GCC_OPTIONS='-c' '-v' '-o' '/home/tsecer/.ccache/tmp.hash.Harry.16487.o' '-shared-libgcc' '-mtune=generic' '-march=i686'
     /usr/libexec/gcc/i686-redhat-linux/4.4.2/cc1plus -fpreprocessed /home/tsecer/.ccache/HappyCoexi.tmp.Harry.16487.ii -quiet -dumpbase HappyCoexi.tmp.Harry.16487.ii -mtune=generic -march=i686 -auxbase-strip /home/tsecer/.ccache/tmp.hash.Harry.16487.o -version -o /tmp/ccsP2Dyc.s
    GNU C++ (GCC) version 4.4.2 20091027 (Red Hat 4.4.2-7) (i686-redhat-linux)
        compiled by GNU C version 4.4.2 20091027 (Red Hat 4.4.2-7), GMP version 4.3.1, MPFR version 2.4.1.
    GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128396
    Compiler executable checksum: 1654075adcfd832dfb7b0208272c8238
    COLLECT_GCC_OPTIONS='-c' '-v' '-o' '/home/tsecer/.ccache/tmp.hash.Harry.16487.o' '-shared-libgcc' '-mtune=generic' '-march=i686'
     as -V -Qy -o /home/tsecer/.ccache/tmp.hash.Harry.16487.o /tmp/ccsP2Dyc.s
    GNU assembler version 2.19.51.0.14 (i686-redhat-linux) using BFD version version 2.19.51.0.14-34.fc12 20090722
    COMPILER_PATH=/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/:/usr/libexec/gcc/i686-redhat-linux/4.4.2/:/usr/libexec/gcc/i686-redhat-linux/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/
    LIBRARY_PATH=/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/:/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../:/lib/:/usr/lib/
    COLLECT_GCC_OPTIONS='-c' '-v' '-o' '/home/tsecer/.ccache/tmp.hash.Harry.16487.o' '-shared-libgcc' '-mtune=generic' '-march=i686'
    [tsecer@Harry gccg++]$

  • 相关阅读:
    http2新特性
    SSL/TLS工作原理
    https工作原理解析
    k8s认证与鉴权
    grpc
    golang channel是线程安全的吗
    golang map是线程安全的吗
    k8s创建deployment的工作流
    Docker实践:部署漏洞扫描 AWVS + Nessus
    Python Peewee
  • 原文地址:https://www.cnblogs.com/tsecer/p/10485964.html
Copyright © 2011-2022 走看看