C言語(二)ポインタ
一、ポインタの概要
1.概要
ポインタ:実は住所です.
ポインタ変数:変数アドレスを格納する変数.
2.初期化
1)定義後初期化
int a =10;
int *p;
p=&a;
2)定義と初期化
int a=10;
int *p =&a;
注記:データ型の後、変数名の前にある「*」は、ポインタ変数であることを示す説明子です.
*pのようなデータ型が前にない場合、ここでは「*」はポインタ変数が指す変数を取り出すポインタ演算子です.
3.ポインタ変数の使用メモリ
同じコンパイラ環境では、ポインタ変数のタイプに関係なく、使用されるメモリは固定されます.
コンパイラによって、ポインタ変数の使用メモリが異なります.
16ビット・コンパイラ->2バイト、32ビット・コンパイラ->4バイト、64ビット・コンパイラ->8バイト
二、ポインタと配列
1.pはポインタ、aは配列
1)pが配列要素を指す場合、p+1は常に配列要素を指す次の要素を表す.コンパイラ環境に関係なく、指向するデータ型に関係ありません.
例えば、p=&a[2]、p+1=&a[3]
2)異なるタイプの配列要素では,p値の変化は異なる.配列要素がint型の場合、p+1はpの値に2(16ビットコンパイラ環境)を加え、p+1の値がいくらであっても、常に次の要素を指すことを保証します.
2.pの初期値が&a[0]であると仮定すると、
1)p+iとa+iは,いずれも要素a[i]のアドレスを表すことができる.これらは、配列のi番目の要素のアドレスを指します.
2)*(p+i)と*(a+i)は、いずれも配列要素a[i]を表す.
3)p+iとa+iはいずれも配列のi番目の要素を指すが,両者には違いがある.ポインタ変数としてのpは、p++のように自身を変えることができる値である.しかし、aは配列のヘッダアドレスを表す定数であり、配列の名前でもあり、その値は変更できません.すなわち、a++は合法ではありません.
3.配列名を関数実パラメータとする場合、実際には配列のヘッダアドレスをパラメータ配列に渡し、2つの配列は同じメモリ空間を共通にする.
4.多くの場合、ポインタと配列は互いに切り替えて使用できるが、ポインタが配列であるとは言えない.
5.例
三、ポインタと文字列
1.文字列は特殊な文字配列と見なすことができ、自然に配列である.特殊なのは、配列の末尾に「0」が自動的に追加され、末尾を表すためです.
2.ポインタと文字列の使用
3.遍歴文字列
四、ポインタと関数
1.振り返る
int *p=12;
pはアドレスを格納する.
*pはメモリアドレスを取り出す値です.
p+1,次のアドレス
*(p+1)、次のアドレスの値
2.ポインタを返す関数
3.関数へのポインタ
ポインタが関数を指すのはなぜですか?
関数はプログラムとして、メモリにも一部の記憶空間を占有し、関数のエントリアドレスである開始アドレスもあります.関数にアドレスがある以上、ポインタ変数はアドレスを格納するために使用されるので、ポインタは関数を指すことができ、関数名は関数のアドレスである.
4.例
1)宣言と初期化
2)実用化
1.概要
ポインタ:実は住所です.
ポインタ変数:変数アドレスを格納する変数.
2.初期化
1)定義後初期化
int a =10;
int *p;
p=&a;
2)定義と初期化
int a=10;
int *p =&a;
注記:データ型の後、変数名の前にある「*」は、ポインタ変数であることを示す説明子です.
*pのようなデータ型が前にない場合、ここでは「*」はポインタ変数が指す変数を取り出すポインタ演算子です.
3.ポインタ変数の使用メモリ
同じコンパイラ環境では、ポインタ変数のタイプに関係なく、使用されるメモリは固定されます.
コンパイラによって、ポインタ変数の使用メモリが異なります.
16ビット・コンパイラ->2バイト、32ビット・コンパイラ->4バイト、64ビット・コンパイラ->8バイト
二、ポインタと配列
1.pはポインタ、aは配列
1)pが配列要素を指す場合、p+1は常に配列要素を指す次の要素を表す.コンパイラ環境に関係なく、指向するデータ型に関係ありません.
例えば、p=&a[2]、p+1=&a[3]
2)異なるタイプの配列要素では,p値の変化は異なる.配列要素がint型の場合、p+1はpの値に2(16ビットコンパイラ環境)を加え、p+1の値がいくらであっても、常に次の要素を指すことを保証します.
2.pの初期値が&a[0]であると仮定すると、
1)p+iとa+iは,いずれも要素a[i]のアドレスを表すことができる.これらは、配列のi番目の要素のアドレスを指します.
2)*(p+i)と*(a+i)は、いずれも配列要素a[i]を表す.
3)p+iとa+iはいずれも配列のi番目の要素を指すが,両者には違いがある.ポインタ変数としてのpは、p++のように自身を変えることができる値である.しかし、aは配列のヘッダアドレスを表す定数であり、配列の名前でもあり、その値は変更できません.すなわち、a++は合法ではありません.
3.配列名を関数実パラメータとする場合、実際には配列のヘッダアドレスをパラメータ配列に渡し、2つの配列は同じメモリ空間を共通にする.
4.多くの場合、ポインタと配列は互いに切り替えて使用できるが、ポインタが配列であるとは言えない.
5.例
#include <stdio.h>
#include <string.h>
int main() {
// int
int a[4] = {1, 2, 3, 4};
// int , 0
int *p = a;
int i;
for (i = 0; i < 4; i++) {
// *
int value = *(p+i);
printf("a[%d] = %d
", i, value);
}
return 0;
}
三、ポインタと文字列
1.文字列は特殊な文字配列と見なすことができ、自然に配列である.特殊なのは、配列の末尾に「0」が自動的に追加され、末尾を表すためです.
2.ポインタと文字列の使用
#include <stdio.h>
int main() {
char a[10]="china";
char b[10];
//b="china"; // b , ,
char *c="china";
char *d;
d="china";// ,
char *e="china";//e , china
e="uk"; // uk,
//*e='m';// e ,
int leng =strlen(e);
printf("%d
",leng); // :2
printf("%c
",*e); // e 。
//printf("%s
",*e); // e uk “u”, 。
return 0;
}
3.遍歴文字列
char a[]="china";
char *p=a;
for(;*p !='\0';p++){
printf("%c",*p);
}
// :china
四、ポインタと関数
1.振り返る
int *p=12;
pはアドレスを格納する.
*pはメモリアドレスを取り出す値です.
p+1,次のアドレス
*(p+1)、次のアドレスの値
2.ポインタを返す関数
char * upper(char *str) {
// 。 str 。
char *dest = str;
//
while (*str != '\0') {
//
if (*str >= 'a' && *str <= 'z') {
// 。 ASCII
*str -= 'a' - 'A'; //a-97 A-65
}
//
str++; //
}
//
return dest;
}
3.関数へのポインタ
ポインタが関数を指すのはなぜですか?
関数はプログラムとして、メモリにも一部の記憶空間を占有し、関数のエントリアドレスである開始アドレスもあります.関数にアドレスがある以上、ポインタ変数はアドレスを格納するために使用されるので、ポインタは関数を指すことができ、関数名は関数のアドレスである.
4.例
1)宣言と初期化
#include <string.h>
#include <stdio.h>
int sum(int a, int b) {
return a + b;
}
int main() {
//int (*p)()=sum;//
int (*p)(int, int)=sum;//
//int (*p)(int number1,int number2)=sum;
//int result = (*p)(1, 3);//
int result=p(1,3);
printf("%d
", result);
return 0;
}
2)実用化
#include <string.h>
#include <stdio.h>
#include <stdio.h>
//
int minus(int a, int b) {
return a - b;
}
//
int sum(int a, int b) {
return a + b;
}
//
int mul(int a, int b) {
return a * b;
}
// counting a b , , 1
void counting(int (*p)(int, int), int a, int b) {
int result = p(a, b);
printf(" :%d
", result);
}
int main() {
//
counting(sum, 6, 4);// p
//
counting(minus, 6, 4);
//
counting(mul, 6, 4);
return 0;
}