C専門家プログラミングノート


C専門家プログラミングノート
転自:<>
1.限定子について
C言語では、合法的なポインタ付与の2つのオペランドは、いずれも限定子または無限定子のある適合型のポインタを指すことを規定している.左ポインタが指すタイプ
右ポインタが指すタイプのすべての制限子でなければなりません.たとえば、
char *cp;
const char *ccp;
ccp = cp;

左オペランドはconst制限子のあるcharを指すポインタであり、右オペランドは制限子のないcharを指すポインタである.charはcharと互換性があり、左側に右側が含まれているので、付与は合法です.しかし逆にコンパイル警告があります.
"error C2440: '=' : cannot convert from 'const char *' to 'char *'"
2.連合について
コンビネーションと構造の最大の違いは、後者の各メンバーが順次格納され、コンビネーションの各メンバーがオフセットアドレスゼロから格納され、各メンバーの位置が重なり、ある時点で1人のメンバーだけが実際に使用されることです.
次のような使い方が一般的です
union bits32_tag
{
	int whole;
	struct {char c0, c1, c2, c3;} byte;
}value;

使用時に32ビットの整数を抽出したり、バイトを抽出したりすることができます.
3.ポインタの初期化について
ポインタを定義するときは、スペースを割り当てるのではなく、ポインタ自体のスペースを割り当てるだけです.定義時に文字列定数で初期化しない限り、
char *p = "breadfruit";
文字列定数のみがこのように初期化できますが、他にはできません.たとえば、
float *pip = 3.14;//error
また、ポインタ文字列定数は変更できません.
4.配列間で直接値を割り当てることはできません
ポインタでしか行えず配列では行えない操作があります.配列値を直接修正し、次のコードを見てください.
int array[100], array2[100];


void fun1(int *ptr)
{


	ptr[1] = 3;
	*ptr = 3;
	ptr = array2;
}


void fun1(int arr[])
{
	
	arr[1] = 3;
	*arr = 3;
	arr = array2;
}


int main(int argc, char* argv[])
{
	


	array[1] = 3;
	*array = 3;
	array = array2;// error,     。




	return 0;
}

fun 2に配列が直接付与されるのは,パラメータとして伝達されたときにポインタとして処理されているからである.
5.2 D配列の代わりにポインタ配列
次の2つの書き方は同じ役割を果たしています.
char vegetables[][10] = {
		"carrot",
		"celery",
		"corn",
};


char *vegetables[] = {
	"carrot",
		"celery",
		"corn",
};

しかし、このような使い方は文字列定数にしか使えません.他のタイプではできません.例えば、次のコードが間違っています.
int *weights[] = {
	
		{1,2,3,4,5},
		{6, 7},
		{8,9,10}


	};

そうしなければならない場合は、まずいくつかの個別の配列を作成し、これらの配列で元の配列を初期化することができます.以下のようにします.
int row_1[] = {1,2,3,4,5};
int row_2[] = {6, 7};
int row_3[] = {8,9,10};


int *weights[] = {
	
		row_1,
		row_2,
		row_3


	};
	

6.配列とポインタのアドレスについて
次のコードの出力結果を見て、
char ga[] = "abcdef";


void my_array_func(char ca[10])
{


	printf("addr of array param = %#x 
", &ca); printf("addr of array param = %#x
", ca); printf("addr of array param[0] = %#x
", &(ca[0])); printf("addr of array param[1] = %#x
", &(ca[1])); } void my_pointer_func(char *pa) { printf("addr of ptr param = %#x
", &pa); printf("addr of ptr param = %#x
", pa); printf("addr of ptr param[0] = %#x
", &(pa[0])); printf("addr of ptr param[1] = %#x
", &(pa[1])); } int main(int argc, char* argv[]) { printf("addr of ga = %#x
", &ga); printf("addr of ga = %#x
", ga); printf("addr of ga param[0] = %#x
", &(ga[0])); printf("addr of ga param[1] = %#x
", &(ga[1])); printf("******************************
"); my_array_func(ga); printf("******************************
"); my_pointer_func(ga); return 0; }

出力:
addr of ga = 0x425168
addr of ga = 0x425168
addr of ga param[0] = 0x425168
addr of ga param[1] = 0x425169
******************************
addr of array param = 0x12fef8
addr of array param = 0x425168
addr of array param[0] = 0x425168
addr of array param[1] = 0x425169
******************************
addr of ptr param = 0x12fef8
addr of ptr param = 0x425168
addr of ptr param[0] = 0x425168
addr of ptr param[1] = 0x425169
Press any key to continue

理解しにくいとしか言わない.第1段,&gaはもちろん配列のアドレスで、gaもどうして同じ結果になったのですか?これはちょうどC言語が配列名を配列アドレスと規定しているだけなので、&gaとgaの結果は同じです.第2段,&caとcaは等しくない.これは配列がパラメータとして伝達されるとポインタとなり,&caは取ったポインタのアドレス(すなわち配列のアドレスがあるアドレス)であるからである.第3段は第2段と原理が同じである.