為什么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++]$


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM