c言語における*と〔〕の議論


1.定義とメモリ割当ての宣言
1.1 c/C++によってコンパイルされたプログラムが占有するメモリは以下の部分に分けられる.
(1)スタック領域(stack)-コンパイラによって自動的に割り当てられて解放され、関数のパラメータ値、ローカル変数の値などが格納されます.
(2)ヒープ領域(heap)—一般的にプログラマによって割り当てられて解放され、プログラマが解放されない場合、プログラム終了時にOSによって回収される可能性がある.
(3)グローバル領域(静的領域)(static):グローバル変数と静的変数の記憶はブロックにあり、初期化されたグローバル変数と静的変数はブロック領域にあり、初期化されていないグローバル変数と初期化されていない静的変数は隣接する別のブロック領域にある.プログラムが終了するとシステムから解放されます.
(4)文字定数領域-定数文字列はここにあります.プログラムが終了するとシステムから解放されます.
(5)プログラムコード領域
1.2
*で宣言すると、ポインタはスタック領域に格納され、特定のポインタが指す値は定数領域、グローバル領域、またはスタックに格納されます.
[]で宣言すると、配列全体がスタック領域に格納され、宣言変数が自身、すなわち配列の最初の要素を指す.
1次元配列の例を見てみましょう

#include <iostream>
using namespace std;

main()
{
     char *c1 = "abc";
     char c2[] = "abc";
     char *c3 = ( char* )malloc(3);
     //    *c3 = "abc" //error
     strcpy(c3,"abc");
     c3[0] = 'g';
     printf("%d %d %s
",&c1,c1,c1); printf("%d %d %s
",&c2,c2,c2); printf("%d %d %s
",&c3,c3,c3); getchar(); }

実行結果
2293628 4199056 abc
2293624 2293624 abc
2293620 4012976 abc
1.3変数を[]で宣言する場合は、char a[]={'a'.'b','c','d'}のように{}で定義できますが、*で宣言することはできません.この方式は配列の独特な定義方式であるからである.
2.2ビット配列
上は1次元配列の例ですが、2次元配列を見てみましょう.
2.1[][]声明
このように宣言された2次元配列を1次元配列と見なすことができる.配列のすべての要素はスタック領域にあります.
(1)まず,char a[][]またはchar a[3][]で配列を宣言することはできず,array type has incomplete element type,すなわち,2次元の配列のタイプが不明確であると誤報する.
(2)char a[][3]はこのように宣言することができるが,宣言する際には初期値を付与しなければならず,コンパイラはその配列にスタックにどれだけの空間を割り当てるかを知る.
次の例を示します.

#include <stdio.h>
int main()
{
	char x[][2]={'1','2','3','4'};
	printf("%c",*((char*)x));
	printf("%c",*((char*)x+1));
	printf("%c",*((char*)x+2));
	printf("%c",*((char*)x+3));
}

実行結果は1234
(3)char a[3][3]をこのように宣言することができ、これは最も標準的な2ビット配列宣言であり、2ビット配列は1次元配列として使用することができ、ポインタによって値を取ることができる.
2.2[]*組合せ宣言
(1)char*a[]は、aが配列であり、配列の各要素がポインタであることを表す.[]に具体的な値がなければ初期値を付与する必要があり,char a[][3]の場合と同様である.char a[][3]は配列を表すため、配列内の各要素は長さ3の配列である.
(2)char(*a)[]は、aがポインタであり、配列を指すことを表す.ここでの[]は具体的な値を持たなくてもよいが、スタックにはポインタが1つしか格納されず、他のすべての値がスタックに格納される.
2.3**声明
char**aはポインタユニットを指すポインタであり、スタックにはポインタが1つしか格納されていない.
3.関数伝達値
関数の値を渡す場合、2次元配列を1つ渡す場合、関数のパラメータ宣言の中で最も良い方法はchar(*a)[3]であり、char**aでパラメータ宣言を行うとエラーが発生する.パラメータ配列は1次元のサイズを認識できないため、パラメータに1次元のサイズを宣言しなければならない.