09_指针

本文详细介绍了指针的概念,包括内存地址、指针变量和指针引用。讨论了如何通过指针作为函数参数来改变实参值,以及返回地址值的函数。同时,讲解了指针数组和指向指针的指针,包括指针的加减运算在操作数组元素中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

9.1 地址与指针变量

9.1.1 内存地址

  1. 将内存抽象成一个很大的一维字符数组。
  2. 编码就是对内存的每一个字节分配一个32位或64位的编号(与32位或者64位处理器相关)。
  3. 这个内存编号我们称之为内存地址。

内存中的每一个数据都会分配相应的地址:

  1. char:占一个字节分配一个地址
  2. int: 占四个字节分配四个地址
  3. float、struct、函数、数组等

9.1.2 指针和指针变量

  1. 内存区的每一个字节都有一个编号,这就是“地址”。
  2. 如果在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并确定它的内存地址(编号)
  3. 指针的实质就是内存“地址”。指针就是地址,地址就是指针。
  4. 指针是内存单元的编号,指针变量是存放地址的变量。
  5. 通常我们叙述时会把指针变量简称为指针,实际他们含义并不一样。

9.2指针引用

9.2.1 指针变量的定义和使用

  1. 指针也是一种数据类型,指针变量也是一种变量
  2. 指针变量指向谁,就把谁的地址赋值给指针变量
  3. “*”操作符操作的是指针变量指向的内存空间
#include <stdio.h>

int main(){
int a = 0;
char b = 100;
printf("%p, %p\n", &a, &b); //打印a, b的地址
//int*代表是一种数据类型,int*指针类型,p是变量名
//定义了一个指针类型的变量,可以指向一个int类型变量的地址
int* p;
p = &a;//将a的地址赋值给变量p,p也是一个变量,值是一个内存地址编号
printf("%d\n", *p);//p指向了a的地址,*p就是a的值
char *p1 = &b;
printf("%c\n", *p1);//*p1指向了b的地址,*p1就是b的值
return 0;
}

注意:&可以取得一个变量在内存中的地址。但是,不能取寄存器变量,因为寄存器变量不在内存里,而在CPU里面,所以是没有地址的。

9.2.2 通过指针间接修改变量的值

int a = 0;
int b = 11;
int *p = &a;
*p = 100;
printf("a = %d, *p = %d\n", a, *p);
p = &b;
*p = 22;
printf("b = %d, *p = %d\n", b, *p);

9.3 用指针作函数参数

9.3.1 函数形参改变实参的值

#include <stdio.h>
void swap1(int x, int y){
int tmp;
tmp = x;
x = y;
y = tmp;
printf("x = %d, y = %d\n", x, y);
}

void swap2(int *x, int *y){
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}


int main(){
int a = 3;
int b = 5;
swap1(a, b); //值传递
printf("a = %d, b = %d\n", a, b);
a = 3;
b = 5;
swap2(&a, &b); //地址传递
printf("a2 = %d, b2 = %d\n", a, b);
return 0;
}

9.3.2 数组名做函数参数

数组名做函数参数,函数的形参会退化为指针:

#include <stdio.h>
void printArrary(int *a, int n){
int i = 0;
    for (i = 0; i < n; i++){
        printf("%d, ", a[i]);
    }
printf("\n");
}


int main(){
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int n = sizeof(a) / sizeof(a[0]);
//数组名做函数参数
printArrary(a, n);
return 0;
}

9.4 返回地址值的函数

#include <stdio.h>
int a = 10;
int *getA(){
return &a;
}
int main(){
*( getA() ) = 111;
printf("a = %d\n", a);
return 0;
}

9.5 指针数组,指向指针的指针

9.5.1 数组名

数组名字是数组的首元素地址,但它是一个常量:

int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
printf("a = %p\n", a);
printf("&a[0] = %p\n", &a[0]);
//a = 10; //err, 数组名只是常量,不能修改

9.5.2 指针操作数组元素

#include <stdio.h>

int  main(){
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
int n = sizeof(a) / sizeof(a[0]);
for (i = 0; i < n; i++){
//printf("%d, ", a[i]);
printf("%d, ", *(a+i));
}
printf("\n");
int *p = a; //定义一个指针变量保存a的地址
for (i = 0; i < n; i++){
p[i] = 2 * i;
}
for (i = 0; i < n; i++){
printf("%d, ", *(p + i));
}
printf("\n");
return 0;
}

9.5.3 指针加减运算

1) 加法运算

  1. 指针计算不是简单的整数相加
  2. 如果是一个int *,+1的结果是增加一个int的大小
  3. 如果是一个char *,+1的结果是增加一个char大小
#include <stdio.h>

int main(){
int a;
int *p = &a;
printf("%d\n", p);
p += 2;//移动了2个int
printf("%d\n", p);
char b = 0;
char *p1 = &b;
printf("%d\n", p1);
p1 += 2;//移动了2个char
printf("%d\n", p1);
return 0;
}

通过改变指针指向操作数组元素:

#include <stdio.h>

int main(){
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
int n = sizeof(a) / sizeof(a[0]);
int *p = a;
for (i = 0; i < n; i++){
printf("%d, ", *p);
p++;
}
printf("\n");
return 0;
}

2) 减法运算

示例1:

#include <stdio.h>

int main(){
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int i = 0;
int n = sizeof(a) / sizeof(a[0]);
int *p = a+n-1;
for (i = 0; i < n; i++){
printf("%d, ", *p);
p--;
}
printf("\n");
return 0;
}

示例2:

#include <stdio.h>

int main(){
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int *p2 = &a[2]; //第2个元素地址
int *p1 = &a[1]; //第1个元素地址
printf("p1 = %p, p2 = %p\n", p1, p2);

int n1 = p2 - p1; //n1 = 1
int n2 = (int)p2 - (int)p1; //n2 = 4
printf("n1 = %d, n2 = %d\n", n1, n2);
return 0;
}

9.5.4 指针数组

指针数组,它是数组,数组的每个元素都是指针类型。

#include <stdio.h>

int main(){
//指针数组
int *p[3];
int a = 1;
int b = 2;
int c = 3;
int i = 0;

p[0] = &a;
p[1] = &b;
p[2] = &c;

for (i = 0; i < sizeof(p) / sizeof(p[0]); i++ ){
    printf("%d, ", *(p[i]));
}
printf("\n");

return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值