[英]is using a constant without an explicit cast invoke undefined behavior?
在调用一个函数或从一个函数返回一个期望值为T
类型的值的值时,是否使用不带显式强制转换的常量文字调用未定义的行为?
例如,我们有一个函数的原型是long foo(unsigned long x);
调用: foo(4); //does this invoke UB?
foo(4); //does this invoke UB?
long foo(unsigned long x) { x += 10; return 10; } // does this invoke UB ?
我们应该写foo((unsigned long)4)
并return (long)10
吗?
不,这都是定义明确的。
两种类型之间存在一个隐式转换规则,因此int
会简单地转换为unsigned long
,并且程序会按预期运行。
文字4
类型为int
。 (在C节6.4.4.1整数常量中,类似的节在C ++中也可用)
在C和C ++中都很好地定义了从int
到unsigned long
隐式转换。 (在C第6.3.3.1节中)
我们应该写foo((unsigned long)4)并返回(long)10吗?
您的两个示例均定义良好,因此尽管可以接受这种转换是多余的。
考虑下面的C代码:
// foo.c
int foo(unsigned long x) { }
和
// main.c
int foo();
int main()
{
foo(4); // UB
foo((unsigned long)4); // OK
}
foo(4)
调用是UB,因为在调用范围内没有原型的函数时,必须手动确保参数匹配。 默认参数提升出现,仅此而已。
当然,从编写健壮的代码的角度来看,编写强制转换是一个不好的解决方案。 更好的解决方案是编写一个原型:
int foo(unsigned long);
包含在两个.c
文件中的头文件中。
return 10;
case永远不能是UB,因为编译器在编译函数体内的代码时会知道函数的真实返回类型。
不,这没有意义,因为这样的参数在C和C ++中都是通过值传递的 :
long foo(unsigned long x);
您可能认为它是技术上的,因为x
参数是在foo
内部定义的本地自动变量,并分配有传递参数的值:
unsigned long x = 4;
如果参数的类型与参数不匹配,则编译器将尝试进行隐式转换。 例如,将double
类型的参数静默转换为unsigned long
类型,即使这意味着信息丢失(尽管您可能会收到编译器警告)。
但是,当您将x
参数的类型标记为引用时,可能会遇到麻烦(仅C ++):
long foo(unsigned long& x);
在这里,编译器不允许您将其称为foo(4)
,因为您现在通过引用传递,并且不能这样修改4
。 但是,如果参数用const
限定符标记,则可以传递它:
long foo(const unsigned long& x);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.