gpt4 book ai didi

c++ - g++/gcc 中 char 的符号及其历史

转载 作者:太空狗 更新时间:2023-10-29 20:39:25 24 4
gpt4 key购买 nike

首先让我先声明,我知道 charsigned charunsigned char 在 C++ 中是不同的类型。从标准的快速阅读来看,char 是否 signed 似乎也是实现定义的。为了让事情变得更有趣,g++ 似乎决定了 char 是否在每个平台的基础上被签名!

所以不管怎样,在那个背景下,让我介绍一个我在使用这个玩具程序时遇到的错误:

#include <stdio.h>

int main(int argc, char* argv[])
{
char array[512];
int i;
char* aptr = array + 256;

for(i=0; i != 512; i++) {
array[i] = 0;
}

aptr[0] = 0xFF;
aptr[-1] = -1;
aptr[0xFF] = 1;
printf("%d\n", aptr[aptr[0]]);
printf("%d\n", aptr[(unsigned char)aptr[0]]);

return 0;
}

预期的行为是对 printf 的两次调用都应输出 1。当然,在 gccg++ 4.6.3 上会发生什么在 linux/x86_64 上运行是第一个 printf 输出 -1 而第二个输出 1。这与 chars 被签名和 g++ 解释一致-1 的负数组索引(这在技术上是未定义的行为)是明智的。

这个错误似乎很容易修复,我只需要将 char 转换为 unsigned ,如上所示。我想知道的是这段代码是否曾被期望在使用 gcc/g++ 的 x86 或 x86_64 机器上正常工作?看起来这可能在 ARM 平台上按预期工作,显然 chars 是无符号的,但我想知道这段代码在使用 g++ 的 x86 机器上是否一直存在错误?

最佳答案

我在你的程序中没有看到未定义的行为。负数组索引不一定无效,只要将索引添加到前缀的结果指向有效的内存位置即可。 (如果前缀是数组对象的名称或指向数组对象第 0 个元素的指针,则负数组索引是无效的(即具有未定义的行为),但这里不是这种情况。)

在这种情况下,aptr 指向 512 元素数组的元素 256,因此有效索引从 -256 到 +255(+256 产生刚好超过数组末尾的有效地址,但它不能被取消引用)。假设 CHAR_BIT==8signed charunsigned char 或普通 char 中的任何一个都有一个范围,该范围是数组有效索引范围的子集。

如果 plain char 被签名,那么:

aptr[0] = 0xFF;

会将 int0xFF (255) 隐式转换为 char ,并且该转换的结果是实现定义的——但它将在普通 char 的范围内,并且几乎肯定是 -1 。如果 plain char 是无符号的,那么它会将值 255 分配给 aptr[0] 。因此,代码的行为取决于普通 char 的签名(并且可能取决于实现定义的将超出范围的值转换为签名类型的结果),但没有未定义的行为。

(从 C99 开始,将超出范围的值转换为带符号的类型也可能会引发实现定义的信号,但我知道没有任何实现会真正做到这一点。在将 0xFF 转换为时引发信号char 可能会破坏现有代码,因此编译器编写者极力避免这样做。)

关于c++ - g++/gcc 中 char 的符号及其历史,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27803749/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com