是在没有显式强制转换的情况下使用常量调用未定义的行为吗?

is using a constant without an explicit cast invoke undefined behavior?

在调用函数或从函数返回值时,期望类型为 T 的值,使用没有显式转换的常量文字会调用未定义的行为吗?

例如,我们有一个原型是long foo(unsigned long x);的函数 调用: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++ 中也有类似的部分)

intunsigned long 的隐式转换在 C 和 C++ 中都有明确的定义。 (在 C 部分 6.3.3.1)

should we write foo((unsigned long)4) and return (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; 情况永远不会是 UB,因为编译器在编译函数体内的代码时,函数的真实 return 类型是已知的。

不,这没有意义,因为这样的参数在 C 和 C++ 中都是按值传递的:

long foo(unsigned long x);

你可能会认为它是技术上的,因为 x 参数是在 foo 中定义的局部自动变量,并分配了传递参数的值:

unsigned long x = 4;

如果参数类型与参数不匹配,则编译器会尝试隐式转换。例如,double 类型的参数被静默转换为 unsigned long 类型,即使这意味着信息丢失(尽管您可能会收到编译器警告)。

然而,当您将 x 参数的类型标记为 reference(仅限 C++)时,您可能会遇到麻烦:

long foo(unsigned long& x);

在这里,编译器不允许您将其称为foo(4),因为您现在是通过引用传递,而4 不能这样修改。但是,如果参数标有 const 限定符:

,则可以传递它
long foo(const unsigned long& x);