C语言 day8 | 我的日常分享

C语言 day8

指针

数组元素的指针

案例1:通过数组元素指针遍历数组的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
int main(int argc,char *argv[]){
int arr[5] = {10,20,30,40,50};
int n = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int *p = &arr[0];

for(i = 0; i < n; i++){
//printf("arr[i]=%d \n",arr[i]);
printf("arr[i]=%d ",*(p+i));
//p+i代表的是第i个元素的地址
//*(p+i)代表的是第i个元素的值
}
printf("\n");

return 0;
}

运行结果:
图片

案例2:通过数组元素指针获取键盘输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
int main(int argc,char *argv[]){
int arr[5] = {10,20,30,40,50};
int n = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int *p = &arr[0];

for(i = 0; i < n; i++){
//scanf("%d",&arr[i]);
scanf("%d",p+i);
}

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

return 0;
}

运行结果:
图片

案例3:问,输出的是多少?

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(int argc,char *argv[]){
int arr[5] = {10,20,30,40,50};
int *p = &arr[2];
p++;
printf("%d",*(p+1));

return 0;
}

运行结果:
图片


数组的 [] 和 *() 的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
int main(int argc,char *argv[]){
//数组名arr作为地址代表的是 首元素地址(第0个元素的地址)
//数组名arr作为类型 代表的是数组的总大小 sizeof(arr)
int arr[5] = {10,20,30,40,50};
int *p = NULL;

p = &arr[0];//arr == &arr[0]

printf("%d\n",arr[1]);//20
printf("%d\n",*(arr + 1));//20

printf("-----------------------------");

printf("%d\n",*(1 + arr));//20
printf("%d\n",1[arr]);//20 也可以哦!
// 在使用中 []的本质就是*()的缩写 在早期C语言中是没有[]的,所以的[]用的都是*()
//缩写的规则就是,+左边的值放在[]的左边,+右边的值放在[]的里面,

return 0;
}

运行结果:
图片

为啥 arr代表的是 数组第0个元素的地址

由上面的结论可得:

1
2
3
4
&arr[0] = & *(arr+0) = arr+0 = arr;
//& * 在一起可以抵消


总结:

  1. [] 是*() 的缩写
  2. 数组名arr代表的是数组 首元素的地址(第0个元素的地址)

arr 和 &arr 的区别(了解)

arr:数组的首元素地址

&arr:数组的首地址(数组名取地址没啥意义的,这个只是一个表达式的结合)

案例:

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
int main(int argc,char *argv[]){
int arr[5] = {10,20,30,40,50};

printf("arr=%u\n",arr);
printf("arr+1=%u\n",arr+1);
printf("------------------------\n");
printf("&arr=%u\n",&arr);
printf("&arr+1=%u\n",&arr+1);

return 0;
}

运行结果:
图片

分析:

arr+1增加了4字节,跳过1个元素
&arr+1增加了20字节,跳过5个元素即整个数组

结论:

  1. arr代表的是数组首元素的地址,+1跳过一个元素
  2. &arr代表的是数组的首地址,+1跳过整个数组
  3. arr和&arr在地址编号上是一样的,但是类型是完全不一样的

注意:数组名 arr 是个符号常量,不能被修改(赋值) arr++ (错误)


指向同一个数组的两个元素的指针变量间的关系

案例1:问,p2-p1=?12还是3?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
int main(int argc,char *argv){
int arr[5] = {10,20,30,40,50};
int *p1 = arr;
int *p2 = arr+3;


//1、指向同一个数组的两个指针变量相减,返回的是相差的元素的个数
printf("%d",p2-p1);//3

//2、指向同一个数组的指针变量可以比较大小
if(p2>p1){
printf("p2>p1");
}else{
printf("p2<=p1");
}

//3、指向同一个数组的两个指针变量,可以相互赋值
p1=p2;//p1和p2指向同一处

//4、指向同一数组的两个指针变量,不要相加
p1+p2;

//5、[]在不越界的情况下,里面可以为负数
printf("%d\n",p2[-2]);// 展开为*( p2 + (-2) )= *(p2-2)=20
return 0;
}

案例2:

#include<stdio.h>
int main(int argc,char *argv){
    int arr[5] = {10,20,30,40,50};
    int *p = arr;

    printf("%d\n",*p++);//10
    printf("%d\n",(*p)++);//20
    printf("%d\n",*(p++));//21
/*
第一次做:20,21,30

优先级() > ++(从右至左) = *(从右至左)

*/
    return 0;
}

图片
讲解: