1

私はCプログラミングの経験が比較的豊富です。それは私のお気に入りの言語の 1 つです。今日、シェル プログラミングについて勉強しているときに、Linux システム (Backtrack 5 r2) で実行した ac プログラムに出くわしました。そして、プログラムは私が本当に理解できなかった奇妙な出力をしました。

これがコードです...

#include <stdio.h>

int main(int argc, char *argv[])
{
    char array[] = { 0x25, 115, 0 };
    char array2[] = { 68, 0x61, 118, 0x69, 0144, 040,
                      0107, 97, 0x74, 119, 0157, 0x6f,
                      100, 0x20, 0x72, 117, 'l', 0x65,
                      115, 041, 012, 0 };

    printf(array, array2);
}

gcc を使用してこのコードをコンパイルし、実行時に次のような出力を得ました。

デビッド・ガットウッドが支配!

この出力を取得した方法と理由を本当に理解できませんでした。私の知る限り、配列の名前を「printf」に渡すと、配列のベースアドレス、つまり配列の0番目の要素のアドレスが出力されます。これも、「printf」ステートメントで適切な書式指定子が使用されている場合にのみ、適切に表示されます。

では、どこが間違っているのか、重要なことを見落としているのか、それとも gcc が原因なのか?

4

3 に答える 3

4

と考えarrayてください"%s"。したがって、printf文字列を出力します。

ASCII 0x25: %
ASCII 115:  s

についても同様ですarray2。ただし、著者が10進数と8進数を混在させる理由はわかりません。

于 2013-03-02T07:57:48.053 に答える
3

このプログラムは難読化された書き方です

#include <stdio.h>

int main(int argc, char *argv[])
{
    char array[] = { '%', 's', '\0' };
    char array2[] = { 'D', 'a', 'v', 'i', 'd', ' ', ..., '\0' };

    printf(array, array2);
}

printf は形式として文字列を想定しており、このような式で使用される配列名は (「減衰」、この用語は公式の標準語ではありませんが) 最初の要素へのポインターとして扱われるため、すべて適切です。実際、初期化は次と同等です

char *array = "%s";
char *array2 = "David ...";

ただし、後者は書き込み可能ではありません (文字列リテラルは C では読み取り専用であるため)。

いいえ、配列を printf (正確にはどこに?) に渡しても、そのアドレスは出力されません。配列アドレス (またはポインター) の出力は、%p変換指定子でのみ実行できます。

printf ("array/ptr address = %p\n", (void *)array);

未定義の動作を避けるために(void *)キャストが必要であることに注意してください。

于 2013-03-02T08:42:26.450 に答える
0

あなたprintf("%s", "David Gatwood rules!"); が書いたように、c の経験があるとしたら、c 文字列として使用される文字を含む char 配列へのポインターも見たことがあるはずです。

于 2013-03-02T12:43:02.197 に答える