目 录CONTENT

文章目录

指针(二)

Administrator
2022-10-30 / 0 评论 / 0 点赞 / 1660 阅读 / 6956 字

指针和数组

数组的指针

1、一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,
它们都有相应的地址。所谓数组的指针是指数组的起始地址。
2、数组名表示数组的首地址,因此数组名也是一种指针
3、通过数组名访问数组中元素

int ch[] = {1,2,3,4};

假如我们想访问ch中的第3个元素:ch[3] == 4
我们也可以通过指针法引用数组中的元素:比如 *(ch + 3)
那么,如果想访问第n个元素呢?

*(ch + n) 注意:n<=sizeof(ch)/sizeof(ch[0])-1

练习:假如有数组int a[4], 编写代码实现如下功能:
1、通过从键盘上输入数字对数组a的每一个元素进行赋值
2、打印出数组a中每一个元素的地址
3、通过指针法将数组a中的每一个元素的值打印出来

int a[4];
int i;
for (i = 0; i < 4; i++)
 scanf(“%d”, &a[i]);
for (i = 0; i < 4; i++)
{
 printf(“%p %d\n”, &a[i], *(a+i));
}

5、通过指针变量间接访问数组

int a[4] = {1,2,3,4};
int *p;
p = a;
*(p + 2) = 100;
char ch[] = {'a', 'b', 'c'};
char *p2;
p2 = ch;
*(p2+1) = 'A';
 int ch[] = {1, 2, 3, 4};
 printf("%d\n", ch[4]);
 printf("%p %p\n", &ch[3], &ch[4]);
 //数组名:数组的首地址
 printf("ch: %p\n", ch);
 //数组中的第0个元素的地址:数组的首地址
 printf("&ch[0]: %p\n", &ch[0]);
 printf("%d %d\n", ch[3], *(ch+3));
 int a[4];
 int i;
 for (i = 0; i < 4; i++)
 {
 scanf("%d", &a[i]); //a+i
 getchar();
 }
 //打印数组中每个元素的地址
 for (i = 0; i < 4; i++)
 printf("%p\n", &a[i]);
 //通过指针法将数组a中的每一个元素的值打印出来
 for (i = 0; i < 4; i++)
 printf("%d\n", *(a+i));
 int *p;
 p = a; //指针p指向了数组a
 //指针指向了一个数组,可以将指针当数组看待
 for (i = 0; i < 4; i++)
 printf("%d\n", p[i]); //通过下标发访问数组中的元素
 // printf("%d\n", *(p+i));

6、数组指针越界

int b[4] = {10, 20, 30, 40};
int a[4];
a[4] = 100;
printf("a[4]: %d\n", a[4]);
printf("b[0]: %d\n", b[0]);
printf("a: %u, b: %u\n", &a, &b); //打印数组a和b的首地址

微信截图_20221030205223

指针数组

1、指针数组顾名思义就是:存放指针的数组,本质是数组,数组中的每个元素都是指针

#include <stdio.h>
int main()
{
 int a = 10, b = 20, c = 30;
 int *p[3];
 p[0] = &a;
 p[1] = &b;
 p[2] = &c;
 return 0;
}

2、注意:int *p[3]; 等价于 (int *) p[3]; 因为[] 比 *的优先级要高先与p匹配。
3、思考:如何通过一个数组存储10个人的姓名?

char *name[10] = {"zhangsan", "lisi", "wangwu", "zhaoliu, "tianqi"};

name数组中保存了10个字符串常量的首地址(注意:没有保存字符串常量而是常量的首地址)
微信截图_20221030205335

指针变量的地址

1、我们在定义一个指针变量的时候,编译器会分配一块空间来存储这个指针变量的值,分配的这块
内存空间肯定有一个地址编码啦,那么这个地址编码肯定就是这个指针变量的地址啦

#include <stdio.h>
int main()
{
 int a = 10;
 int *p;
 p = &a;
 //将指针变量p的值以及变量a的地址打印出来(结果应该是两者相等)
 printf("p: %p, &a: %p\n", p, &a);
 //打印指针变量p的地址(存储指针变量p的内存空间的首地址)
 printf("&p: %p\n", &p);
 return 0;
}

微信截图_20221030205424
2、强调:指针变量p的值保存的是另外一个变量a的地址0x300800,指针变量的地址是存储p这个指针变量的值的那块内存空间的首地址:0x3007F8,这块空间中保存的值是0x300800

一级指针作为函数的形参

1、函数的形参为数组
如果函数的形参是数组,该形参的定义方法如下:

void func(int a[], int n)
{}

我们也可以将形参定义为指针类型:

void func(int *a, int n)
{}

在实际工作中我们通常使用第二种方法!
2、调用函数时需要传递字符串可将形参设计为char *类型

void func(char *p) //调用函数时将字符串的地址赋值给指针变量p
{
 printf("%c\n", p[0]);
}
int main()
{
 func("hello");
 return 0;
}

3、当形参为数组时,如果获取数组的长度呢?
微信截图_20221030205638

为什么sizeof(a)和sizeof(b)的值都是8呢?
原因:编译器在编译的时候将a和b当做了指针来处理了!!!

4、注意:如果函数的形参为指针,在函数体中一般先对指针的值进行判断,判断指针的值是否为NULL
微信截图_20221030205728

二级指针

1、用一个指针变量保存一个一级指针变量的地址,这个指针我们称之为二级指针
2、二级指针的定义

数据类型变量名;

int a = 10;
int *p = &a; //p为一级指针,保存变量a的地址
int **pp = &p; //pp为二级指针 保存一级指针p的地址

微信截图_20221030205902
3、二级指针的应用

//二级指针的使用
int a = 10;
int *p = &a;
int **p2 = &p; //二级指针p2保存了一级指针p的地址(p2指向了p )
int ***p3 = &p2; //三级指针
//*p2 == p == &a
printf("%p %p %p\n", *p2, p, &a);
//**p2 == *p == *(&a) == a
printf("%d %d %d %d\n", **p2, *p, *(&a), a);
**p2 = 100;
printf("%d %d %d %d\n", **p2, *p, *(&a), a);
//*p3 == p2 = &p
//**p3 == *p2 == p == &a
//***p3 == **p2 == *p == *(&a) == a
printf("***p3: %d\n", ***p3);

微信截图_20221030205956

0

评论区