char* line = (char*) malloc(MAX_LINE_LEN);
これはスタイルが悪いです。Cでキャストする必要はありませんmalloc
。これを 2 つのセクションに分けて説明します。その方が説明と比較が簡単だからです。
char *line;
という名前の char へのポインターを宣言しますline
。オブジェクト(または何もない)を指すように割り当てることができます。sizeof
an オブジェクトはその型のサイズであり、システムsizeof (line)
によってsizeof (char *)
異なる です。型(char へのポインターへのポインター)を持つ&line
a のアドレスです。保存期間は、宣言されている場所によって異なります。char *
char **
関数の外部で宣言されている場合は、プログラムの存続期間中続く静的ストレージ期間があります。静的ストレージ期間を持つオブジェクトは0
、明示的な初期化が存在しない限り (たとえば、あなたの場合) に初期化されます。0
は であり、初期化子なしで関数の外で宣言された場合null pointer constant
、このオブジェクトは何も指さないことを示します。
コード ブロック内で宣言されている場合、自動保存期間があり、実行がそのコード ブロックの最後に到達するまで続きます。自動保存期間を持つオブジェクトは、明示的に初期化するか、使用する前に割り当てる必要があります。そうしないと値が不確定になるためです。
初期化により値が割り当てられるため、不確定な状態で開始されることはありません。malloc
動的記憶域期間を持つオブジェクトへのポインターを返します。つまり、ポインターが指すオブジェクトは、明示的にfree
d されるまで存続します。
これ 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])
のアドレスは(文字の配列へのポインタ) です。&line
char (*)[MAX_LINE_SIZE]
MAX_LINE_SIZE
これは上記のように再割り当てできないため、郵便番号の例とは異なります。コンパイラがポインターを期待する場所で配列が使用されると、配列は最初の要素へのポインターに暗黙的に変換されます。たとえば、次のことを考えてみましょう。
strcpy(line, "Hello, world!");
関数プロトタイプは、2 つの( char へのポインター) 引数を受け入れるchar *strcpy(char *restrict s1, const char *restrict s2);
ことを示しています。この例では、引数の 1 つが で、もう 1 つがです。どちらも に変換されました。strcpy
char *
char[MAX_LINE_LEN]
char[14]
char *
この配列からポインターへの変換は、なぜchar *line; line = "hello";
有効でchar line[MAX_LINE_LEN]; line = "hello";
はないのかを説明しています。変換の結果のポインターを変更することはできません。
前者がポインタで後者が配列であることは知っていますが、システムはどのように違いを見分けるのでしょうか?
前述のように、配列式は、ポインターが必要な場所で使用されると、ポインター式に変換されます。たとえば、array
inarray[x]
は in に変換さpointer
れpointer[x]
ます。何を聞いているんですか?なぜ配列とポインタの違いを知る必要があるのでしょうか?
配列は別の場所に格納されており、システムが範囲外になるとメモリの割り当てを自動的に解除すると思います。
はい。保存期間の違いについては前に説明しました。
ポインターを扱っているときには発生しないため、自分で削除する必要があります。私が間違っている?
はい。ポインタの概念とストレージ期間の概念を混同しています。p は、動的ストレージ期間を持つint *p = malloc(sizeof *p);
an を指すように初期化されます。が呼び出されるまで、int
それはint
破棄されません。free(p);
ただし、以下の両方の変数は、main
などの修飾子なしで 内で宣言されているため、自動保存期間がありますstatic
。p
を指すi
; p
ポインタです。free
動的な保存期間を持つオブジェクトを指していないため、pしないでください。動的ストレージ期間free
を持つオブジェクトを破棄するためにのみ定義されています。
int main(void) {
int i = 42;
int *p = &i;
}