Return 函数声明和定义的类型不匹配,但编译器可以接受吗?
Return type of function declaration & definition didn't match, compiler was ok with it though?
我在我的程序中犯了一个错误,我将我的函数声明为 return 类型 bool
,即使函数 return 编辑了 unsigned long long
。在一个源文件中:
#include <iostream>
using namespace std;
bool base(unsigned, unsigned);
int main(){
int i = 27;
cout << base(i,3);
}
并在另一个定义函数(和一个附加函数的幂)中:
unsigned long long power(int base, int exponent){
unsigned long long temp = 1;
if(exponent == 0) return 1;
for(int i = 1; i <= exponent; ++i)
temp *= base;
return temp;
}
unsigned long long base(unsigned x, unsigned base){
unsigned long long result = 0;
int i = 0;
while(x != 0){
result += (x%base)*power(10,i);
x = (x-(x%base))/base;
++i;
}
return result;
}
该函数以给定的底数计算出数字(这里我们以 3 为底数计算 27)。令我惊讶的是程序编译了,但不出所料输出给出了错误的答案(232 而不是预期的 1000),因为 return 类型是错误的。我想知道为什么编译器允许声明中的 return 类型是 bool
,即使它与定义中的 return 类型不对应。我的印象是函数原型必须与其相应的定义完全匹配,否则找不到函数?这很奇怪,因为我花了一些时间试图寻找问题,因为编译器没有提出它。
您看到的是未定义的行为:当您以与其前向声明不兼容的方式定义函数时,您的程序格式错误:
7.5.5: If two declarations declare functions with the same name and parameter-type-list (8.3.5) to be members of the same namespace or declare objects with the same name to be members of the same namespace and the
declarations give the names different language linkages, the program is ill-formed; no diagnostic is required if the declarations appear in different translation units.
当您继续调用此类函数时,行为未定义。未定义的行为可以以任何它希望的方式表现出来。你的情况是调用成功了,但是返回值不正确。
如果没有你的帮助,编译器是没办法搞定的,因为两个函数之间的联系是由链接器完成的,而不是由编译器完成的。编译器做任何事情都为时已晚,因此您需要使用不同的方法:通过创建一个包含函数声明的头文件,然后在您定义的两个文件中包含相同的头文件来避免此类错误以及调用该函数的文件。
部分原因是它们是两个独立的编译单元,上面base()
的声明在编译第二个编译单元(又名源文件,粗略地说)。同样,base()
的实际定义在编译 main()
.
时对编译器不可见
原因的第二部分是决定调用什么函数只使用参数的类型,而不是 return 类型。这意味着名称重整(对名称进行修饰,以便链接器可以将重载函数作为不同的函数接受)只需要编码有关函数参数类型的信息,而不是 return 类型。因此,链接器会将第二个编译单元中的定义视为与第一个编译单元中的声明相匹配。
最终结果是未定义的行为。
修复是为了确保在编译第二个单元时编译器可以看到第一个编译单元中的 base()
声明。换句话说,将声明放在头文件中,并 #include
在两个源文件中。然后编译器将拒绝 base()
的定义,因为它与前面的声明不匹配。
我在我的程序中犯了一个错误,我将我的函数声明为 return 类型 bool
,即使函数 return 编辑了 unsigned long long
。在一个源文件中:
#include <iostream>
using namespace std;
bool base(unsigned, unsigned);
int main(){
int i = 27;
cout << base(i,3);
}
并在另一个定义函数(和一个附加函数的幂)中:
unsigned long long power(int base, int exponent){
unsigned long long temp = 1;
if(exponent == 0) return 1;
for(int i = 1; i <= exponent; ++i)
temp *= base;
return temp;
}
unsigned long long base(unsigned x, unsigned base){
unsigned long long result = 0;
int i = 0;
while(x != 0){
result += (x%base)*power(10,i);
x = (x-(x%base))/base;
++i;
}
return result;
}
该函数以给定的底数计算出数字(这里我们以 3 为底数计算 27)。令我惊讶的是程序编译了,但不出所料输出给出了错误的答案(232 而不是预期的 1000),因为 return 类型是错误的。我想知道为什么编译器允许声明中的 return 类型是 bool
,即使它与定义中的 return 类型不对应。我的印象是函数原型必须与其相应的定义完全匹配,否则找不到函数?这很奇怪,因为我花了一些时间试图寻找问题,因为编译器没有提出它。
您看到的是未定义的行为:当您以与其前向声明不兼容的方式定义函数时,您的程序格式错误:
7.5.5: If two declarations declare functions with the same name and parameter-type-list (8.3.5) to be members of the same namespace or declare objects with the same name to be members of the same namespace and the declarations give the names different language linkages, the program is ill-formed; no diagnostic is required if the declarations appear in different translation units.
当您继续调用此类函数时,行为未定义。未定义的行为可以以任何它希望的方式表现出来。你的情况是调用成功了,但是返回值不正确。
如果没有你的帮助,编译器是没办法搞定的,因为两个函数之间的联系是由链接器完成的,而不是由编译器完成的。编译器做任何事情都为时已晚,因此您需要使用不同的方法:通过创建一个包含函数声明的头文件,然后在您定义的两个文件中包含相同的头文件来避免此类错误以及调用该函数的文件。
部分原因是它们是两个独立的编译单元,上面base()
的声明在编译第二个编译单元(又名源文件,粗略地说)。同样,base()
的实际定义在编译 main()
.
原因的第二部分是决定调用什么函数只使用参数的类型,而不是 return 类型。这意味着名称重整(对名称进行修饰,以便链接器可以将重载函数作为不同的函数接受)只需要编码有关函数参数类型的信息,而不是 return 类型。因此,链接器会将第二个编译单元中的定义视为与第一个编译单元中的声明相匹配。
最终结果是未定义的行为。
修复是为了确保在编译第二个单元时编译器可以看到第一个编译单元中的 base()
声明。换句话说,将声明放在头文件中,并 #include
在两个源文件中。然后编译器将拒绝 base()
的定义,因为它与前面的声明不匹配。