配列をprintfに直接渡すことはできますか?
char text[1024] = "text";
printf("%s", text);
または、明示的にcharポインターにキャストする必要があります。
char text[1024] = "text";
printf("%s", (char*) text);
最初の要素へのポインタだけを置くのではなく、配列要素をva_listに直接コピーするのではないかと思ったので質問しています。
はい、配列を直接渡すことができます。正確には、配列の名前は配列のアドレスを表し、。との違いはありませんchar *
。
(char*)text
text
この例ではほとんど違いはありません!配列のベースアドレスは、関数の引数として渡されるとポインタに減衰します。
実際、配列でtext
なくても、可変引数関数であるため、char
ほとんど違いはありません。printf
int printf(const char *format, ...);
そしてそれが気にするのは最初の議論についてです。ロジックがうまくいかないかもしれませんがprintf
、気にしません!
簡単に言えば、はい、Cの配列は最初の要素へのポインタです。 (編集:長い答え、実際には、Cの配列は単なる名前である識別子またはラベルですが、前に&またはsizeofを付けない式の一部として使用すると、ポインターに変換されるか、ポインターとして評価されます) 。
さらに長い答え:ご覧のとおり、関数は実際には引数として配列を受け取ることはできませんが、コンパイラーはそれらに何かを送信する必要があるため、ポインターを送信します。printf()
したがって、最初の文はおそらく「のような機能に関する限り...」で始まるはずです。
一部の関数は配列を取ることを目的としていますが、それは単なる幻想です。これら2つの機能は同じです。
func(char *a);
func(char a[]);
以下のCFAQエントリでは、配列とポインタの微妙な違いについて詳しく説明しています。
char a[] = "this";
char *b = "that";
a[0]はb[0]とは完全に異なるコードを生成しますが、添え字演算子[]が期待される結果を与えるという点でほぼ同等です。
printf()
興味深いことに、フォーマット指定子 "%s\n"もポインタとして渡されます。
sizeof
or unary演算子のオペランドである場合&
、または宣言内の別の配列を初期化するために使用される文字列リテラルである場合を除き、 「N要素配列の」型の式は「ポインタ」T
型の式に置き換えられます。T
その値は、配列の最初の要素のアドレスです。
あなたが書くとき
printf("%s", text);
式は、値が。text
である型の新しい式に置き換えられ、このポインタ値がに渡されます。これは、引数をキャストする必要がないことを意味します。また、配列式を関数パラメーターとして渡して、呼び出された関数に配列型として受け取らせることはできないことも意味します。変換は、関数が呼び出される前に行われます。 char *
&text[0]
printf
ポインタと配列の名前は交換可能です。(メモリ割り当てのほかに)
あなたが持っているとき
char *a = "abcdef";
char b[5];
あなたは書くことができます
char z = a[2]; // 'c'
char x = *b;
char y = *(b+2);
しかし、あなたはできません
b ++;
変更不可能なポインタ とarray b
見なすことができますchar * const b