1.int *p;中的*是类型修饰符 →p是指针变量
2.*p = 12;中的*是解引用运算符 → 向p指向的位置写值
3.int *p;*p = 12;不能这样做,指针(无论全局还是局部)必须初始化!!!
3.1 初始化解决方案1——指向已有的变量
int *p;
int x = 0; // 先有一个普通变量
p = &x; // p 指向 x
*p = 12; // 现在没问题,相当于 x = 12
3.2初始化解决方案2——动态分配内存
#include "stdlib.h"
int *p = malloc(sizeof(int)); // 在堆上分配一块 int 大小的内存,C 语言中不需要强制转换,C++要。
if (p != NULL) {
*p = 12; // 现在安全了
free(p); // 用完后释放
}
4.int sum(int *ar);与int sum(int ar[]);等价。因为数组名本身就是一个指针;
这里顺便记一下,数组正常情况下初始化是:
int arr1[5] ;
int arr2[] = {1, 2, 3, 4, 5};
int arr[5] = {1, 2, 3};
int arr[2][3];
int arr[2][3]={0};//或者直接赋值
但是数组作为形参时可以int sum(int ar[]);数组变量是特殊的指针;
数组变量是const的指针,所以不能被赋值。两数组之间赋值也不能直接
int arr[];
int arr1[];
arr[] = arr1[];
但是可以定义一个非const指针将数组名赋给它
int *p = arr[];
或者
int arr1[] = {1, 2, 3, 4, 5};
int arr[5]; // 必须先指定大小//循环复制
for (int i = 0; i < 5; i++) {
arr[i] = arr1[i];
}// memcpy函数
memcpy(arr, arr1, sizeof(arr1));
这里再引申两种指针:
const int *p;和int * const p;
const int *p;/int const* p | 指向常量的指针(指针可变,指向的值不可变) | const 在*左边,修饰int |
int * const p; | 常量指针(指针本身不可变,指向的值可变) | const 在*右边,修饰p |
首先const int *p/int const* p,const 在*左边,修饰int,指针可变,指向的值不可变;
int x = 10, y = 20; const int *p = &x; // p 指向 x // *p = 30; // ❌ 错误:不能通过 p 修改指向的值 p = &y; // ✅ 正确:p 本身可以指向别处
然后int * const p,const 在*右边,修饰p,指针本身不可变,指向的值可变;
int x = 10, y = 20; int * const p = &x; // p 固定指向 x *p = 30; // ✅ 正确:可以通过 p 修改 x 的值 // p = &y; // ❌ 错误:p 本身不能改变指向
数组就是第二种了。
5.对指针加1是在地址上加,如char类型一字节就是加1,而int类型是4字节就是加4了。
6.指针相减的结果是两地址的差除以变量类型的字节。
7.*p++
int arr[] = {10, 20};
int *p = arr;
int x = *p++;++运算优先级高于*,所以先算p++,p++把arr[0]备份,之后再后移p = arr[1],再解引用备份旧地址赋值给x。
8.void *p;通用指针,指向未知类型的指针。可以指向任何类型,不能直接解引用,不能做指针算术。