目录
一、内存和地址
二、指针是什么?
三、指针变量的内容
四、指针类型
五、间接访问操作符
(一)易混淆
六、野指针
(一)野指针成因
1. 指针未初始化
2. 指针越界访问
3. 指针指向的空间释放
(二)如何规避野指针
(三)处理未初始化指针
1. 总是用NULL来初始化指针
2. 用assert函数
补充:指针为什么要初始化
七、常量和指针
(一)指向常量的指针
1. 具体形式
2. 把pci声明为指向整数常量的指针意味着:
(二)指向非常量的常量指针
1. 举例
2. 注意
(三)指向常量的常量指针
八、指针的指针
(一)对于二级指针的运算有:
(二)注意:
(三)总结
九、字符指针
(一)易错 :cout特性
(二) 把字符串 hello,world! 首字符的地址放到p中
(三)举例
1. 常量字符串之间
2. 字符数组之间
3. 总结
十、指针数组
(一)整形数组和字符数组
(二)整形指针数组
十一、数组指针
(一)判断数组指针
举例1: 定义一个数组指针,该指针指向char* arr[5]数组
举例2: 定义一个数组指针,该指针指向int arr2[10]数组
(二)&数组名VS数组名
十二、 数组参数、指针参数
(一)一维数组传参
1. 举例
(二)二维数组传参
1. 传参方式
2. 举例
(三)一级指针传参
1. 当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
2. 举例
(四)二级指针传参
1. 当函数的参数为二级指针的时候,可以接收什么参数?
2. 举例
int a = 112, b = -1;在内存中开辟空间
float c = 3.14;
int* d = &a;//这里对变量a,取出它的地址//将a的地址存放在d变量中,d就是一个指针变量
float* e = &c;
例如:
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
表达式 | 右值 | 类型 |
a | 112 | int |
b | -1 | int |
c | 3.14 | float |
d | 100 | int* |
e | 108 | float* |
*d | 112 | int |
*e | 3.14 | float |
错误写法:
正确:
#include
#include
using namespace std;
int main()
{int* p = (int*)malloc(sizeof(int));if (p == NULL)exit(-1);*p = 20;cout << *p;//20free(p);return 0;
}
//错误写法
#include
using namespace std;
int main()
{int arr[10] = { 0 };int* p = arr;int i = 0;for (i = 0; i <= 11; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++) = i;}return 0;
}
int* p = NULL;
......
if (p == NULL)//不应该解引p
{}
else//可以使用p
{}
assert(p != NULL);
const int *pci;//指向整数常量
//等价形式int const* pci;
#include
#include
using namespace std;
int main()
{int num = 5;const int limit = 500;int* pi = (int*)malloc(sizeof(int));//指向整数const int* pci = (int*)malloc(sizeof(int));//指向整数常量cout << &pci << " " << pci << endl;//000000ACB338FC98 00000269CB403140pci = &limit;//对应第一点cout << &pci << " " << pci << endl;//000000ACB338FC98 000000ACB338FC54pci = #//对应第二点cout << &pci << " " << pci << endl;//000000ACB338FC98 000000ACB338FC34//*pci=123;是错误的free(pi);return 0;
}
int num = 5;
int *const cpi=#
#include
using namespace std;
int main()
{int num = 5;const int limit = 25;int *const cpi=#cout << cpi << " " << *cpi<
#include
using namespace std;
int main()
{int num = 5;const int limit = 25;//const int *const cpci;错误写法必须初始化const int* const cpci = &limit;cout << cpci << " " << *cpci << endl;//000000CF749EF9D4 25const int* const cpci2 = #cout << cpci2 << " " << *cpci2 << endl;//000000CF749EF9B4 5return 0;
}
int a=12;
int* pa=&a;
int** ppa=&pa;
#include
using namespace std;
int main()
{int a = 12;int* pa = &a;int** ppa = &pa;cout << &ppa << " " << ppa << endl;//000000C434FEF9F8 000000C434FEF9D8cout <<&pa << " " << pa << endl;//000000C434FEF9D8 000000C434FEF9B4cout <<&a<<" "<< a;//000000C434FEF9B4 12return 0;
}
表达式 | 相当的表达式 |
a | 12 |
pa | &a |
*pa | a,12 |
ppa | &pa |
*ppa | pa,&a |
**ppa | *pa,a,12 |
#include
using namespace std;
int main()
{const char* p = "hello,world!";cout << &p << " " << p;//000000CC043AFAE8 hello,world!return 0;
}
#include
using namespace std;
int main()
{const char* p = "hello,world!";const char* p2 = "hello,world!";if (p == p2)cout << "p和p2相同" << endl;elsecout << "p和p2不同" << endl;return 0;
}
原因:
#include
using namespace std;
int main()
{char str[]= "hello,world!";char str2[] = "hello,world!";if (str == str2)cout << "str和str2相同" << endl;elsecout << "str和str2不同" << endl;return 0;
}
原因:
C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块
int*arr3[5]
int* p;//p是整形指针----指向整形的指针----可以存放整形的地址
char* pc;//pc是字符指针----指向字符的指针----可以存放字符的地址
int *p1[10];
int (*p2)[10];
char* arr[5];
char* (*pa)[5] = &arr;
int arr2[10];
int (*p)[10] = &arr2;
#include
using namespace std;
int main()
{int arr[10];cout << arr << " " << arr+1 << endl;//000000F84C1AF798 000000F84C1AF79Ccout << &arr << " " << &arr+1 << endl;//000000F84C1AF798 000000F84C1AF7C0return 0;
}
#include
using namespace std;
void test1(int a[])
{swap(a[0],a[1]);
}
void test2(int b[10])
{swap(b[2], b[3]);
}
void test3(int* c)
{swap(c[4], c[5]);
}
void test4(int* d[])
{swap(d[0], d[1]);
}
void test5(int* e[20])
{swap(e[2], e[3]);
}
void test6(int** f)
{swap(f[4], f[5]);
}
void print(int arr[])
{for (int i = 0; i < 6; i++){cout << arr[i] << " ";}cout << endl<
void test1(int a[row][col])//第一种
void test2(int b[][col])//第一种
void test3(int (*c)[col])//第二种
错误形式:
void test(int* arr);//参数定义一个整形指针,是存放整形数据
void test(int** arr);//参数是二级指针,二级指针是存放一级指针的地址
#include
using namespace std;
void test1(int a[3][5])
{a[0][0] = 1, a[0][1] = 2;
}
void test2(int b[][5])
{b[1][0] = 3, b[1][1] = 4;
}
void test3(int(*c)[5])
{c[1][0] = 5, c[1][1] = 6;
}
void print(int d[3][5])
{for (int i = 0; i < 3; i++){for (int j = 0; j < 5; j++){cout << d[i][j] << " ";}cout << endl;}
}
int main()
{int arr[3][5] = { 0 };print(arr);test1(arr);cout << endl;print(arr);test2(arr);cout << endl;print(arr);test3(arr);cout << endl;print(arr);return 0;}
例如:
void test1(int *p);//p是一级指针
#include
using namespace std;
void test(int* p)
{;
}
int main()
{int a = 12;int* p1 = &a;test(&a);//传地址test(p1);//传一级指针return 0;
}
#include
using namespace std;
void test(int** p)
{;
}
int main()
{int a = 12;int* p = &a;int** pp = &p;test(&p);//传一级指针的地址test(pp);//传二级指针int* arr[10];//arr是指针数组,里面存放的指针,传arr过去实际是传首元素的地址过去(首元素是一个指针),也就是传入了一个指针的地址test(arr);return 0;
}