我在某处看到这段代码,这不是整数溢出和未定义行为吗?
假设0 < str[i] < 127
char *msl_decrypt(char *str) {
char *decrypted;
unsigned int i;
int key = 0xFACA;
for (i = 0; i < strlen(str); ++i) {
str[i] = str[i] + key; // referring to this line, is it UB?
}
...
最佳答案
很遗憾您没有指定目标参数。所以对于以下我假设:
CHAR_BIT == 8
sizeof(int) >= 2
- 不是填充位
str
指向有效且已初始化的内存,该内存正确地以nul
结尾且不大于INT_MAX
(或者使用size_t
索引 - 感谢@chux)。- 可能还有其他我们倾向于视为理所当然的先决条件。
这些对于大多数现代实现来说都是典型的。
对于 sizeof(int) == 2
,初始化器是实现定义的行为,因为您使用 unsigned int
常量作为初始化器。对于更宽的 int
这没问题。如果 (int)(0xFACA) + CHAR_MAX > INT_MAX
(在算术上,也仅与 2 字节 int
相关),事情也会变得更加复杂。
其余部分以更复杂的方式依赖于实现定义的行为:
1)加法str[i] + key
:这里先将str[i]
转为int
,加法完成作为 int
并产生 int
结果。
2) 赋值str[i] = ...
:这里将加法的int
结果转换为char
。为此,我们有两种变体,具体取决于 char
的符号性(实现定义):
- unsigned:结果以标准定义的方式转换为
unsigned char
。 - signed:结果以实现定义的方式“向下”转换为“更小的”
signed char
。
因此:没有 未定义的行为,但这(和评论)表明在 C 中使用有符号整数时必须牢记多少。
但是:
涉及太多实现定义的行为,并且需要很多先决条件(尽管这很常见)。最好在整个代码中使用 unsigned char
和 unsigned int
。这将使代码符合标准并表现良好。即使对于 CHAR_BIT
值以外的值。如果您依赖 8 位值,请使用 stdint.h
中的 uint8_t
。
关于c - 这段代码是否是整数溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35350045/