指针和数组 【sizeof 、strlen与指针和数组的综合题、以及笔试题】
数组 以及 指针 笔试 sizeof strlen
2023-09-27 14:21:00 时间
一、一维数组
数组名:通常指的是首元素地址
两个例外:
1.sizeof(数组名) - 整个数组的所占空间大小
2.&数组名 - 整个数组的地址
int main()
{
//一维数组
int a[] = { 1,2,3,4 };
//sizeof是操作符,求内存空间所占的字节
printf("%d\n", sizeof(a));//16
//size(数组名) - 整个个数组的大小 4*4=16字节
printf("%d\n", sizeof(a + 0));//4/8
//首元素地址 +0 - 还是首元素地址 4/8
printf("%d\n", sizeof(*a));//4
//*a 首元素地址解引用 - 首元素(整型)4字节
printf("%d\n", sizeof(a + 1));//4/8
//首元素地址+1 - 第二个元素的地址 - 指针 4/8
printf("%d\n", sizeof(a[1]));//4
//a[1]是数组第二个元素,整型 - 4字节
printf("%d\n", sizeof(&a));//4/8
//&数组名 - 整个数组的地址 - 4/8
printf("%d\n", sizeof(*&a));//16
//*&a - a -sizeof(a) - 整个数组的大小 -16
printf("%d\n", sizeof(&a + 1));//4/8
//&a + 1 - 数组指针 +1,跳过整个数组,仍然是指针 4/8
printf("%d\n", sizeof(&a[0]));//4/8
//&a[0] - 首元素地址 4/8
printf("%d\n", sizeof(&a[0] + 1));//4/8
//&a[0] + 1 首元素地址+1,第二个元素的地址 4/8
return 0;
}
二、字符数组 - 数组里存的是单个字符
int main()
{
//字符数组 - 数组里存的是单个字符
char arr[] = { 'a','b','c','d','e','f' };
//printf("%d\n", sizeof(arr));//6
整个数组的大小 - 字符数组 - 6*1=6
//printf("%d\n", sizeof(arr + 0));//4/8
首元素地址+0 - 首元素地址 4/8
//printf("%d\n", sizeof(*arr));//1
*arr 首元素 - 字符型 - 1字节
//printf("%d\n", sizeof(arr[1]));//1
arr[1] - 数组第二个元素 - 字符型 - 1字节
//printf("%d\n", sizeof(&arr));//4/8
&数组名 - 整个数组的地址 - 4/8
//printf("%d\n", sizeof(&arr + 1));//4/8
&arr + 1 - 整个数组的地址 + 1 跳过整个数组 - 仍然是地址 4/8
//printf("%d\n", sizeof(&arr[0] + 1));//4/8
&arr[0] + 1 - 首元素地址+1 -第二个元素的地址 - 4/8
//char arr[] = { 'a','b','c','d','e','f' };
//strlen() - 字符串函数 - 计算字符串的个数,数到字符串结束标志\0前。
printf("%d\n", strlen(arr));//随机值
//字符串abcdef没有看到\0,strlen()会继续往后找,直到遇见\0结束,所以这里的值是未知的,随机值
printf("%d\n", strlen(arr + 0));//随机值
//首元素地址 +0 - 首元素地址 - 从首元素地址开始往后找,直到\0,同样也是随机值
//printf("%d\n", strlen(*arr));//非法访问error
//*arr 首元素 - strlen() 是通过指针来计算字符串的,所以这是错误的
//printf("%d\n", strlen(arr[1]));//非法访问error
//arr[1]数组第二个元素 - 同样错误
printf("%d\n", strlen(&arr));//随机值
//&arr - 整个数组的地址,随机值
printf("%d\n", strlen(&arr+1));//随机值-6
//整个数组的地址+1 - 跳过整个数组 - 随机值-6
printf("%d\n", strlen(&arr[0] + 1));//随机值-1
//首元素地址+1 - 跳过一个char - 第二个字符的地址 - 随机值-1
return 0;
}
三、字符数组 - 数组里存的是字符串
int main()
{
//字符数组 - 数组里存的是字符串 - a b c d e f \0
char arr[] = "abcdef";
//printf("%d\n", sizeof(arr));//7
字符的个数6个(abcdefg)+字符串的结束标志\0 = 7
//printf("%d\n", sizeof(arr + 0));//4/8
首元素地址+0 - 首元素地址 -4/8
//printf("%d\n", sizeof(*arr));//1
首元素 - 字符型 - 1
//printf("%d\n", sizeof(arr[1]));//1
第二个元素 - 字符型 -1
//printf("%d\n", sizeof(&arr));//4/8
整个数组的地址 - 4/8
//printf("%d\n", sizeof(&arr + 1));//4/8
整个数组的地址 +1 跳过整个数组 - 仍然是地址 - 4/8
//printf("%d\n", sizeof(&arr[0] + 1));//4/8
//首元素地址 +1 - 第二个元素的地址 -4/8
//char arr[] = "abcdef";
printf("%d\n", strlen(arr));//6
//首元素地址 - 直到\0 - 一共6个字符
printf("%d\n", strlen(arr + 0));//6
//首元素地址 - 直到\0 - 6
//printf("%d\n", strlen(*arr));//非法访问error
//首元素 - strlen()通过指针计算 - 非法访问
//printf("%d\n", strlen(arr[1]));//非法访问error
//第二个元素 - 同理 - 非法访问
printf("%d\n", strlen(&arr));//6
//整个数组的地址 - 相当于从首元素地址开始 - 直到\0 -6
printf("%d\n", strlen(&arr + 1));//随机值
//整个数组的地址 +1 - 跳过整个数组 - 此时已经错过了字符abcdef的\0了,只能往后一直找直到遇到\0
printf("%d\n", strlen(&arr[0] + 1));//
//首元素地址 +1 - 跳过一个元素到第二个元素的地址 - 6-1=5
return 0;
}
四、 指针 - 指向一个字符串的指针
int main()
{
char* p = "abcdef";
//printf("%d\n", sizeof(p));//4/8
p 是指针 - 指向字符串起始a - 4/8
//printf("%d\n", sizeof(p + 1));//4/8
p + 1,指向第二个字符 -仍然是指针 - 4/8
//printf("%d\n", sizeof(*p));//1
*p得到第一个元素 - 字符型 - 1
//printf("%d\n", sizeof(p[0]));//1
p[0] 等价于 *(p+0) - 第一个元素 - 字符型 - 1
//printf("%d\n", sizeof(&p));//4/8
p本身是一个指向字符串"abcdef"的指针 - &p 对指针取地址 - 仍然是地址 -4/8
//printf("%d\n", sizeof(&p + 1));//4/8
对指针取地址 + 1 - 指针 - 4/8
//printf("%d\n", sizeof(&p[0] + 1));//4/8
//首元素地址 +1 - 地址 - 4/8
// char* p = "abcdef";
printf("%d\n", strlen(p));//6
//p 是指针 - 指向首元素a - 往后数直到\0 - 6
printf("%d\n", strlen(p + 1));//5
//指针p +1 - 指向第二个元素b的地址 - 6-1=5
//printf("%d\n", strlen(*p));//非法访问error
//*p 首元素 - 非法访问
//printf("%d\n", strlen(p[0]));//非法访问error
//首元素 - 非法访问
printf("%d\n", strlen(&p));//随机值
//p为指针 - &p对指针取地址 - 仍是地址 -此时是随机值,因为不知道p的地址的\0在哪
printf("%d\n", strlen(&p + 1));//随机值
//p的地址+1 - 随机值
printf("%d\n", strlen(&p[0] + 1));//5
//首元素取地址 +1 - 指向第二个元素b的地址 - 6-1=5
return 0;
}
五、二维数组
int main()
{
//二维数组
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//48
//整个数组的大小 - 3行*4列*4(int)=48
printf("%d\n", sizeof(a[0][0]));//4
//第一行第一列的元素 - 首元素 - int - 4
printf("%d\n", sizeof(a[0]));//16
//a[0]第一行数组名
//第一行整个一维数组的大小4*4=16
//二维数组第一行 - 第一个一维数组 的大小 - 4*4=16
printf("%d\n", sizeof(a[0] + 1));//4/8
//a[0]并没有单独放在sizeof里
//此时表示首元素a[0][0],+1,a[0][1]
//第一行第二个元素的地址,4/8
printf("%d\n", sizeof(*(a[0] + 1)));//4
//第一行第二个元素地址,解引用
//元素int - 4
printf("%d\n", sizeof(a + 1));//4/8
//首元素地址 + 1 - 第一个一维数组地址 +1 - 第二个一维数组地址 -4/8
printf("%d\n", sizeof(*(a + 1)));//16
//第二个一维数组 -16
printf("%d\n", sizeof(&a[0] + 1));//4/8
//首元素地址+1 - 第一个一维数组的地址 +1 -第二个一维数组的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//16
//第二个一维数组 - 16
printf("%d\n", sizeof(*a));//16
//首元素 - 第一个一维数组 - 4*4= 16
printf("%d\n", sizeof(a[3]));//16
//虽然不存在 arr[3],但是可以假设存在 - 第四个一维数组 - 16
return 0;
}
六、指针笔试题
1.
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
//整个数组地址+1 - 跳过整个数组 -强制类型转换为int*
printf("%d,%d", *(a + 1), *(ptr - 1));//2,5
//*(a+1) - *(首元素地址+1)- 2
//指针ptr最开始移动到数组后面的第一个元素 ,此时指针类型还是数组指针
//强制类型转换 - int*
//*(ptr - 1) - 往前移动一个整型 ,解引用 - 5
return 0;
}
2.
//2
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
p = 0x100000;
printf("%p\n", p + 0x1);//0x100014
//0x1 - 十六进制的1
//p为指针 - 指针类型是结构体指针 - 那么移动1就是移动一个结构体的长度 - 这个结构体20字节
// 结构体指针 + 1 = 步长为该结构体的大小: 20字节(014)
//0x100000 + 1 = 0x100014
printf("%p\n", (unsigned long)p + 0x1);
//p为指针 - 强制类型转换为unsigned long 这样的整型
//此时 p = 0x100000 不是地址,而是具体的整型的数值了
//0x100000 + 1 =0x100001
printf("%p\n", (unsigned int*)p + 0x1);
//p为结构体指针 - 强制类型转换为unsigned int* 整型指针
// 整型指针+ 1 ,步长:4字节
//0x100000 + 1 =0x100004
return 0;
}
3.
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);//0x00000004 0x02000000
//&a整个数组的地址+1,移动到数组最后一个元素后面的位置,数组指针
//强制类型转换成int* 整形指针
//ptr1[-1]可以理解为,*(ptr1-1),往前移动一个整型,解引用得到了4,
//十六进制 0x00000004
//%x 打印得到 4(前面的0x00000000省略了)
//a为首元素地址,一个十六进制数,假设 0x 00 11 22 33
//强制类型转换为整型,此时这个地址成为一个数值,+1,得到0x 00 11 22 34
//此时再强制类型转换为 int* 此时变成指向这个 0x 00 11 22 34 地址的指针了
// 如果为小端存储,地址由低到高,内存如下:
// 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
//相当于是首元素地址+1字节 ,指向了首元素01 后的第一个00
//*ptr2 解引用这个地址,从这个地址开始往后取4字节得到 00 00 00 02
//十六进制为 0x02000000
//%x 打印得到 2000000(前面的0x0省略了)
return 0;
}
4.
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);//
// int a[3][2] = { (0, 1), (2, 3), (4, 5) };逗号表达式
// int a[3][2] = { 1, 3, 5 };
//p为首元素指针
//打印p[0] => *(p+0) => 1
return 0;
}
5.
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]);
//fffffffc,-4
//画图理解:a[5][5],感叹号所示位置为两个符号相隔四个字节为 -4
//|` _ _ _ `|_ _ _ ` _|_ _ ` _ _|_ ` _ ! _|_ _ ! _ _|
// &a[4][2]
// p[0] p[4][2]
//-4
//10000000 00000000 00000000 00000100
//11111111 11111111 11111111 11111011
//11111111 11111111 11111111 11111100 - -4的补码
//转换为十六机制 ff ff ff fc
return 0;
}
6.
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));//10,5
//1, 2, 3, 4, 5| 6, 7, 8, 9, 10
//&aa+1,整个数组地址+1,跳过整个数组;转换为int*指针 - 1,得到10
//1 2 3 4 5| 6 7 8 9 10
// arr+1(数组指针)
//*(arr+1)得到整个数组,然后强制类型转换为int*,指向元素6
//ptr2-1,往前移动一个整型,指针指向5
return 0;
}
7.
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);//at
//work at alibaba
//pa指向a[0]w,pa++指向a
//打印字符串得到at
return 0;
}
8.
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;
}
相关文章
- Numpy基本操作——numpy中数组的基本操作
- 数组
- JVM 中对象的内存布局以及如何计算对象和数组的大小
- mongoDB查询投射以及数组查询
- JSON-JSON字符串转换成JSON对象、JSON对象数组、java实体类以及保存到List列表中
- Swift JSON字符串和字典以及数组的互转
- 【C语言】制作“学生管理成绩系统”,内容包括【系统显示】【录入信息】【删除信息】【等级评定】【成绩排序】【成绩修改】【查找学生】涉及循环、结构体和数组等
- LeetCode_前缀和_困难_862.和至少为 K 的最短子数组
- 传智播客Java 二维数组
- 闲话链表的诞生以及它与数组亲缘关系的故事
- Java数据结构和算法——数组、单向链表、双向链表
- js 数组 reduce() 方法
- ES数组类型字段搜索以及数组空值搜索
- C语言笔记第03章:数组