相关疑难解决方法(0)

在循环中的什么时候整数溢出变成未定义的行为?

这是一个例子来说明我的问题,其中涉及一些我不能在这里发布的更复杂的代码.

#include <stdio.h>
int main()
{
    int a = 0;
    for (int i = 0; i < 3; i++)
    {
        printf("Hello\n");
        a = a + 1000000000;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个程序在我的平台上包含未定义的行为,因为它a会在第3个循环中溢出.

这是否会使整个程序具有未定义的行为,或者仅在溢出实际发生之后?编译器是否可能a 会解决溢出问题,因此它可以声明整个循环未定义,并且不会打扰运行printfs,即使它们都在溢出之前发生?

(标记为C和C++,即使它们不同,因为如果它们不同,我会对这两种语言的答案感兴趣.)

c c++ integer-overflow undefined-behavior

85
推荐指数
7
解决办法
1万
查看次数

枚举常量在C和C++中表现不同

为什么这样:

#include <stdio.h>
#include <limits.h>
#include <inttypes.h>

int main() {
    enum en_e {
        en_e_foo,
        en_e_bar = UINT64_MAX,
    };
    enum en_e e = en_e_foo;
    printf("%zu\n", sizeof en_e_foo);
    printf("%zu\n", sizeof en_e_bar);
    printf("%zu\n", sizeof e);
}
Run Code Online (Sandbox Code Playgroud)

4 8 8用C和8 8 8C++ 打印(在4字节整数的平台上)?

我的印象是,UINT64_MAX赋值将强制所有枚举常量至少为64位,但en_e_foo在纯C中保持为32.

这种差异的理由是什么?

c c++

81
推荐指数
6
解决办法
4529
查看次数

constexpr未定义的行为

我一直在试验constexpr.在我的测试编译器(g ++ 4.6)上,无法编译带有关于越界访问的错误.是一个编译器需要在编译时被发现呢?

#include <iostream>

constexpr const char *str = "hi";

constexpr int fail() {
  return str[1000]; // Way past the end!
}

template <int N>
struct foo {
  static void print() { std::cout << N << std::endl; }
};

int main() {  
  foo<fail()>::print();
}
Run Code Online (Sandbox Code Playgroud)

c++ undefined-behavior language-lawyer c++11

18
推荐指数
2
解决办法
933
查看次数

编译时和运行时未定义的行为

我仍然无法准确指出实际定义了未定义行为的级别。假设以下代码:

int i = value;
unsigned int x = static_cast<unsigned int>(i);
Run Code Online (Sandbox Code Playgroud)

这是有效的 C++ 代码并定义为 egi1. 但是i = -1它变成了未定义的行为,因此应用程序在运行时处于 UB 状态。

在下面的代码示例中,UB 在编译时已经很明显了。所以我的问题是,UB 可以在编译时或运行时出现是否正确?这里的正确术语是什么?

void foo(int* p)
{
    int v = *p;
    if (p == nullptr)
        return;
}
Run Code Online (Sandbox Code Playgroud)

c++ undefined-behavior

5
推荐指数
0
解决办法
99
查看次数

是否保证在计算常量表达式时捕获所有形式的未定义行为

我遇到了以下主张

实际上,在计算常量表达式时,需要捕获该语言中所有形式的 UB(尽管标准库中的 UB 不需要捕获)。只有运行时 UB 才可能发生任何事情。

(强调我的)

我的问题是上述说法在技术上正确吗?

在询问用户标准如何强加这一点时,他们引用了expr.const#5.8,其中指出:

5.表达式 E 是核心常量表达式,除非对 E 的计算遵循抽象机 ([intro.execution]) 的规则,将计算以下其中一项:

5.8. 具有 [intro] 到 [cpp] 中指定的未定义行为的操作;

但在阅读了上面的[expr.const#5.8]之后,我无法弄清楚这如何意味着在计算常量表达式时需要捕获语言中所有形式的 UB。那么有人可以澄清这个引文如何支持(如果支持的话)上面引用的评论中提出的主张吗?


我还读过这样的内容:

如果行为未定义,编译器可以接受它,拒绝它,发出警告,并根据标准,甚至在您的计算机上崩溃、挂起或安装病毒。

因此,在我看来(在阅读第一条评论后),常量表达式求值期间的 UB 和运行时 UB 之间存在根本区别。

真相是什么?

c++ undefined-behavior language-lawyer

5
推荐指数
1
解决办法
251
查看次数

在编译阶段扩展"未定义行为"的原因是什么?

在编译阶段扩展UB的原因是什么?遇到UB代码时,不是编译和链接二进制文件,而是让二进制文件服从UB?(如果不可能生成二进制文件,那么只需打印一条关于它的错误消息.)

毕竟,我们期望从编译器的最确切的报告汇编即使在源代码中包含UB-代码(几乎每件的源代码可能包含一些UB-代码).

您能给这样的UB-代码一个具体的例子,这确实更有道理,让编译器表现出UB比让生成的二进制表现出UB?

这个问题源于这一点:"未定义的行为"是否扩展到编译时?

c++

-1
推荐指数
1
解决办法
162
查看次数