4

次のコード フラグメントがあります。

char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
printf("%s\n", tab);

への呼び出しでエラー/警告が表示されない理由がわかりませんprintf警告は表示されますが、エラーは表示されず、プログラムは正常に実行されます。' ' が出力されます12
printfは 型の引数char *、つまり へのポインタを期待していますchar。したがって、 を宣言した場合char arr[3]arrは を含むメモリ ユニットのアドレスであるcharため、それを使用して呼び出すと、 char へのポインタ、つまりにprintf減衰します。 同様に、は3 文字の型配列を含むメモリ ユニットのアドレスであり、メモリ ユニットのアドレスには が含まれているため、に減衰し、問題になるはずです。char *
tabchartabchar **printfchar *.

誰かがこの問題を説明できますか?

補遺:

私が得る警告は次のとおりです。
a.c:6: warning: char format, different type arg (arg 2)

4

4 に答える 4

6

ソースの例

#include <stdio.h>

int main( void ) {
  char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
  printf("%s\n", tab);

  return 0;
}

警告をコンパイルします

$ gcc test.c
test.c:関数'main'内:
test.c:5:警告:フォーマット'%s'はタイプ'char *'を予期していますが、引数2のタイプは'char(*)[3]' </ pre>

ポインタはポインタです

toの%s引数printfは、(文字列への)ポインタを受け取ることを関数に示します。Cの文字列は、ASCII-Zで終了する一連のバイトにすぎません。tab[2][3]変数はポインターです。一部のコンパイラは、ポインタの不一致に関する警告を発行します。ただし、コードは、指定されたポインタから開始して(文字を出力しながら)ゼロバイトが見つかるまでメモリをトラバースする12ため、コードは出力されます。printf1、2、および\ 0は、tab変数で表されるアドレスから開始して、連続してメモリに設定されます。

実験

実験として、次のコードをコンパイルして実行するとどうなりますか。

#include <stdio.h>

int main( void ) {
  char tab[2][3] = {'1', '2', '\0', '3', '4', '\0'};
  printf("%s\n", tab[1]);

  return 0;
}

実験することを恐れないでください。あなたが今知っていることに基づいて答えを思い付くことができるかどうか見てください。tab警告を取り除き、引き続き表示するために、(実験に照らして)今どのように参照します12か?

于 2009-06-29T08:26:19.040 に答える
4

tabパラメーターは、printf()呼び出しの省略形と一致します。CおよびC++コンパイラは、そのようなパラメータをチェックする義務を負いません。

于 2009-06-29T08:28:22.700 に答える
4

tabに減衰するというあなたの仮定char **は間違っています: tabtypechar [2][3]を持っています。つまり、 に減衰しchar (*) [3]ます。配列とポインターはよく似た動作をしますが、同じものではないことを理解することが重要です。printf()は を期待しているchar *ので、 のビットを受け取り、それchar (*) [3]に応じて解釈します。お使いのプラットフォームで動作しますが、C 標準はこれを保証しません。両方のポインターが同じメモリ位置を参照しますが、それらの表現は同一である必要はありません。

詳細については、この関連する質問に対する私の回答を確認してください。

于 2009-06-29T09:02:04.803 に答える
1

あなたはそれを自分で説明したようですが、何を言うべきかわかりません。

tab2 つの の配列ですchar *。の各要素は受け入れることができるtab文字列ですが、char へのポインタへのポインタであるため、それ自体は受け入れられません。printftab

于 2009-06-29T08:24:36.297 に答える