[英]is using a constant without an explicit cast invoke undefined behavior?
Upon invoking a function,or returning a value from a function,that expects a value of type T
,does using a constant literal without explicit cast invoke undefined behavior? 在调用一个函数或从一个函数返回一个期望值为
T
类型的值的值时,是否使用不带显式强制转换的常量文字调用未定义的行为?
For example,we have a function who's prototype is long foo(unsigned long x);
例如,我们有一个函数的原型是
long foo(unsigned long x);
Invocation: foo(4); //does this invoke UB?
调用:
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 ?
should we write foo((unsigned long)4)
and return (long)10
?? 我们应该写
foo((unsigned long)4)
并return (long)10
吗?
No, it is all well-defined. 不,这都是定义明确的。
There exists an implicit conversion rule between the two types, so the int
is simply converted to an unsigned long
and the program works as expected. 两种类型之间存在一个隐式转换规则,因此
int
会简单地转换为unsigned long
,并且程序会按预期运行。
Type of literal 4
is int
. 文字
4
类型为int
。 (In C section 6.4.4.1 Integer constants, similar section available in C++ also) (在C节6.4.4.1整数常量中,类似的节在C ++中也可用)
Implicit conversion from int
to unsigned long
is well defined in both C and C++. 在C和C ++中都很好地定义了从
int
到unsigned long
隐式转换。 (In C section 6.3.3.1) (在C第6.3.3.1节中)
should we write foo((unsigned long)4) and return (long)10?
我们应该写foo((unsigned long)4)并返回(long)10吗?
Both of your example are well defined, so this conversion though acceptable is superfluous. 您的两个示例均定义良好,因此尽管可以接受这种转换是多余的。
Consider this C code: 考虑下面的C代码:
// foo.c
int foo(unsigned long x) { }
and 和
// main.c
int foo();
int main()
{
foo(4); // UB
foo((unsigned long)4); // OK
}
The foo(4)
call is UB because when you are calling a function with no prototype in scope, you must manually make sure the parameters match. foo(4)
调用是UB,因为在调用范围内没有原型的函数时,必须手动确保参数匹配。 The default argument promotions occur but that's all. 默认参数提升出现,仅此而已。
Of course, writing the cast is a bad solution from the point of view of writing robust code. 当然,从编写健壮的代码的角度来看,编写强制转换是一个不好的解决方案。 The better solution would be to write a prototype:
更好的解决方案是编写一个原型:
int foo(unsigned long);
in a header file which is included from both the .c
files. 包含在两个
.c
文件中的头文件中。
The return 10;
return 10;
case can never be UB because the function's true return type is known to the compiler when it is compiling the code inside the function body. case永远不能是UB,因为编译器在编译函数体内的代码时会知道函数的真实返回类型。
No, it wouldn't make sense, since such argument is passed by value in both C and C++: 不,这没有意义,因为这样的参数在C和C ++中都是通过值传递的 :
long foo(unsigned long x);
You may think of it technicaly as x
parameter is a local automatic variable defined inside foo
and assigned with the value of passed argument: 您可能认为它是技术上的,因为
x
参数是在foo
内部定义的本地自动变量,并分配有传递参数的值:
unsigned long x = 4;
If type of argument does not match with parameter, then compiler tries with implicit conversion. 如果参数的类型与参数不匹配,则编译器将尝试进行隐式转换。 For instance, an argument of type
double
is silenty converted into of type unsigned long
, even it means loss of information (you might get a compiler warning though). 例如,将
double
类型的参数静默转换为unsigned long
类型,即使这意味着信息丢失(尽管您可能会收到编译器警告)。
You may however get into trouble, when you mark type of x
parameter as reference (C++ only): 但是,当您将
x
参数的类型标记为引用时,可能会遇到麻烦(仅C ++):
long foo(unsigned long& x);
Here, the compiler would not allow you to call it as foo(4)
, because you are now passing by reference, and 4
cannot be modified as such. 在这里,编译器不允许您将其称为
foo(4)
,因为您现在通过引用传递,并且不能这样修改4
。 You may however pass it if the parameter is marked with const
qualifier: 但是,如果参数用
const
限定符标记,则可以传递它:
long foo(const unsigned long& x);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.