C语言-指针练习


C语言-指针练习

以下皆在32位平台,地址的大小在32位平台下是4个字节,在64位平台下是8个字节
数组名是首元素的地址,但以下两种情况例外:

  1. sizeof(数组名) - 数组名表示整个数组
  2. &数组名 - 数组名表示整个数组

一维数组

整型数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int a[]={1,2,3,4};
printf("%d\n",sizeof(a));//16
//sizeof(数组名),数组名表示整个数组,4*4=16。
printf("%d\n",sizeof(a+0));//4
//数组名表示首元素地址,a+0还是数组首元素地址,地址的大小在32位平台下是4个字节。
printf("%d\n",sizeof(*a));//4
//数组名表示首元素地址,*a表示首元素
printf("%d\n",sizeof(a+1));//4
//数组名表示首元素地址,a+1表示第二个元素的地址
printf("%d\n",sizeof(a[1]));//4
//下标从0开始,a[1]表示第二个元素
printf("%d\n",sizeof(&a));//4
//&数组名,数组名表示整个数组,&a表示整个数组的地址,但只要是地址,在32位平台下就是4个字节
printf("%d\n",sizeof(*&a));//16
//&a表示整个数组的地址,*&a表示整个数组,整个数组的大小为16
printf("%d\n",sizeof(&a+1));//4
//&a表示整个数组的地址,&a+1表示跳过这个数组,但还是地址,所以是4个字节
printf("%d\n",sizeof(&a[0]));//4
//首元素地址
printf("%d\n",sizeof(&a[0]+1));//4
//第二个元素地址

字符数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
char a[]={'a','b','c','d','e','f'};
printf("%d\n",sizeof(a));//6
//sizeof计算整个数组大小 6*1=6
printf("%d\n",sizeof(a+0));//4
//a是首元素地址,a+0还是首元素地址,地址的大小在32位平台下是4个字节。
printf("%d\n",sizeof(*a));//1
//数组名表示数组首元素地址,*a表示首元素
printf("%d\n",sizeof(a[1]));//1
//a[1]第二个元素
printf("%d\n",sizeof(&a));//4
//&a整个数组的地址,但还是地址,4个字节
printf("%d\n",sizeof(&a+1));//4
//&a+1跳过整个数组后的地址,还是地址,4个字节
printf("%d\n",sizeof(&a[0]+1));//4
//&a[0]+1第二个元素地址,4个字节

//strlen函数从字符串的开头位置依次向后计数,遇见\0结束,最终计算的字符串长度不包括\0,strlen的参数是地址。
printf("%d\n",strlen(a));//随机值
printf("%d\n",strlen(a+0));//随机值
printf("%d\n",strlen(*a));//错误,strlen要的参数是地址
printf("%d\n",strlen(a[1]));//错误,strlen要的参数是地址
printf("%d\n",strlen(&a));//随机值
printf("%d\n",strlen(&a+1));//随机值-6
printf("%d\n",strlen(&a[0]+1));//随机值-1
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
char a[]="abcdef";
printf("%d\n",sizeof(a));//7
//sizeof(a)计算整个数组的大小,""里面的字符串最后自动加\0,所以为7个字节
printf("%d\n",sizeof(a+0));//4
//a+0首元素地址
printf("%d\n",sizeof(*a));//1
//*a首元素
printf("%d\n",sizeof(a[1]));//1
//a[1]第二个元素
printf("%d\n",sizeof(&a));//4
//&a整个数组的地址
printf("%d\n",sizeof(&a+1));//4
//&a+1跳过整个数组后的地址,只要是地址,在32位平台下就是4个字节
printf("%d\n",sizeof(&a[0]+1));//4
//&a[0]第一个元素的地址,&a[0]+1第二个元素的地址

//strlen函数从字符串的开头位置依次向后计数,遇见\0结束,最终计算的字符串长度不包括\0,strlen的参数是地址。
//""里面的字符串最后自动加\0
printf("%d\n",strlen(a));//6
printf("%d\n",strlen(a+0));//6
printf("%d\n",strlen(*a));//错误,strlen要的参数是地址
printf("%d\n",strlen(a[1]));//错误,strlen要的参数是地址
printf("%d\n",strlen(&a));//6
printf("%d\n",strlen(&a+1));//随机值
printf("%d\n",strlen(&a[0]+1));//5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char *p="abcdef";//把常量字符串的第一个字符'a'的地址存放到p中。
printf("%d\n",sizeof(p));//4
//指针变量p的大小
printf("%d\n",sizeof(p+1));//4
//p+1得到'b'的地址
printf("%d\n",sizeof(*p));//1
//*p 第一个字符'a'
printf("%d\n",sizeof(p[0]));//1
//p[0] 第一个字符'a'
printf("%d\n",sizeof(&p));//4
//取出p的地址
printf("%d\n",sizeof(&p+1));//4
//跳过p后的地址还是地址
printf("%d\n",sizeof(&p[0]+1));//4
//&p[0]:'a'的地址,&p[0]+1:'b'的地址,还是地址

