2

この質問はばかげているように聞こえるかもしれませんが、私にはよくわかりません。つまり、次の違いは何ですか。

char* line = (char*) malloc(MAX_LINE_LEN);

char line[MAX_LINE_LEN];

まさに?前者がポインタで後者が配列であることは知っていますが、システムはどのように違いを見分けるのでしょうか? メモリはどのように割り当て/保存されますか?

lineまた、ポインタとして宣言されている場合は占有されているメモリを削除できるのに、配列の場合は削除できないのはなぜですか? 配列は別の場所に保存されており、システムがスコープ外になるとメモリの割り当てを自動的に解除すると思います。これは、ポインターを扱っている場合には発生しないため、自分で削除する必要があります。私が間違っている?

4

4 に答える 4

4
char* line = (char*) malloc(MAX_LINE_LEN);

これはスタイルが悪いです。Cでキャストする必要はありませんmalloc。これを 2 つのセクションに分けて説明します。その方が説明と比較が簡単だからです。

char *line;という名前の char へのポインターを宣言しますline。オブジェクト(または何もない)を指すように割り当てることができます。sizeofan オブジェクトはその型のサイズであり、システムsizeof (line)によってsizeof (char *)異なる です。型(char へのポインターへのポインター)を持つ&linea のアドレスです。保存期間は、宣言されている場所によって異なります。char *char **

  • 関数の外部で宣言されている場合は、プログラムの存続期間中続く静的ストレージ期間があります。静的ストレージ期間を持つオブジェクトは0、明示的な初期化が存在しない限り (たとえば、あなたの場合) に初期化されます。0は であり、初期化子なしで関数の外で宣言された場合null pointer constant、このオブジェクトは何も指さないことを示します。

  • コード ブロック内で宣言されている場合、自動保存期間があり、実行がそのコード ブロックの最後に到達するまで続きます。自動保存期間を持つオブジェクトは、明示的に初期化するか、使用する前に割り当てる必要があります。そうしないと値が不確定になるためです。

初期化により値が割り当てられるため、不確定な状態で開始されることはありません。malloc動的記憶域期間を持つオブジェクトへのポインターを返します。つまり、ポインターが指すオブジェクトは、明示的にfreed されるまで存続します。

これ lineは、郵便封筒の郵便番号のようなものだと考えてください。そこに何かを書くことができます。その何かは、オブジェクト (および人) を見つけることができる場所を示します。郵便番号は、オブジェクト (または人) のサイズについては何も教えてくれません。


char line[MAX_LINE_LEN];

MAX_LINE_LENこれは文字の配列を宣言します。

  • 関数の外部で宣言された場合、静的ストレージ期間があり、配列全体がゼロで埋められます。

  • 関数またはコード ブロック内で宣言された場合、自動保存期間があり、配列内の値は不確定です。これらは、使用する前に初期化する (たとえばchar line[MAX_LINE_SIZE] = { 0 };、すべてを初期化する) か、または割り当てる (たとえばline[0] = '\0';、配列の最初の要素に割り当てる) 必要があります。

タイプはであるため、指定された要素の数からわかるchar[MAX_LINE_SIZE]ように、サイズは になります。この場合sizeof (char[MAX_LINE_SIZE])のアドレスは(文字の配列へのポインタ) です。&linechar (*)[MAX_LINE_SIZE]MAX_LINE_SIZE

これは上記のように再割り当てできないため、郵便番号の例とは異なります。コンパイラがポインターを期待する場所で配列が使用されると、配列は最初の要素へのポインターに暗黙的に変換されます。たとえば、次のことを考えてみましょう。

strcpy(line, "Hello, world!");

関数プロトタイプは、2 つの( char へのポインター) 引数を受け入れるchar *strcpy(char *restrict s1, const char *restrict s2);ことを示しています。この例では、引数の 1 つが で、もう 1 つがです。どちらも に変換されました。strcpychar *char[MAX_LINE_LEN]char[14]char *

この配列からポインターへの変換は、なぜchar *line; line = "hello";有効でchar line[MAX_LINE_LEN]; line = "hello";はないのかを説明しています。変換の結果のポインターを変更することはできません。

前者がポインタで後者が配列であることは知っていますが、システムはどのように違いを見分けるのでしょうか?

前述のように、配列式は、ポインターが必要な場所で使用されると、ポインター式に変換されます。たとえば、arrayinarray[x]は in に変換さpointerpointer[x]ます。何を聞いているんですか?なぜ配列とポインタの違いを知る必要があるのでしょうか?

配列は別の場所に格納されており、システムが範囲外になるとメモリの割り当てを自動的に解除すると思います。

はい。保存期間の違いについては前に説明しました。

ポインターを扱っているときには発生しないため、自分で削除する必要があります。私が間違っている?

はい。ポインタの概念とストレージ期間の概念を混同しています。p は、動的ストレージ期間を持つint *p = malloc(sizeof *p);an を指すように初期化されます。が呼び出されるまで、intそれはint破棄されません。free(p);ただし、以下の両方の変数は、mainなどの修飾子なしで 内で宣言されているため、自動保存期間がありますstaticpを指すi; pポインタです。free動的な保存期間を持つオブジェクトを指していないため、pしないでください。動的ストレージ期間freeを持つオブジェクトを破棄するためにのみ定義されています。

int main(void) {
    int i = 42;
    int *p = &i;
}
于 2013-04-27T10:42:39.197 に答える
1

答えはすぐそこにあります。ヒープとスタックの問題です。

配列、ポインタ、ローカル変数はスタック オブジェクト、ヒープ オブジェクトは malloc/free メソッドを使用しています。

スタックとヒープとは何ですか? を見てください。詳細については。

于 2013-04-27T12:57:39.793 に答える
1
char* line;

スタックにポインターを割り当てます。プログラムカウンタがこの宣言の範囲外になると、自動的に解放されます。

line = (char*) malloc(MAX_LINE_LEN);

MAX_LINE_LENヒープにバイトを動的に割り当てます。正確には、次のように使用する必要がありますmalloc

line = malloc(MAX_LINE_LEN * sizeof(char));

後で呼び出しfree(line)て、このヒープ メモリを解放する必要があります。

sizeof(line)ポインターが取得したバイト数 (通常は 4 または 8 バイト) を返します。


char line[MAX_LINE_LEN];

MAX_LINE_LENスタックに文字を割り当てます。プログラムカウンタがこの宣言の範囲外になると、自動的に解放されます。

sizoef(line)MAX_LINE_LEN * sizeof(char)バイトを返します。

于 2013-04-27T10:08:48.160 に答える