2009-09-02 15 views
4

g ++を使用しています。私はmain(int,char**)のコードを使用していますので、私はそれを呼び出すことができます。私はShould I use char** argv or char* argv[] in C?を見て、char**char* []に相当すると言います。これは、C++関数呼び出しでは当てはまりません。たとえば: C++:function arg char **はcharと同じではありません* []

void f1(char** p){;} 

void f2(char* p[]){ 

    f1(p); 

//...` 

} 

は、コンパイラが、私は配列はコールのためのポインタに変換されていることを言って見ての参照を「... char**から char (*)[]変換できません」文句で失敗しますが、これはそうではないようです次のようになります。

void f3(char* [] p); 

char caa[16][16]; 
f3(caa); 

も失敗します。インダイレクションのレベルが同じであれば(例えば、char*** ptrchar[][][] carray)、タイプは互換性があると私は想定していました。

誰かがこれらの問題を明確にするために参照できる参考資料を提供できますか?

ありがとうございました。

答えて

12

これはC++でも同じです。コンパイラが最初のケースについて記述しているように文句を言うと、それは不適合です。

2番目のケースを説明するには、実際に何が起こったのかを理解することが重要です。配列型の式は、対応するポインタ型、すなわちT[n]->T*に暗黙的に変換可能です。しかし、T自体が配列の場合、このケースは特別に扱われず、配列からポインタへの減衰を伝播しません。したがって、T*[n]T**に減衰しますが、T[x][y]は、T[y]*までしか減衰しません。

実装上の観点からは、これは意味をなさない。なぜなら、許容されるならば、さらに崩壊するとポインタへのポインタであるT**となる。一方、2D C配列は、ギザギザの配列(すなわち、配列へのポインタの配列)として実装されておらず、単一の連続したメモリブロックを形成する。だから、の中に "T**"というアドレスを取る配列がありません。許容されるケースでは、典型的な実装では、配列のアドレスを全体として取り、それを単一要素へのポインタの型に変換します(通常の場合と同じように、すべての型のポインタ表現が同じ場合、実行時にno-op)。ここで

引用規格は、ISO C++ 03、4.2 [conv.array]/1:

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to an rvalue of type “pointer to T.” The result is a pointer to the first element of the array.

+0

実際、私はURLを期待していました。あなたが何を言っているのか分かりません。 char ** equivはchar * []になりますか?それは私には思われる: char c; char * cp =&c; 'char ** cpp = &cp;' char * cparray [128]; cparrayとcppは同等ではありません。 &T [n] - > T *はありませんか?私が取り組もうとしている問題は、関数呼び出しの引数で変換が行われていることです。私が今使っているリファレンスは、O'Reilly C++ in a Nutshellです。 「ISO C++ 03、4.2 [conv.array]」はWeb上で入手できますか?それとも、出版社から注文しなければならない文書ですか? – cvsdave

+1

引数型に適用すると、関数宣言では同じですが_only_です。また、 'char * []'は 'char **'に暗黙的に変換可能ですが、 'char [] []'はそうではありません。 –

+0

ISO C++はC++言語標準の仕様です。言い換えれば、C++言語の正確な構文とセマンティクスを定義する主要なドキュメントです。 PDFは$ 30で購入することはできますが、ここでは無料ではありません:http://www.techstreet.com/cgi-bin/basket?action=add&item_id=3626517 –

1
void f2(char* p[]){ 

the compiler complaining " cannot convert char (*)[] to char**... "

奇妙。 char(*)[]の文字配列へのポインタですが、コードスニペットにはchar *p[]引数があります。つまり、の文字配列を意味します。これらの型は実際には異なります(配列要素のサイズが異なるため)。コードスニペットは完全にコンパイルされるだけではありません。あなたは本当に何かスペルミスがあります。

シャーロックホームズモード:またはtypedefが関係していますか? ;-)

void f1(char** p){;} 

typedef char type[]; 
void f2(type * p){ 
    f1(p); 
} 

これは実際にはコンパイルされず、参照したエラーが発生します。

+0

void f4(char * [16]){;} int main * int argc、char * * argv){ char caa [16] [16]; f4(caa); ; } yield: a.cpp:関数 'int main(int、char **) ': a.cpp:4:エラー:' char(*)[16]'を 'char ** 'に変換できません。引数 '1 'から' void f4(char **)'へ g ++ 3.4.5 Redhat 5とWin XPで実行 これは私を困惑させるものです。 – cvsdave

+1

さて、Pavel Minaevは、関数呼び出し中の '' char ca [16] [16] 'が' 'char(* caa)[16]' ''に変換されていることを説明しました。つまり、 '* caa'は文字の*配列*を意味し、' caa'と同じです。あなたが望むのは、 '(char *)caa [16]'に変換するか、 '' char * caa [16] ''に変換することです。 –

関連する問題