如果 char c = 0x80,为什么 printf("%d\n", c << 1) 输出 -256?

发布于 2024-09-29 01:22:04 字数 241 浏览 7 评论 0 原文

#include<stdio.h>
int main(void)
{
  char c = 0x80;
  printf("%d\n", c << 1);
  return 0;
}

在本例中,输出为 -256。如果我写 c << 0 则输出为 -128

我不明白这段代码背后的逻辑。

#include<stdio.h>
int main(void)
{
  char c = 0x80;
  printf("%d\n", c << 1);
  return 0;
}

The output is -256 in this case. If I write c << 0 then the output is -128.

I don't understand the logic behind this code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

谈场末日恋爱 2024-10-06 01:22:04

char 可能在您的平台上进行签名,在这种情况下,0x80 代表 -128(假设二进制补码)。

char 用作 << 运算符的操作数时,它会被提升为 int(仍然是 -128)。所以当你应用左移时,你会得到-256。从技术上讲,改变负值是实现定义未定义的,但您看到的是典型行为。

char may be signed on your platform, in which case 0x80 represents -128 (assuming two's complement).

When a char is used as an operand with the << operator, it is promoted to int (still -128). So when you apply the left-shift, you get -256. Technically, shifting negative values is implementation-defined undefined, but what you see is typical behaviour.

烟酒忠诚 2024-10-06 01:22:04

您的出发点已经有问题了:

char c = 0x80;

如果(在您的情况下似乎) char 是有符号类型,则您将整数常量 128 分配给仅保证的类型保留最大 127 的值。然后,您的编译器可能会选择为您提供一些实现定义的值(我猜在您的情况下为 -128 )或发出范围错误。

然后你就对该负值进行左移。这会产生未定义的行为。总的来说,您有几个实现定义的选择以及决定结果的未定义行为:

  • char 的符号性、
  • 如何将 128 转换为 signed char 的选择
  • char 的宽度
  • int 的符号表示(存在三种可能性)
  • 选择如何实现(或不实现)负 int 上的左移>

对您来说,查找所有这些案例并看看可能有什么不同的结果可能是一个很好的练习。

总之,一些建议:

  • 选择适当的常量来初始化变量
  • 不要使用普通的 char 进行算术
  • 不要对有符号类型进行左移

Already your starting point is problematic:

char c = 0x80;

If (as seemingly in your case) char is a signed type, you are assigning the integer constant 128 to a type that is only guaranteed to hold values up to 127. Your compiler then may choose to give you some implementation defined value (-128 in your case I guess) or to issue a range error.

Then you are doing a left shift on that negative value. This gives undefined behavior. In total you have several implementation defined choices plus undefined behavior that determine the outcome:

  • signedness of char
  • the choice of how to convert 128 to signed char
  • the width of char
  • the sign representation of int (there are three possibilities)
  • the choice on how to implement (or not) left shift on negative int

It may be a good exercise for you to look up all these case an to see what the different outcomes may be.

In summary some recommendations:

  • choose an appropriate constant to initialize a variable
  • don't do arithmetic with plain char
  • don't do left shift on signed types
朕就是辣么酷 2024-10-06 01:22:04

c 被分配为 0x80。假设 8 位字节,其二进制表示值为 10000000。显然,在您的平台上,char 是一种签名类型。因此,0x80(即10000000)对应于-128。

<< 应用于 char 值时,它会提升为 int 并保留符号。因此,当使用 32 位整数向左移动一次时,它会变成 11111111111111111111111100000000 (二进制补码),即 -256。

c is assigned 0x80. Assuming 8-bit bytes, its value in binary representation, is 10000000. Apparently, on your platform, char is a signed type. So, 0x80 (i.e. 10000000) corresponds to -128.

When << is applied to a char value, it is promoted to int and the sign is preserved. So, when shifted once to the left, with 32-bit integers, it becomes 11111111111111111111111100000000 (two's complement) which is -256.

吾性傲以野 2024-10-06 01:22:04

只是一个旁注。从自下而上的角度来看,按位移位(和掩码)基于体系结构的字长(以位表示)。单词的长度因建筑而异。

请参阅此 Wiki 页面了解不同架构

的字长 在目标体系结构中,可以使用位移来进行乘法和除法(在某些情况下),比使用操作数更快。

请参阅此 Wiki 页面,了解有趣的位移位图

依赖于体系结构,我们不能假设一段特定的位移代码在不同的体系结构中都会以相同的方式工作。然而,一旦熟悉了不同架构的不同字长的概念,位移就变得不那么神秘并且更可预测了。

值得庆幸的是,今天我们有 8 位、16 位、32 位和 64 位字长,并且只有 8 位字符长度。在古代计算时代,架构可能有 12 位、15 位或 23 位字长(等等,令人作呕)。

Just a side-note. From a bottom up perspective, bit-wise shifting (and masking) is based on an architecture's word-length (expressed in bits). The length of a word, varies from architecture to architecture.

See this Wiki page for word lengths by architecture

If one knows the word length of the target architecture, one can use bit-shifting to multiply, and divide (in some cases), faster than using operands.

See this Wiki page for interesting diagrams of bit-shifting

Since bit-shifted code is architecture dependent, one cannot assume a specific piece of bit-shifted code will work the same way from architecture to architecture. However, once one is familiar with the idea of different word lengths for different architectures, bit-shifting becomes less mysterious and more predictable.

Thankfully, today we have 8, 16, 32, and 64 bit word lengths, and exclusively 8 bit character lengths. In the days of ancient computing, an architecture might have a 12, or a 15, or a 23 bit word length (etc., ad nauseum).

对你而言 2024-10-06 01:22:04

我想知道为什么你的编译器不会抱怨 0x80 不适合 char 的警告,在你的平台上它只能表示从 -0x80 到 0x7F 的值。

尝试这段代码:

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

 int main() {
      printf("char can represent values from %d to %d.\n", CHAR_MIN, CHAR_MAX);
      return EXIT_SUCCESS;
 }

您的情况称为溢出。

I wonder why your compiler do not complain with a warning that 0x80 does not fit in char, which on your platform can represent only values from -0x80 to 0x7F.

Try this piece of code:

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

 int main() {
      printf("char can represent values from %d to %d.\n", CHAR_MIN, CHAR_MAX);
      return EXIT_SUCCESS;
 }

Your situation is called OVERFLOW.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文