#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
判断下列代码的输出结果
/*
解题思路:
1、首先明确此代码考察的是对sizeof的使用方法的熟悉程度
sizeof是一个计算数据大小的一个操作符,对于一个数组。
2、其次明确sizeof()里面的数组名表示的是什么含义
(1)sizeof(数组名),其中数组名表示的是整个数组
(2)(&数组名) ,其中数组名表示的是整个数组
3、对代码进行分析
*/
int main()
{
//一维数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//16 求整个数组的大小:4*4
printf("%d\n", sizeof(a + 0));//4/8 a+0表示的是指向数组首元素地址的指针移动0位,其本质还是指针
printf("%d\n", sizeof(*a));//4 *a表示的是对指向数组首元素地址的指针进行解引用,得到的是数组的首元素
printf("%d\n", sizeof(a + 1));//4/8 与a+0类似
printf("%d\n", sizeof(a[1]));//4 a[1]表示的是数组的首元素
printf("%d\n", sizeof(&a));//4/8 &a表示的是对整个数组取地址,其本质还是个地址
printf("%d\n", sizeof(*&a));//16 *&a表示的是对a取地址再进行解引用,其本质表示的是整个数组,相当于求数组的大小
printf("%d\n", sizeof(&a + 1));//4/8 &a+1,其本质是地址
printf("%d\n", sizeof(&a[0]));//4/8 &a[0] —— a先与[0]结合,再&,表示的是对数组首元素取地址
printf("%d\n", sizeof(&a[0] + 1));//4/8 与&a[0]类似
//注:只要是地址(指针),其大小就是4个或者8个字节,32位系统占4个字节,64位系统占8个字节
return 0;
}
#include<string.h>
int main()
{
//字符数组
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//6 6*1
printf("%d\n", sizeof(arr + 0));//1
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//4/8
printf("%d\n", sizeof(&arr));//4/8
printf("%d\n", sizeof(&arr + 1));//4/8
printf("%d\n", sizeof(&arr[0] + 1));//4/8
//strlen()参数部分需要的是地址
printf("%d\n", strlen(arr));//随机值 由于strlen只有遇到\0才会停止查找,而数组中没有0,所以为随机值
printf("%d\n", strlen(arr + 0));//随机值
//printf("%d\n", strlen(*arr));//err
//printf("%d\n", strlen(arr[1]));err
//printf("%d\n", strlen(&arr));strlen接收的是const char*的类型,不接收数组指针类型
//printf("%d\n", strlen(&arr + 1));//同理
printf("%d\n", strlen(&arr[0] + 1));//随机值-1
return 0;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7
printf("%d\n", sizeof(arr + 0));//4/8
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4/8
printf("%d\n", sizeof(&arr + 1));//4/8
printf("%d\n", sizeof(&arr[0] + 1));//4/8
printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr + 0));//6
/*printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));//违法访问
printf("%d\n", strlen(&arr));//err
printf("%d\n", strlen(&arr + 1));*/
printf("%d\n", strlen(&arr[0] + 1));//随机值
return 0;
}
int main()
{
const char *p = "abcdef";//将a的地址存在p指针中
printf("%d\n", sizeof(p));//4/8
printf("%d\n", sizeof(p + 1));//4/8
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//1 p[0]==*(p+0) 可以将p看成是数组名
printf("%d\n", sizeof(&p));//4/8
printf("%d\n", sizeof(&p + 1));//4/8
printf("%d\n", sizeof(&p[0] + 1));//4/8
//注意:strlen()函数里面传的参数的完整类型是const char*类型,若传参传入其他类型时,系统会进行抱错,在低版本编译器中只会报警告,严格来说是错误的
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
printf("%d\n", strlen(&p[0] + 1));//5 &p[0] + 1实际和p + 1表示结果是一样的
return 0;
}
int main()
{
//二维数组
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//48=12*4
printf("%d\n", sizeof(a[0][0]));//4
printf("%d\n", sizeof(a[0]));//16=4*4 sizeof(数组名)计算的是整个数组的大小
//二维数组可以看成是元素由一维数组构成的一维数组,a[0]可以看成是二维数组第一行的数组名,而sizeof(数组名)其中的数组名表示的是整个数组,而不是首元素地址
printf("%d\n", sizeof(a[0] + 1));//4/8 a[0] + 1表示的是首元素地址加1,即表示的是第一行的第二个元素地址。第二行首元素地址应为a[1]+0
printf("%d\n", sizeof(*(a[0] + 1)));//4 *(a[0] + 1)表示的是第一行第二个元素
printf("%d\n", sizeof(a + 1));//4/8 a + 1是第二行数组的地址
printf("%d\n", sizeof(*(a + 1)));//16=4*4 表示第二行数组的元素
printf("%d\n", sizeof(&a[0] + 1));//4/8 a[0]可以看成是二维数组第一行的数组名,&a[0]表示的是第一行的整个数组的地址,&a[0]+1表示的是第二行的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//16=4*4 表示第二行数组的元素
printf("%d\n", sizeof(*a));//16=4*4 a是首元素地址,其实就是第一行的数组。*a即为第一行数组的元素
printf("%d\n", sizeof(a[3]));//16
//a[3]表示的是第四行的地址,sizeof()内的表达式是不参与真是运算的!!!,只是根据()里的类型计算它的大小。与arr[0]其实是类似的
return 0;
}
/*总结:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。*/
指针笔试题——求下列指针代码的结果
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
/*&a,取出的是整个数组的地址,&a+1跳过的是整个数组。再将数组指针类型的指针转换成整形指针类型赋给ptr。注意,前面跳过数组时是跳了5个整形,而限制ptr-1只
向前移了1个整形,所以最后指针指向的位置是第5个元素的地址,而非第一个元素的地址*/
printf("%d,%d", *(a + 1), *(ptr - 1));//输出结果为2,5
return 0;
}
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
p = (struct Test*) 0x100000;
printf("%p\n", p + 0x1);//p是一个结构体指针,指针+1跳过整个一个结构体指针,也就是20个字节。换算成16进制则为0x 10 00 14
printf("%p\n", (unsigned long)p + 0x1);//将p强转为一个无符号长整型,+1,则表示的是数值加1.直接在地址上+1即可,即0x100001
printf("%p\n", (unsigned int*)p + 0x1);//将p强转为无符号整形指针类型,由于是整形,所以+1跳过四个字节。所以结果为0x100004
return 0;
}
int main()
{
int a[4] = { 1, 2, 3, 4 };
int *ptr1 = (int *)(&a + 1);//&a——将整个数组a取地址并跨国整个数组,然后将数组指针强转为int*类型赋给ptr1
int *ptr2 = (int *)((int)a + 1);//将a强转为整形,并+1。(整数+1,实际上相当于向后偏移一个字节)后,再将其强转为int*类型赋给ptr2
printf("%x,%x", ptr1[-1], *ptr2);//结果为4,2000000
// ptr1[1]可以看成是一个指向数组的整形指针向前挪动一位的数组。由于int类型的指针只能取出四个字节的空间,因此*pte2为2000000
return 0;
}
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//{(0.1)}表示的是括号表达式,逗号表达式结果是最后一个表达式的结果
int *p;
p = a[0];
printf("%d", p[0]);//p[0]相当于*(p+0),输出结果是1
return 0;
}
int main()
{
int a[5][5];
int(*p)[4];
p = (int(*)[4])a;//将a的类型强转为(int(*)[4])并赋给p指针
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//p[4][2]可以看成是*(*(p+4)+2)。答案为:FFFFFFFC,-4
return 0;
}
int main()
{
int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int *ptr1 = (int *)(&aa + 1);//&arr为取出整个二维数组的地址,+1跳过整个二维数组,再将数组指针类型强转为int*类型赋给ptr1
int *ptr2 = (*(aa + 1));//aa为第一行数组的地址,aa+1为第二行数组的地址,对其解引用为第二行首元素的地址(*(aa+1)可看成aa[1]),再赋给ptr2
printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
//ptr1-1为将ptr1指针向左移动一个整形即4个字节的空间再对其解引用,答案为10
//ptr2-1为在对第二行首元素指针进行向左移动4个字节的空间再对其解引用,答案为5
return 0;
}
int main()
{
const char *a[] = { "work","at","alibaba" };
const char**pa = a;//把指针数组的首元素地址传给pa
pa++;//表示的是第二个字符串的首元素地址
printf("%s\n", *pa);//%s只有遇到\0才会停止打印,答案为:at
return 0;
}
int main()
{
const char *c[] = { "ENTER","NEW","POINT","FIRST" };
const char**cp[] = { c + 3,c + 2,c + 1,c };
const char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp + 3);//cpp这样的值一直在发生变化,上卖弄对cpp++操作后的结果将保留到下一个求值的起始条件
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
//不懂重新看鹏哥视频p43