为啥打印 unsigned char 有时有效,有时无效?在 C 中

Posted

技术标签:

【中文标题】为啥打印 unsigned char 有时有效,有时无效?在 C 中【英文标题】:Why does printing an unsigned char sometimes work and sometimes not? In C为什么打印 unsigned char 有时有效,有时无效?在 C 中 【发布时间】:2012-07-07 04:36:37 【问题描述】:

对于一个学校项目,我正在编写河豚加密(只是加密,而不是解密)。我已经完成了加密本身,我决定为了好玩而进行解密(在 Blowfish 中很容易)。

我使用无符号字符来表示字节(尽管我认为 uint8_t 会更便携)。当我试图打印出解密的字节时,我遇到了这个问题。我正在加密纯文本消息。我已经能够打印出我加密的实际短信,但仅限于一个非常特定的位置。相同的确切代码似乎在其他任何地方都不起作用。这里是:

int n;
for(n = 0; n < numBlocks; n++) // Blocks are 32-bit unsigned ints (unsigned long)

     // uchar is just a typedef for unsigned char
     // message is an array of uchars
     message[n] = (uchar) ((blocks[n]>>24));
     message[n+1] = (uchar) ((blocks[n]>>16));
     message[n+2] = (uchar) ((blocks[n]>>8));
     message[n+3] = (uchar) ((blocks[n]));
     // Printing works here; exact message comes back
     printf("%c%c%c%c", message[n], message[n+1], message[n+2], message[n+3]); 

但是当我尝试在两行之后使用完全相同的代码时,它不起作用

for(n = 0; n < numBlocks; n++)

     // Printing doesn't work here.
     // Actually, the first letter works, but none of the others
     printf("%c%c%c%c", message[n], message[n+1], message[n+2], message[n+3]); 

我也试过打印数字格式的字符,我可以看到它们实际上已经改变了。

这里到底发生了什么?这是未定义的行为吗?有没有人有可靠的解决方案?我没有做任何事情来改变两个调用之间的消息数组的值。

我正在使用 sparc 处理器的 Sun 5.10 上运行和编译它。

【问题讨论】:

如果字节值与人类可读的字符不对应,那么如果您使用%c,它们将不会有意义地显示。 那么,当你printf("%d %d %d %d\n", ...) 时你会得到什么? 你的“消息”数组内容如何变化?您是否尝试过在 gdb(或 xdb,我猜 Sun 编译器附带 xdb)下运行它,然后检查消息指向的内存块? 116 101 115 116 10 0 0 0 是我在第一个循环中得到的。 (字符串为“test\n”) 顺便说一句,如果定义了 uint8_tunsigned char 相同。使用格式宏PRIu8PRIx8unsigned char 使用格式字符串%hhu%hhx 打印uint8_t 【参考方案1】:
for(n = 0; n < numBlocks; n++) // Blocks are 32-bit unsigned ints (unsigned long)

     message[n] = (uchar) ((blocks[n]>>24));
     message[n+1] = (uchar) ((blocks[n]>>16));
     message[n+2] = (uchar) ((blocks[n]>>8));
     message[n+3] = (uchar) ((blocks[n]));

每次执行此循环时,将 message[n] 设置为 message[n+3],然后将 n 增加 1。这意味着您的第一次迭代设置message[0]message[1]message[2]message[3],然后您的第二次设置message[1]message[2]message[3]message[4]。因此,基本上,您在每次迭代时都会覆盖消息中除第一个字符之外的所有字符。

您很可能需要将 message 放大 4 倍,然后这样做:

message[n*4] = ...
message[n*4 + 1] = ...

【讨论】:

@TrgicPixel 不要难过,我想每个人都经历过。有时你只需要一个局外人从一个新的角度来看待你的代码来发现错误。

以上是关于为啥打印 unsigned char 有时有效,有时无效?在 C 中的主要内容,如果未能解决你的问题,请参考以下文章

为啥将 unsigned char 用于 RGB 像素数据?

如何将 unsigned char 打印为 ascii

如何在 C++ 中将 unsigned char[] 打印为 HEX?

为啥我不能声明 unsigned char* test = "Some text"

在 C 中使用 unsigned char 进行神奇打印

如何使用ostream在c ++中打印unsigned char作为十六进制?