我希望这很简单。这些是由反斜杠\
分隔的20个十六进制值,C编译器确实使它们成为33个字符的字符串,因为\NUMBER
是单值\NUMBER+ALPHA
= 2个字节以及{{1 2个字节。
\ALPHA+NUMBER
我的问题是在磁盘上保存到33个字节后,我们(在读取33个字节后)可以重新制作我们在C中的相同演示文稿吗?那么程序打印char str[] =
"\b3\bc\77\7\de\ed\44\93\75\ce\c0\9\19\59\c8\f\be\c6\30\6";
//when saved is 33 bytes
,这里有任何解决问题的方法吗?
"\b3\bc\77\7\de\ed\44\93\75\ce\c0\9\19\59\c8\f\be\c6\30\6"
答案 0 :(得分:2)
您拥有的字符串文字:
"\b3\bc\77\7\de\ed\44\93\75\ce\c0\9\19\59\c8\f\be\c6\30\6"
将根据C89生成未定义的行为(不确定C89的源是否可信,但我的观点仍然存在)和根据C11标准实现定义的行为。特别是,\d
,\e
,\9
,\c
是未在标准中定义的转义序列。 gcc
不会抱怨\e
,因为它是一个GNU扩展,代表ESC。
由于存在实现定义的行为,因此我们必须知道您正在使用的编译器,因为结果可能会有所不同。
另一件事是,你没有显示清楚你知道编译后字符串的内容。 (一种更清晰的展示方式是在内存中包含字符串的十六进制转储,并显示您如何知道转义序列。)
这就是编译器识别看起来像十六进制字符串的方式:
String: \b 3 \b c \77 \7 \d e \e d \44 \9 3 \75 \c e \c 0 \9 \1 9 \5 9 \c 8 \f \b e \c 6 \20 \6
Char: \b 3 \b c \77 \7 d e \e d \44 \9 3 \75 c e c 0 9 \1 9 \5 9 c 8 \f \b e c 6 \20 \6
Hex: 08 33 08 63 3f 07 64 65 1b 64 24 39 33 3d 63 65 63 30 39 01 39 05 39 63 38 0c 08 65 63 36 18 06 00
在灌木丛周围挨打。假设您使用gcc
编译代码(忽略警告)。运行代码时,使用char[]
将整个fwrite
写入文件。我还假设在源代码中只使用了小写字符。
您应该将看起来像2位十六进制数的所有可能的转义序列\xy
映射到1或2个字节的序列。它们不是很多,你可以编写一个程序来模拟编译器的行为:
x
是a
中的任何一个,b
,f
(\n
之类的其他转义序列不是十六进制数字)和e
(由于GNU扩展)。它被映射到特殊字符。\E
映射到ESC)xy
形成有效的八进制序列。它被映射到具有相应值的字符。x
形成有效的八进制序列。它被映射到具有相应值的字符。x
保持不变。y
,则y
保持不变。请注意,实际char
可能有两种不同的方式。例如,\f
和\14
将映射到相同的char
。在这种情况下,可能无法获取源中的字符串。你能做的最多就是猜测源代码中的字符串是什么。
以您的字符串为例,08
和33
可以来自\b3
,但它也可以来自\10\63
。
使用map产生,有些情况下映射是明确的:大于3f
的十六进制不能来自八进制转义序列,并且必须来自原始字符串中字符的直接解释。从此,您知道如果遇到e
,它必须是看起来像十六进制序列中的第二个字符。
您可以使用地图作为指南,并将模拟作为检查地图是否会生成ASCII代码的方法。在不知道源代码中声明的字符串的任何内容的情况下,您可以导出的最多是源代码中原始(损坏)字符串的候选列表。如果您至少知道源代码中字符串的长度,则可以减小候选列表的大小。