指针:也是一个变量,存放所指变量的地址,根据变量定义的不同,指针指向的类型也不同
注意:*是与前面类型一体的
int main(void)
{
int* p; //等价于int *p;
//为了区分变量,C语言中一般将*放置于变量名前面
int* p,p1; //p是指向int类型的指针,p1是指向int类型的普通变量
//上面语句等价下面语句,仅仅是下面语句看着更易区分
int *p,p1; //p是指向int类型的指针,p1是指向int类型的普通变量
return 0;
}
//指针的初始化
//1.第一种初始化
int main(void)
{
int a = 0x66;
int *p; //定义一个指向int的指针p
p = &a; //指针指向a的地址
return 0;
}
//2.第二种初始化
int main(void)
{
int a = 0x66;
int *p = &a;
return 0;
}
使用指针:
*p相当于解引用,去找指针存储的地址,根据地址去找对应的数据。
操作方式 | 举例 | 解释 |
---|---|---|
取地址 | p = &a; | 将数据a的首地址赋值给p |
取内容 | *p; | 取出指针指向的数据单元 |
加 | p++; 或者 p =p+5; | 指针向下移动一个数据宽度/指针向下移动5个数据宽度(地址增大) |
减 | p–; 或者 p =p-5; | 指针向上移动一个数据宽度/指针向上移动5个数据宽度(地址减小) |
int main()
{
char a[] = { 0x34, 0x35, 0x36 };
char *p;
p = a; //a为数组的首地址,相当于也是一个指针
printf("%x\n", a[0]);
printf("%x\n", a[1]);
printf("%x\n", a[2]);
//利用指针解引用
printf("*p为%x\n", *p);
printf("*(p+1)为%x\n", *(p+1));
printf("*(p+2)为%x\n", *(p + 2));
return 0;
}
值传递 | 址传递 |
---|---|
函数调用后,实参的值不会发生改变 | 函数调用后,实参的值会发生改变 |
形参会开辟与实参相同大小空间的内存 | 形参与实参公用一段内存空间 |
隔离数据,安全 | 数据公用,已造成数据的丢失与差错 |
使用址传递,形参和实参公用一段内存,当形参改变数值时,实参的值也会发生变化,为了防止出现这种情况,一般在函数调用前加const,只允许对参数进行读,不可以修改。
//加上const,只允许数组被读,不允许修改
int FindMax(const int* arr[], int Count)
{
int Max = arr[0];
for (int i = 1; i < Count; i++)
{
if (arr[i] > Max)
{
Max = arr[i];
}
}
return Max;
}
int main(void)
{
int a[] = { 3, 5, 7, 1, 9 };
int max = 0;
max = FindMax(a, sizeof(a) / sizeof(a[0]));
printf("max为%d\n", max);
return 0;
}
(2)使用指针传递输出参数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计
例子:返回数组最大值及其出现的次数,利用指针有两个返回值
//找出最大值并返回最大值及其出现的次数
//*max与*Count分别与主函数里面的Max和Count共用一段地址
void FindMaxCount(int *max, int *Count, const int *arr, int length)
{
*max = arr[0];
*Count = 1;
for (int i = 1; i < length; i++)
{
if (*max < arr[i])
{
*max = arr[i]; //更新最大值
*Count = 1; //并将Count置为1
}
else if (*max == arr[i])
{
(*Count)++;
}
}
}
int main(void)
{
int a[] = { 9, 100, 24, 56, 77, 99, 100 };
int Max; //找最大值
int Count; //最大值出现的次数
FindMaxCount(&Max, &Count, a, sizeof(a)/sizeof(a[0]));
printf("Max为%d,Count为%d\n", Max, Count);
return 0;
}
句柄:类似于把手,有了把手,就可操作程序。
3. 直接访问物理地址下的数据
(1)访问硬件指定内存下的数据,如设备ID号等
(2)将复杂格式的数据转换为字节,方便通信与存储