ポインタ(Pointer)は、英語で文字通り解釈すると、特定のオブジェクトを指すものであり、プログラムではデータアドレスを指すアドレスです。
1. ポインタの宣言
変数の型名と変数名の間にアスタリスクを追加します*
。アスタリスクは、次のコード*intPtr1
の と の*intPtr2
そうしないと、宣言時に次の変数名のアスタリスクを見逃す可能性があります。複数のポインター。たとえばintPtr4
、整数変数のみを宣言します。
int *intPtr1, *intPtr2;
int* intPtr3, intPtr4;
ポインタを宣言する際には必ず初期化を行ってください(初期化されていない場合、未知のアドレスを指す可能性があります)。
2. ポインタの種類
ポインタの型は、ポインタが指すアドレスに格納されているデータ型を示します。int *
ポインタをfloat *
ポインタに変換する必要がある場合、プログラムはデータを浮動小数点データとして再解釈するだけです。
void *
ポインタはアドレスを表すだけであり、ポインタが指すデータ型は不明ですが、ポインタが指すデータ型は再定義できます。
3. ポインタの基本操作
逆参照*
ポインタが指すアドレスのデータを取得します。
宣言された場合は、*变量名
変数がポインタとして使用されることを意味し、それ以外の場合は、*变量名
ポインタが指すアドレス内のデータを意味します。
住所を取る&
変数のメモリアドレスを取得し、対応するポインタに代入します。
4. ポインタの算術演算
ポインタと整数の算術演算は、一般的な数値の加算や減算とは異なりますが、ポインタの型に拘束されます。ポインタの算術演算は、現在のポインタが指すアドレスを、ポインタ型の長さ k のアドレスだけ前後に移動します。次のポインタは必ずしも有効なデータを持つアドレスを指しているわけではないため、ポインタ演算を行うときは注意してください。
- 配列名は、配列の最初の要素へのポインタとみなすことができます。ポインタのさまざまな操作を配列名に適用できますが、配列は静的であり、配列名は唯一の要素を表すため、配列名を再割り当てすることはできません。配列の場合、ポインタのように他のアドレスを指すことはできません。
ポインター間の減算演算は、ポインター アドレス間の距離 (正または負) を返します。この距離もポインターの型にバインドされます。
string str[] = {
"1","2","3" };
//取地址
string *s1 = &str[0];
string *s2 = &str[1];
//解引用
cout << s1 << ' ' << *s1 << endl;
cout << s2 << ' ' << *s2 << endl;
//算数操作
cout << s1 + 1 << ' ' << *(s1 + 1) << endl;
cout << s2 - s1 << ' ' << s1 - s2 << endl; //1 -1
ポインタは意味がないので追加できません。
4.定数ポインタ
constオブジェクトへのポインタconst T *ptr1
ptr1 が指すアドレスのデータは変更できませんが、ptr1 が指すアドレスは変更できます。
定数ポインタT *const ptr2
ptr2 が指すアドレスは変更できませんが、そのアドレスに格納されているデータは変更できます。
const オブジェクトへの const ポインタconst T *const ptr3
ptr3 が指すアドレスは変更できず、このアドレスのデータも変更できません。
int numA = 3;
//不能修改数据,能改指针的地址
const int* ptr1 = &numA;
//*ptr1 = 8;
ptr1 = &numA + 1;
//能修改数据,不能改指针的地址
int* const ptr2 = &numA;
*ptr2 = 9;
//ptr2 = &numA + 1;
//不能修改数据,也不能改指针的地址
const int* const ptr3 = &numA;
//*ptr3 = 9;
//ptr3= &numA + 1;
5. ポインタ配列と配列ポインタ
-
ポインター配列:
T *ptrArr[size]
、ptrArr は配列であり、配列内の各要素はポインターです。ポインターの型は ** です。 ** を使用して配列の要素を読み取ることT*
ができます。*(ptrArr[i])
-
配列ポインタ:
T (*arrPtr)[size]
、arrPtr は配列を指します。配列のアドレスを arrPtr に割り当てる必要があります。逆参照した後、配列と同等になります。** ** を使用して配列の要素を読み取ることができます(*arrPtr)[i]
。
int num[5] = {
1,2,3,4,5 };
//指针数组:元素是指针的数组
int* ptrArr[5] = {
&num[0],&num[1],&num[2],&num[3],&num[4] };
for (int i = 0; i < 5; ++i) {
cout << ptrArr[i] << ':' << *(ptrArr[i]) << ' ';
}; cout << endl;
//数组指针:指向数组的指针
int(*arrPtr)[5] = #
for (int i = 0; i < 5; ++i) {
cout << ptrArr[i] << ':' << (*ptrArr)[i] << ' ';
}; cout << endl;
6. ポインタからポインタへ
ポインタは任意の変数またはオブジェクトを指すことができ、もちろんポインタを指すこともできます。
ポインタへのポインタが宣言されている場合、ポインタが指すポインタの型を表すために ** が使用されます。ポインタのポインタは通常、関数がパラメータを渡すときに受信ポインタを変更するために使用されます。
const_cast と reinterpret_cast
- const_cast : 型の const または volatile 属性を変更し、非 const オブジェクトへのポインタまたは参照を返します。このとき、そのデータはポインタまたは参照を通じて変更できます。
int numA = 3; const int* ptr1 = &numA; int* ptr2 = const_cast<int*>(ptr1); const int numB = 3; int& numb = const_cast<int&>(numB);
- reinterpret_cast : 変数のデータ型を変更します
7. ポインタの応用例
ポインタを使用して 2 つの配列をソートする
void sortPtr(int rNum, int* a, int aNum, int* b, int bNum) {
int* p, * q;
int* r = (int*)malloc((aNum + bNum) * sizeof(int));
int* res = r;
for (p = a, q = b; p < a + aNum && q < b + bNum;) {
if (*p > *q) {
*r++ = *q++;
}
else {
*r++ = *p++;
}
}
if (p < a + aNum) {
for (; p < a + aNum;)
*r++ = *p++;
}
else if (q < b + bNum) {
for (; q < b + bNum;)
*r++ = *q++;
}
for (r = res; r < res + aNum + bNum; ++r) {
cout << *r << ' ';
}
cout << endl;
}
ポインタを使用して配列を反復処理する
//遍历数组时,要知道该数组的长度,以免指针超出数组的范围,导致读取数据失败
void testStr(string* p, int size) {
for (int i = 0; i < size; ++i) {
cout << p << endl;
++p;
}
}
//遍历字符数组时,
void testChar(const char* p) {
while (*p) {
cout << *p << endl;
++p;
}
}