目录
数组名的意义:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。
每道题都可以先忽视旁边注释,自行做题后再对照答案
由于后面部分题都是画图来理解,所以文字描述很少,但只要学会这两篇文章, 理解起来应该不难:
练习一
一维数组
//思考这里的sizeof里面代表什么,最终输出是什么?
#include<stdio.h>
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a)); //这里的a在sizeof里面单独出现,
所以表示整个数组,所以输出为16
printf("%d\n", sizeof(a + 0)); //这里的a不在sizeof中单独出现,
代表的是首元素的地址,加0相当于每当,
所以还是首元素的地址,输出为4/8
printf("%d\n", sizeof(*a)); //这里的a不在sizeof里面单独出现,
所以这里的a代表首元素的地址,*解引用后,
相当于首元素,所以是int类型的元素,输出为4
printf("%d\n", sizeof(a + 1)); //这里的a不在sizeof里面单独出现,
所以表示的首元素的代表的是首元素的地址,
加1后代表地址加1,
也就是加该指针所指向的类型的大小,
也就是指向下一个元素的指针,
所以输出为4/8
printf("%d\n", sizeof(a[1])); //a[1]其实就是元素里第二个元素,也就是2,
大小是int类型,也就是4
printf("%d\n", sizeof(&a)); //这里的a是&a,也就是整个数组的地址,
输出为4/8
printf("%d\n", sizeof(*&a)); //这里的a是&a,也就是整个数组地址,
解引用后代表的是整个数组,也就是4个int
输出为16
printf("%d\n", sizeof(&a + 1)); //这里的a是&a,代表的是整个数组的地址,
加1代表的是跳过整个数组,
虽然指向的下一个数组是位置的,
但只要是指针,大小就为4/8
printf("%d\n", sizeof(&a[0])); //这里相当于取出a[0]的地址,也就是4/8
printf("%d\n", sizeof(&a[0] + 1));//这里相当于取出a[0]的地址,
加1也就是加其所指向类型的大小,
也就是指向a[1]的指针
return 0;
}
指针大小为4是因为在32位平台下测试的,如果是64位平台下测试,答案如下:
练习二
字符数组
//先自行做题,做完再看右侧的注释解析
#include<stdio.h>
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr)); //这里的arr在sizeof里单独出现
代表的是整个数组,
所以输出为6
printf("%d\n", sizeof(arr + 0)); //这里的arr不在sizeof里单独出现,
代表的是首元素的地址,
加0相当于没加,所以输出为4/8
printf("%d\n", sizeof(*arr)); //这里的arr在sizeof里单独出现,
代表的是首元素的地址,
解引用也就是代表第一个元素,
所以输出为1
printf("%d\n", sizeof(arr[1])); //这里的arr[1]代表的是
数组第二个元素,输出为1
printf("%d\n", sizeof(&arr)); //这里的arr是&arr,
代表的是整个数组的地址,
输出为4/8
printf("%d\n", sizeof(&arr + 1)); //这里的arr是&arr,
代表的是整个数组的地址,
加1表示跳过整个数组,
指向下一个数组的地址,
所以输出为4/8
printf("%d\n", sizeof(&arr[0] + 1)); //这里是取出arr[0]的地址,
加一表示变成指向arr[1]的指针,
所以输出为4/8
return 0;
}
练习三
⼆维数组
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a)); //这里的a代表整个数组,
所以输出为48
printf("%d\n", sizeof(a[0][0])); //这里的a相于整个数组的第一个元素,
所以输出为4
printf("%d\n", sizeof(a[0])); //这里的a[0]相当于整个二维数组的第一个
元素,第一个元素是一个由四个元素的
一维数组所以输出为16
printf("%d\n", sizeof(a[0] + 1)); //这里的a[0]相当于整个数组的
第一个a[0][0]元素d地址
加1相当于是这个数组的第二个元素,
的地址,所以输出为4/8
printf("%d\n", sizeof(*(a[0] + 1))); //这里的同上,也就是a[0][1]那个元素
输出为4
printf("%d\n", sizeof(a + 1)); //这里的a表示首元素地址,也就是一个
含有四个元素的一维数组
加1表示跳过一个一维数组,指向了下一个
数组的地址,所以输出为4/8
printf("%d\n", sizeof(*(a + 1))); //这里解引用也就是第二个一维数组的全部元素
输出为16
printf("%d\n", sizeof(&a[0] + 1)); //&a[0]也就是对第一行的数组名取地址
&a[0]+1得到的是第二行的地址
输出为4/8
printf("%d\n", sizeof(*(&a[0] + 1))); //同时解引用后也就是第二行的元素
输出为16
printf("%d\n", sizeof(*a)); //这里a表示首元素的地址也就是第一行的地址
*解引用也就是第一行的元素,输出为16
printf("%d\n", sizeof(a[3])); //这里虽然没有a[3]的存在,
但a[3]同样也是一个一维数组,
所以输出的是16
这里没有越界访问,没有真的去访问第四行
return 0;
}
练习四
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
练习五
#include<stdio.h>
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;
//假设结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1); //这里指针+1也就是加一个
结构体大小20,单输出为16进制
所以最终输出为0X100014
printf("%p\n", (unsigned long)p + 0x1); //这时候p强制类型转换成了
无符号长整形,加1说白了
也就是+1,输出为0X100001
printf("%p\n", (unsigned int*)p + 0x1); //这里p强制转化成一个int*类型的
指针,加1也就是加一个int类型
的大小,所以输出为0X100004
return 0;
}
练习六
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf("%d", p[0]);
return 0;
}
a[0]表示首元素的地址,即a[0][0]的地址,&a[0][0]赋值给了p,p[0]其实就相当于*(p+0)也就是第一个元素,也就是1。
练习七
#include <stdio.h>
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
p[4][2]和a[4][2]相差了4个元素,相减也就是-4, -4要%p也就是16进制打印
最终也就是FF FF FF FC
练习八
#include <stdio.h>
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);
int *ptr2 = (int *)(*(aa + 1));
printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));
return 0;
}
解引用后答案为10和5
练习九
#include <stdio.h>
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp); //POINT
printf("%s\n", *--*++cpp+3); //ER
printf("%s\n", *cpp[-2]+3); //ST
printf("%s\n", cpp[-1][-1]+1); //EW
return 0;
}
练习十
#include<stdio.h>
int main()
{
int a[4] = { 1,2,3,4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x", ptr1[-1], *ptr2);
return 0;
}
取出来为02 00 00 00.
这题考察的是数据在内存的存储,如果不能理解,可以了解完这篇文章在做一遍: