我试图将一个不可打印的ASCII字符串转换为二进制.这是代码:
int main(int argc, char *argv[]) { char str[32]; sprintf(str,"\x01\x00\x02"); printf("\n[%x][%x][%x]",str[0],str[1],str[2]); return 1; }
我希望输出应该是[1] [0] [2],但它打印[1] [0] [4].
我在这做错了什么?
该sprintf
操作在一审结束了\x00
在你的字符串字面量,因为NUL(U + 0000)终止字符串在C(当你写的编译器不会抱怨\x00
一个字符串内,可以说是语言的不良特性).因此str[2]
访问未初始化的内存和程序有权打印完全废话甚至崩溃.
要做你想做的事,只需消除sprintf
:
int main(void) { static const unsigned char str[32] = { 0x01, 0x00, 0x02 }; // will be zero-filled to declared size printf("[%02x][%02x][%02x]\n", str[0], str[1], str[2]); return 0; }
(二进制数据应始终存储在unsigned char 数组中,而不是普通char;或者uint8_t
如果你有.因为U + 0000终止字符串,我认为使用数组文字而不是字符串文字来编写嵌入式二进制数据是更好的方式;但它更多的static const
是打字.这只是因为数据永远不会被修改并且在编译时就已知;程序在没有它的情况下就可以工作.不要声明argc
,argv
如果你不打算使用它们.返回零,而不是一个,来自main
表示成功完成.)
(sprintf
由于其他原因,使用你使用它的方式是一个坏主意:例如,如果你的二进制块包含\x25
(也称为%
ASCII),它将尝试读取待格式化的其他参数,并再次打印完成无意义或崩溃.如果你有充分的理由不仅仅使用静态初始化数据,那么复制二进制数据块的正确方法是memcpy
.)
C字符串以空字节结尾,因此sprintf
只读取直到\x00
.相反,您可以使用memcpy
(像这样)或简单地初始化
char str[32] = "\x01\x00\x02";