C言語ポインタ

### メモリ上のデータ配置
どのアドレスに確保するかはコンパイラとリンカとOSが決める
変数のアドレスは&を使う e.g. &mydt

int main(void){
	int mydt = 1234;
	printf("mydt=%d\n", mydt);
	printf("mydt address=%p\n", &mydt);
	return 0;
}

$ ./dev
mydt=1234
mydt address=0x7ffd3a448134

### ポインタ
アドレス値を格納できる
int *pt

int main(void){
	int *pt;
	int mydt = 1234, idt;

	pt = &mydt;
	idt = *pt;
	printf("mydt=%d\n", mydt);
	printf("*pt=%d\n", *pt);
	printf("idt=%d\n", idt);

	mydt = 555;
	printf("mydt=%d\n", mydt);
	printf("*pt=%d\n", *pt);

	*pt = 666;
	printf("mydt=%d\n", mydt);
	printf("*pt=%d\n", *pt);

	return 0;
}

$ ./dev
mydt=1234
*pt=1234
idt=1234
mydt=555
*pt=555
mydt=666
*pt=666

### ポインタの演算
&: アドレスを取り出す(アンド)
*: アドレスにある値を参照する(アスタリスク)

– ポインタを宣言するとき、型指定が必要

### ポインタの配列

int main(void){
	int ary[3] = {100, 110, 120};
	int *pt;

	pt = ary;
	printf("adress=%p value=%d\n", pt, *pt);

	pt = &ary[0];
	printf("adress=%p value=%d\n", pt, *pt);

	pt = &ary[1];
	printf("adress=%p value=%d\n", pt, *pt);

	return 0;
}

$ ./dev
adress=0x7fff517b4eec value=100
adress=0x7fff517b4eec value=100
adress=0x7fff517b4ef0 value=110

### ポインタの加減算
+ – ++ —

int main(void){
	int ary[3] = {100, 110, 120};
	int *pt;

	pt = ary;
	while(1){
		printf("%d\n", *pt);
		if (*pt == 120) break;
		++pt;
	}

	pt = ary;
	printf("%d\n", *pt);
	printf("%d\n", *(pt+1));
	printf("%d\n", *(pt+2));

	return 0;
}

### ポインタと文字列

int main(void){
	char s[10] = "ABCD";
	char *p;

	p = s;

	printf("s=%s\n", s);
	printf("p=%s\n", p);

	while(*p != '\0') {
		*p = tolower(*p);
		++p;
	}

	p = s;
	printf("s=%s\n", s);
	printf("p=%s\n", p);

	return 0;
}

./dev
s=ABCD
p=ABCD
s=abcd
p=abcd
ポインタは文字列アドレスだけでなく、文字列リテラルのアドレスも持つことができる。

### ポインタを引数にする

void func(int *dt){
	printf("value=%d\n", *dt);
}

int main(void){
	int nn = 1234;
	func(&nn);

	return 0;
}

### ポインタによる配列渡し
関数への文字列渡しはポインタを使うのが一般的

void strout(char s[]){
	int i;
	printf("%s\n", s);
	for(i=0; s[i] != '\0'; i++)
		printf("%X ", s[i]);
	printf("\n");
}

void strout(char *p){
	printf("%s\n", p);
	while(*p){
		printf("%X ", *p);
		++p;
	}
	printf("\n");
}

int main(void){
	char st[] = "ABCD";

	strout(st);
	strout_p(st);

	return 0;
}

ポインタを戻り値にする関数を書くこともある

ポインタも、メモリのアドレスにアドレスを格納するという概念さえ理解できれば言うほど難しくはありませんね。