printf("%d\n",strlen(p));//6
printf("%d\n",strlen(p+1));//5
printf("%d\n",strlen(*p));//错误
printf("%d\n",strlen(p[0]));//错误
printf("%d\n",strlen(&p));//随机值
printf("%d\n",strlen(&p+1));//随机值
printf("%d\n",strlen(&p[0]+1));//5

二维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int a[3][4]={0};
printf("%d\n",sizeof(a));//48
//数组总大小3*4*4
printf("%d\n",sizeof(a[0][0]));//4
//数组第一行第一个元素的大小
printf("%d\n",sizeof(a[0]));//16
//数组第一行的总大小
printf("%d\n",sizeof(a[0]+1));//4
//a[0]表示第一行的数组名,数组名代表数组首元素地址,所以a[0]就是第一行第一个元素的地址,所以a[0]+1代表数组第一行第二个元素的地址
printf("%d\n",sizeof(*(a[0]+1)));//4
//数组第一行第二个元素
printf("%d\n",sizeof(a+1));//4
//a表示数组第一行(首元素)的地址,a+1表示数组的第二行的地址
printf("%d\n",sizeof(*(a+1)));//16
//a+1表示数组的第二行的地址,*a数组第二行的总大小
printf("%d\n",sizeof(&a[0]+1));//4
//数组第二行的地址
printf("%d\n",sizeof(*(&a[0]+1)));//16
//数组第二行的总大小
printf("%d\n",sizeof(*a));//16
//数组第一行的总大小
printf("%d\n",sizeof(a[3]));//16
//sizeof里面的内容不参与运算,只看里面内容的类型

其他

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
//结构体A类型的变量大小为20字节
//p值为0x100000。下方表达式的值为多少
#include <stdio.h>
struct A
{
int n;
char *pc;
short sh;
char a[2];
short s[4];
}* p;
int main()
{
p=(struct A*)0x100000;
printf("%p\n",p+0x1);//0x100014
//结构体A类型的变量大小为20字节,20转为16进制为0x14
//0x100000+0x14==0x100014
printf("%p\n",(unsigned long)p+0x1);//0x100001
//0x100000转化为十进制为1048576
//1048576+1==1048577转化为16进制为0x100001
printf("%p\n",(unsigned int*)p+0x1);//0x100004
//unsigned int类型为4个字节
//0x100000+4== 0x100004
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//当前机器为小端存储模式
//打印结果是什么?
#include <stdio.h>
int main()
{
int a[4] = {1,2,3,4};
//小端存储模式,数组存放在内存中的样子为:
//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
int *ptr1 = (int*)(&a+1);
int *ptr2 = (int*)((int)a+1);
//(int)a将a强制转换成整数,(int)a+1就是整数+1
//(int*)((int)a+1)相当于地址向后偏移一个字节
//00 00 00 02
printf("%x,%x\n",ptr1[-1],*ptr2);//4,2000000
//ptr1[-1]==*(ptr1+(-1))==*(ptr1-1)
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
//打印结果是什么?
#include <stdio.h>
int main()
{
int a[3][2]={(0,1),(2,3),(4,5)};
//逗号表达式 1 3 5
int *p;
p=a[0];
//a[0]代表a[0][0]地址
printf("%d",p[0]);//1
//p[0]==*(p+0)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//打印结果是什么?
#include <stdio.h>
int main()
{
int a[2][5]={1,2,3,4,5,6,7,8,9,10};
int *ptr1=(int*)(&a+1);
//&a取整个数组的地址,&a+1跳过数组的地址
int *ptr2=(int*)(*(a+1));
//a是a[0]的地址,a+1是a[1]的地址,*(a+1)表示a[1]
//a[1]表示a[1][0]的地址
printf("%d,%d\n",*(ptr1-1),*(ptr2-1));//10,5
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//打印结果是什么?
#include <stdio.h>
int main()
{
char* a[]={"first","second","third","fourth"};
char** ap[]={a+3,a+2,a+1,a};
char*** app=ap;
printf("%s\n",**++app);//third
//++app是ap[1]的地址,*++app是ap[1]:a+2,a+2是a[2]的地址,**++app是a[2]
printf("%s\n",*--*++app+3);//st
//此时app是ap[1]的地址
//++app是ap[2]的地址,*++app是ap[2]:a+1,a+1是a[1]的地址,--*++app是a[0]的地址
//*--*++app是a[0]:first,*--*++app+3是st
printf("%s\n",*app[-2]+3);//rth
//此时app是ap[2]的地址
//*app[-2]等同于*(*(app-2)),*app[-2]为a[3]:fourth,*app[-2]+3为rth
printf("%s\n",app[-1][-1]+1);//econd
//此时app是ap[2]的地址
//app[-1][-1]等同于*(*(app-1)-1),app[-1][-1]为a[1]:second,app[-1][-1]+1是econd
return 0;
}


Author: ljs
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source ljs !
评论
  TOC