-2

とてもシンプルです。これらはバックスラッシュで区切られた 20 の 16 進数値で\あり、C コンパイラは実際に 33 文字の文字列を作成します。これ\NUMBERは、単一の値\NUMBER+ALPHA= 2 バイトと 2 バイトであるため\ALPHA+NUMBERです。

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

私の質問は、ディスクに 33 バイトに保存された後、(33 バイトを読み取った後) C で作成したのと同じプレゼンテーションを作り直すことはできますか? したがって、プログラムは を出力"\b3\bc\77\7\de\ed\44\93\75\ce\c0\9\19\59\c8\f\be\c6\30\6"します。ここに問題解決者はいますか?

"\b3\bc\77\7\de\ed\44\93\75\ce\c0\9\19\59\c8\f\be\c6\30\6";
//when read back program should output this ^
4

1 に答える 1

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いないエスケープ シーケンスです。ESC を表す GNU 拡張であるため、gccについて文句を言うことはありません。\e

実装定義の動作があるため、結果が異なる可能性があるため、使用しているコンパイラを知る必要があります。

もう 1 つのことは、コンパイル後に文字列の内容を認識していることを明確に示していないことです。(表示するより明確な方法は、文字列がメモリ内でどのように見えるかの 16 進ダンプを含め、エスケープ シーケンスをどのように認識しているかを示すことです)。

これは、16 進数のような文字列がコンパイラによってどのように認識されるかです。

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。また、ソースコードでは小文字のみが使用されていると想定しています。

\xy2 桁の 16 進数のように見えるすべての可能なエスケープ シーケンスを 1 または 2 バイトのシーケンスにマップする必要があります。それらの数はそれほど多くなく、コンパイラーの動作をシミュレートするプログラムを作成できます。

  • , , (その他のエスケープ シーケンスは 16 進数ではありません) および(GNU 拡張による) のxいずれかである場合。特殊文字にマップされます。abf\ne
  • (ソース コードで大文字を使用する場合は、\EESC にマップされることに注意してください)
  • xy有効な 8 進シーケンスを形成する場合。対応する値を持つ文字にマップされます。
  • x有効な 8 進シーケンスを形成する場合。対応する値を持つ文字にマップされます。
  • そうでなければ、x同じままです。
  • y消費されなければyそのまま。

実際のchar値は 2 つの異なる方法で取得できることに注意してください。たとえば、\f\14は同じ にマップされcharます。このような場合、ソース内の文字列を取得できない可能性があります。できることは、ソース内の文字列が何であるかを推測することです。

08最初に文字列を例として使用し、から取得することも33できますが\b3、 から取得することもできます\10\63

マップ生成を使用すると、マッピングが明確な場合があります。16 進数より大きい 16 進数は3f、8 進数のエスケープ シーケンスから取得できず、元の文字列の文字を直接解釈して取得する必要があります。eこのことから、 が検出された場合、それは 16 進数のように見えるシーケンスの 2 番目の文字でなければならないことがわかります。

マップをガイドとして使用し、シミュレーションを方法として使用して、マップが ASCII コードを生成するかどうかを確認できます。ソース コードで宣言されている文字列について何も知らなくても、派生できるのはソース コード内の元の (壊れた) 文字列の候補のリストだけです。少なくともソース コード内の文字列の長さがわかっている場合は、候補のリストのサイズを減らすことができます。

于 2013-02-02T17:29:40.010 に答える