基本使用
// 创建int型对象
int a = 10;
// & 是取地址符, * 是代表创建的对象是指针, 将a的内存地址赋值给pt_a指针
int * pt_a = &a;
// *pt_a 是取指针指向的内容,pt_a是内存地址, 将pt_a指向内容修改为常量 11
*pt_a = 11;
// 输出a 变量内容为 11
std::cout << a;
①. int *p;
②. *p=10;
两个的区别:前一个起标识作用,表明定义的p是一个指针,后者的表示通过访问p指向的地址空间
指向指针的指针
int a = 10;
int *p = &a; //指向int型的指针
int **p1 = &p; //指向指针的指针
int ***p2 = &p1; //三级指针
*p2相当于访问p1;
**p2相当于访问p;
***p2相当于访问a;
*p1相当于访问p;
数组指针
int array[] = {-1, 2, -3, 4};
int len = (sizeof(array) / sizeof(array[0]));
for (int i = 0; i < len; ++i) {
printf("[%d] = %d\n", i, array[i]);
}
// 默认指向数组第一个元素
int *p = array; // 或者 int *p = &array[0]
printf("first = %d\n", *p); // 输出-1 数组第1个元素
printf("next = %d\n", *(p + 1)); // 输出2 数组第2个元素
// 通过指针遍历数组
for (int i = 0; i < len; ++i) {
printf("[%d] = %d\n", i, *(p + i));
}
// 通过指针下标获取 元素
printf("%d", p[2]); // 输出第3个元素 -3
return 0;
1.数组元素的三种访问形式:
- 数组名[下标]
array[0]
- 指针变量名[下标]
p[0]
- *(p+1)
*(p)
2.指针变量的+1究竟是加多少?这取决于指针的类型,如果是char类型则加1个字节,如果是int类型的,则加4个字节。
3.利用指针来接收一个数组,指针变量指向了数组的首元素。 如果传递的指p针是 &array[1], *(p + 1) 就会变成第三个元素值
字符串指针
char str1[] = "123456"; // 适用需要修改子串的情况
const char * str2 = "7891011"; // 适用内容不需要修改,且经常被使用
// 修改第一个元素
str1[0] = 'Y';
printf("str1 =%s\n", str1);
printf("str2 =%s\n", str2);
// 第二个元素, char * 是常量不能修改
printf("first =%c\n", *(str2 + 1));
指针函数
void (*p)(); // void指针变量指向的函数没有返回值,()表示p指向的函数没有形参
void test() {
printf("调用了test函数\n");
}
int main() {
p = test; // 有指针p,把指针p指向函数
test(); // 直接调用test()
(*p)(); // 利用指针变量简介调用 (*p)()
p(); // 简化使用p()
return 0;
}
练习: 编写一个函数,计算a和b的和与差(一个函数返回两个值)
int sumAndSub(int a, int b, int *result) {
*result = a + b;
return a - b;
}
int main() {
int sum;
int sub = sumAndSub(5, 6, &sum);
std::cout << sub << "," << sum << std::endl;
return 0;
}
有关指针的疑问
注意:任何类型的指针都占据8个字节的存储空间,那么为什么还要为指针加上类型呢? 对下面一段代码进行内存分析,可以证明指针类型不正确带来的严重后果。
int i = 2;
char c = 1;
int *p = &c; // 本应该是char类型的,写成了int类型
printf("c的值是%d\n", *p); // 打印结果为513,而非1
printf("c的值是%d\n",c); // 值为1
下面是上述代码的结果的内存分析:
指针p访问的本应该是1个字节空间的数据,此时因为指针的类型是int型的,因此程序自然的从指向的地址0x0a开始读取了4个字节的数据,访问的数据从1变成了513。
提示:明确了指针的数据类型,指针才能够正确的访问应该访问的空间数据。