我们可以在C中反转这个字符串吗?

时间:2013-02-02 15:04:26

标签: c string format

我希望这很简单。这些是由反斜杠\分隔的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"

1 个答案:

答案 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个字节的序列。它们不是很多,你可以编写一个程序来模拟编译器的行为:

  • 如果xa中的任何一个,bf\n之类的其他转义序列不是十六进制数字)和e (由于GNU扩展)。它被映射到特殊字符。
  • (如果在源代码中使用大写字符,请注意\E映射到ESC)
  • 如果xy形成有效的八进制序列。它被映射到具有相应值的字符。
  • 如果x形成有效的八进制序列。它被映射到具有相应值的字符。
  • 否则,x保持不变。
  • 如果未使用y,则y保持不变。

请注意,实际char可能有两种不同的方式。例如,\f\14将映射到相同的char。在这种情况下,可能无法获取源中的字符串。你能做的最多就是猜测源代码中的字符串是什么。

以您的字符串为例,0833可以来自\b3,但它也可以来自\10\63

使用map产生,有些情况下映射是明确的:大于3f的十六进制不能来自八进制转义序列,并且必须来自原始字符串中字符的直接解释。从此,您知道如果遇到e,它必须是看起来像十六进制序列中的第二个字符。

您可以使用地图作为指南,并将模拟作为检查地图是否会生成ASCII代码的方法。在不知道源代码中声明的字符串的任何内容的情况下,您可以导出的最多是源代码中原始(损坏)字符串的候选列表。如果您至少知道源代码中字符串的长度,则可以减小候选列表的大小。