将字符数组 char u[10] 与字符串文字 "abc" 进行比较是否是未定义的行为

Is it undefined behavior to compare a character array char u[10] with a string literal "abc"

我找到了 this question on SO, and this 问题的答案。代码如下:

int main()
{

    char u[10];
    cout<<"Enter shape name ";
    cin>>u;
    if(u=="tri") //IS THIS UNDEFINED BEHAVIOR because the two decayed pointers both point to unrelated objects?
    {
        cout<<"everything is fine";
    }
    else
    {
        cout<<"Not fine";
    }
    return 0;
}

我在提到的答案中读到,u"tri" 都会衰减到指向其第一个元素的指针。我的问题是,现在正在比较这两个衰减的指针 未定义的行为 因为这些指针指向不相关的对象?或者程序是fine/valid(没有UB)因为指针取值不同,所以会执行else分支?

代码不会执行作者可能希望它执行的操作,但没有 UB。虽然将指向不相关对象的指针与 < 进行比较有未指定的结果,但检查相等性很好,比较将产生 false.

通过 == 比较指针在 compound#expr 中定义:

If at least one of the operands is a pointer, pointer conversions, function pointer conversions, and qualification conversions are performed on both operands to bring them to their composite pointer type. Comparing pointers is defined as follows:

(3.1) If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object, the result of the comparison is unspecified.

(3.2) Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal.

(3.3) Otherwise, the pointers compare unequal.

您的示例中的两个指针都不代表 [different] 完整对象的最后一个元素之后的地址。两个指针都不为空。它们不代表相同的地址。因此 u=="tri" 是错误的。

通过 < 比较指针是另一回事,因为指针值之间需要某种排序。要通过 == 比较两个指针,只关心它们的值是否相同。

标准说:

[expr.eq]

The == (equal to) and the != (not equal to) operators group left-to-right. The lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) standard conversions are performed on the operands...

因此,我们正在比较指向各个数组的指针。

If at least one of the operands is a pointer, ... Comparing pointers is defined as follows:

  • If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object,72 the result of the comparison is unspecified. [does not apply since neither pointer is past last element]
  • Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal. [does not apply since neither is null, neither point to functions, nor represent same address]
  • Otherwise, the pointers compare unequal. [applies]

行为已定义,否则分支将无条件执行。

Unconditionally unconditionally if-statements 暗示可能存在错误;很可能作者试图比较数组的内容,而操作员并没有这样做。


"warning: comparison with string literal results in unspecified behavior"

我认为此警告消息具有误导性。与两个字符串文字的比较将是未指定的:

if ("tri" == "tri")

未指定此条件是真还是假。

我认为这不会导致未定义的行为,但它肯定不会给出正确的结果。

使用调试器,查看您正在比较的值。例如,如果输入是 "tri":

u == { 't','r','i','[=10=]','[=10=]','[=10=]','[=10=]','[=10=]','[=10=]','[=10=]' }
"tri" == { 't','r','i','[=10=]' }

..如您所见,它们是不同的。从而导致他们的比较结果false.

您可以通过将 u 的大小设置为 4 (int u[4]) 然后给出输入 "tri" 来证明这一点。你会得到输出

everything is fine

但这不是一个灵活的修复,因为它不适用于输入 >< 而不是 3(或 4 通过计算 null termination character [=24 =]).要解决此问题,只需将您的 char array 转换为 std::string:

#include<iostream>
#include<string>

int main()
{
    char u[10]{};
    std::cout << "Enter shape name ";
    std::cin >> u;

    if (std::string(u) == "tri") // Works fine now
    {
        std::cout << "everything is fine";
    }
    else
    {
        std::cout << "Not fine";
    }
    return 0;
}

..或者直接使用std::string

std::string u;
std::cout << "Enter shape name ";
std::cin >> u;

if (u == "tri")
{
// ...