无符号字符值循环 C++
Unsigned char value cycle C++
我(认为我)理解不同变量类型的数学运算。例如,如果我超过 unsigned int
变量的最大限制,它将循环回到 0
.
我不明白这段代码的行为 unsigned char
:
#include<iostream>
int main() {
unsigned char var{ 0 };
for(int i = 0; i < 501; ++i) {
var += 1;
std::cout << var << '\n';
}
}
这只是输出1...9
,然后是一些符号和大写字母,然后它什么都不打印。它不会循环回值 1...9
等
另一方面,如果我在打印前转换为 int
:
#include<iostream>
int main() {
unsigned char var{ 0 };
for(int i = 0; i < 501; ++i) {
var += 1;
std::cout << (int)var << '\n';
}
}
它确实从 1...255
打印,然后从 0...255
循环返回。
这是为什么?似乎 unsgined char
变量 执行 循环(正如我们从 int 转换中看到的那样)。
使用 unsigned char
变量进行数学运算安全吗?我在这里看到的行为是什么?
为什么它不打印预期的整数值?
问题不在于 char
的循环。问题在于 std::ostream
对象和 8 位整数类型的插入操作。这些类型的非成员 operator<<
函数将所有 8 位整数(char
、signed char
和 unsigned char
)视为它们的 ASCII 字符类型。
operator<<(std::basic_ostream)
处理输出 8 位整数类型的规范方式就是您的操作方式。我个人更喜欢这个:
char foo;
std::cout << +foo;
一元运算符 +
将 char
类型提升为 integer
类型,然后调用整数打印函数。
请注意,整数溢出仅针对 unsigned
整数类型定义。如果您使用 char
或 signed char
重复此操作,则该行为未被标准定义。肯定会发生一些事情,因为我们生活在现实中,但溢出行为可能因编译器而异。
为什么不重复 0..9 个字符
我使用 g++
进行编译测试,并在 Ubuntu 20.04 上使用 bash 进行测试。我的不可打印字符在某些情况下被处理为显式符号,或者在其他情况下不打印。非重复行为必须归因于您的 shell 处理这些不可打印字符的方式。如果没有更多信息,我们无法回答这个问题。
在这种情况下,无符号字符不会被视为数字。这种数据类型实际上是一个字节:
1 byte = 8 bits = 0000 0000 which means 0.
cout 正在打印的是表示您通过向其添加 +1 更改的字节的字符。
例如:
0 = 0000 0000
1 = 0000 0001
2 = 0000 0010
.
.
.
9 = 0000 1001
然后,这里开始其他与数字无关的字符。
所以,如果你把它转换成 int,它会给你那个字节的数字表示,给你一个 0-255 的输出。
希望这能说明问题!
编辑:使解释更清楚。
我(认为我)理解不同变量类型的数学运算。例如,如果我超过 unsigned int
变量的最大限制,它将循环回到 0
.
我不明白这段代码的行为 unsigned char
:
#include<iostream>
int main() {
unsigned char var{ 0 };
for(int i = 0; i < 501; ++i) {
var += 1;
std::cout << var << '\n';
}
}
这只是输出1...9
,然后是一些符号和大写字母,然后它什么都不打印。它不会循环回值 1...9
等
另一方面,如果我在打印前转换为 int
:
#include<iostream>
int main() {
unsigned char var{ 0 };
for(int i = 0; i < 501; ++i) {
var += 1;
std::cout << (int)var << '\n';
}
}
它确实从 1...255
打印,然后从 0...255
循环返回。
这是为什么?似乎 unsgined char
变量 执行 循环(正如我们从 int 转换中看到的那样)。
使用 unsigned char
变量进行数学运算安全吗?我在这里看到的行为是什么?
为什么它不打印预期的整数值?
问题不在于 char
的循环。问题在于 std::ostream
对象和 8 位整数类型的插入操作。这些类型的非成员 operator<<
函数将所有 8 位整数(char
、signed char
和 unsigned char
)视为它们的 ASCII 字符类型。
operator<<(std::basic_ostream)
处理输出 8 位整数类型的规范方式就是您的操作方式。我个人更喜欢这个:
char foo;
std::cout << +foo;
一元运算符 +
将 char
类型提升为 integer
类型,然后调用整数打印函数。
请注意,整数溢出仅针对 unsigned
整数类型定义。如果您使用 char
或 signed char
重复此操作,则该行为未被标准定义。肯定会发生一些事情,因为我们生活在现实中,但溢出行为可能因编译器而异。
为什么不重复 0..9 个字符
我使用 g++
进行编译测试,并在 Ubuntu 20.04 上使用 bash 进行测试。我的不可打印字符在某些情况下被处理为显式符号,或者在其他情况下不打印。非重复行为必须归因于您的 shell 处理这些不可打印字符的方式。如果没有更多信息,我们无法回答这个问题。
在这种情况下,无符号字符不会被视为数字。这种数据类型实际上是一个字节:
1 byte = 8 bits = 0000 0000 which means 0.
cout 正在打印的是表示您通过向其添加 +1 更改的字节的字符。
例如:
0 = 0000 0000
1 = 0000 0001
2 = 0000 0010
.
.
.
9 = 0000 1001
然后,这里开始其他与数字无关的字符。 所以,如果你把它转换成 int,它会给你那个字节的数字表示,给你一个 0-255 的输出。
希望这能说明问题!
编辑:使解释更清楚。