2012-03-09 14 views
43

ファイルから配列に一連の文字列を読み込まなければならない割り当てをしています。私は配列の暗号アルゴリズムを呼び出さなければなりません(暗号は2次元配列を転置します)。だから、最初はファイルの情報をすべて2次元配列に入れましたが、残りのコードでは(特にchar []をchar *に設定しようとしたときに)矛盾する型に多くの問題がありました。だから、私はポインタの配列に切り替えることにしました。これにより、ほとんどすべてのコードですべてが簡単になりました。Cでchar []をchar *に変換することはできますか?

今はchar *をchar []に変換して元に戻す必要がありますが、わかりません。私はGoogleで何かを見つけることができませんでした。それが可能かどうか疑問に思っています。

+1

[comp.lang.c FAQ](http://c-faq.com/)のセクション6を読んでください。 –

答えて

87

ポインタと配列の間で混乱しているようです。 (この場合char *char []で)ポインタと配列が配列char a[SIZE]not the same thing.

  • あるaの位置の値が長さSIZE
  • の配列であること場所での値と言うchar *a;ポインタを言いますaのポインタはcharへのポインタです。

    char a[] = "hello"; // array 
    
        +---+---+---+---+---+---+ 
    a: | h | e | l | l | o |\0 | 
        +---+---+---+---+---+---+ 
    
    char *p = "world"; // pointer 
    
        +-----+  +---+---+---+---+---+---+ 
    p: | *======> | w | o | r | l | d |\0 | 
        +-----+  +---+---+---+---+---+---+ 
    
    :これは、メモリに

(例えば、a[10]がどこa点過去10のエントリである)、この(the FAQから採取した例)のように見えるアレイのように動作するポインタ演算と組み合わせることができます

多くの場合、配列参照が最初の要素へのポインタに「崩壊する」ため、ポインタと配列の違いについて混乱するのは簡単です。これは、多くの場合(関数呼び出しに渡されたときなど)、配列がポインタになることを意味します。詳細を知りたい場合は、this section of the C FAQ describes the differences in detail

実際の大きな違いの1つは、コンパイラが配列の長さを知っていることです。上記の例の使用:あなたのコードを見ることなく

char a[] = "hello"; 
char *p = "world"; 

sizeof(a); // 6 - one byte for each character in the string, 
      // one for the '\0' terminator 
sizeof(p); // whatever the size of the pointer is 
      // probably 4 or 8 on most machines (depending on whether it's a 
      // 32 or 64 bit machine) 

を、それが最善の行動をお勧めするのは難しいが、私はどこでも、ポインタを使用するように変更すると、あなたが現在抱えている問題を解決すると思います。次の点に注意してください:

  • 以前に使用されていた配列がある場所では、メモリを初期化する必要があります。例えば、char a[10];char *a = malloc(10 * sizeof(char));になり、その後a != NULLにチェックされます。 sizeof(char)は1と定義されているので、実際にはsizeof(char)と言う必要はありません。完全性のために残しました。

  • Anywhereの以前に配列の長さのためsizeof(a)は('\0'までカウントされ、あなたが文字列を使用している場合、あなたはstrlen()を使用することができます)あなたが割り当てられたメモリの長さによって交換する必要があります持っていました。

  • malloc()への通話ごとに、対応するfree()を呼び出す必要があります。これは、あなたがmalloc()で尋ねたメモリを使って完了したことをコンピュータに伝えます。あなたのポインタがaの場合は、aが指し示すものが不要であることを知っているコードの一点にfree(a);と書いてください。

別の答えは、配列の先頭のアドレスを取得したい場合は、あなたが使用することができ、指摘したように:

char* p = &a[0] 

char型のポインタpがアドレスになります」とあなたはこれを読むことができます要素[0]a "となる。

+7

+1素晴らしい答え –

+0

最後の例では、 'char * p =&a [0]'を 'char * p = &a'? –

+1

@thom_nic:いいえ、 '&a'は6文字の配列へのポインタである' char(*)[6] '型を持っています。これは 'char *'と同じではないので、警告が表示されます。しかし、配列リファレンスが[最初の要素へのポインタに崩壊する]ため、 'char * p = a;'と言うことができます(http://c-faq.com/aryptr/aryptrequiv.html)。ここで長いフォームを使用しました。何が起きているのかがよく分かるからです。 –

9

あなたは char[] c を持っているなら、あなたは*(d+1)を行うことによって char* d = &c[0] とアクセス要素[1] Cを行うことができますが、その他

+0

ああ、ありがとう!私はそれを試みます。 – tparf

+0

また、 'char * d = c;'だけでも構いません。 – mah

-4

まあ、私はあなたの質問を理解することはわからないんだけど...

Cでは、Char []とChar *は同じものです。

編集:この興味深いリンクに感謝します。

+2

私はそれが本当ではないことを恐れている - [ポインタと配列はCで同じではない](http://www.lysator.liu.se/c/c-faq/c-2.html) –

+0

私はそう思ったコンパイラは私にエラーを与えています:( – tparf

+0

@TimothyJones:よくある質問へのリンクはhttp://c-faq.com/です。もちろん、配列とポインタは100%正確です。 *同じことです(そして、それは 'char'ではなく、' Char'ではありません)。 –

2

ポインタとして使用する場合は、配列として宣言する必要はありません。ポインタが多次元配列であるかのように単純に参照することができます。ただ、ポインタへのポインタとして、それを作成し、mallocを使用します。

int i; 
int M=30, N=25; 
int ** buf; 
buf = (int**) malloc(M * sizeof(int*)); 
for(i=0;i<M;i++) 
    buf[i] = (int*) malloc(N * sizeof(int)); 

、その後、あなたはbuf[3][5]または何を参照することができます。

+3

'malloc()'の結果をキャストしないでください。 –

+0

'malloc()'は 'void *'を返します。これは 'buf'に格納するために' int * 'にキャストする必要があります。 – Arcinde

+4

いいえ、キャストは必要ありません。 Cでは、 'void *'型の式は暗黙的に任意のポインタ型(またはポインタ型不完全)型に変換できます。 [comp.lang.c FAQ](http://c-faq.com/)の質問7.7bと[C標準](http://www.open-std.org/)のセクション6.5.16.1を参照してください。 jtc1/sc22/wg14/www/docs/n1570.pdf)。 (C++には異なるルールがあり、C++について議論していた場合には関係します) –

関連する問題