🐒个人主页:平凡的小苏
📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情
目录
1. 指针和数组笔试题解析
数组名的意义:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址 。
一维数组
-
int a[] = {
1,
2,
3,
4};
-
printf(
"%d\n",sizeof(a));
-
//这里数组名单独放在sizeof内部,计算整个数组的大小,结果为
16
-
printf(
"%d\n",sizeof(a+
0));
-
//这里数组名没有单独放在sizeof内部,是数组首元素的地址,结果为
4/
8
-
printf(
"%d\n",sizeof(*a));
-
//这里数组首元素的地址解引用,计算的是元素大小,结果为
4
-
printf(
"%d\n",sizeof(a+
1));
-
//这里数组首元素地址加
1,也是地址,是地址结果就是
4/
8
-
printf(
"%d\n",sizeof(a[
1]));
-
//这里计算元素大小,结果为
4
-
printf(
"%d\n",sizeof(&a));
-
//取出整个数组的地址,是地址结果就为
4/
8
-
printf(
"%d\n",sizeof(*&a));
-
//取出数组的地址,然后解引用,本质是数组名单独放在sizeof内部,结果为
16
-
printf(
"%d\n",sizeof(&a+
1));
-
//地址加
1,是地址结果就为
4/
8
-
printf(
"%d\n",sizeof(&a[
0]));
-
//取出首元素的地址,是地址结果就为
4/
8
-
printf(
"%d\n",sizeof(&a[
0]+
1));
-
//结果为
4/
8
字符数组
-
char arr[] = {
'a',
'b',
'c',
'd',
'e',
'f'};
-
printf(
"%d\n", sizeof(arr));
-
//数组名单独,结果为
6,因为sizeof计算的是占用内存的大小,不用找\
0,并且看类型
-
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));
-
//取出首元素地址加
1,跳过四个字节,是地址结果为
4/
8
-
-
-
-
printf(
"%d\n", strlen(arr));
-
//strlen是遇到
'\0'停止,这个不知道什么时候遇到
'\0',所以结果为随机值
-
printf(
"%d\n", strlen(arr+
0));
-
//同上为随机值
-
printf(
"%d\n", strlen(*arr));
-
//对arr解引用拿到第一个字符,转为十进制为
97,strlen是用地址一个一个访问的,所以这个代码error
-
printf(
"%d\n", strlen(arr[
1]));
-
//同上error
-
printf(
"%d\n", strlen(&arr));
-
//随机值
-
printf(
"%d\n", strlen(&arr+
1));
-
//随机值
-
printf(
"%d\n", strlen(&arr[
0]+
1));
-
//随机值
-
char arr[] =
"abcdef";
-
//“abcdef\
0”数组长度为
7
-
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));
-
//取出数组的地址加
1,跳过数组,指向数组后边,但也是地址,是地址结果就为
4/
8
-
printf(
"%d\n", sizeof(&arr[
0]+
1));
-
//是地址结果就为
4/
8
-
-
-
printf(
"%d\n", strlen(arr));
-
//strlen遇到斜杠
0就停止,结果为
6
-
printf(
"%d\n", strlen(arr+
0));
-
//同上,结果为
6
-
printf(
"%d\n", strlen(*arr));
-
//解引用拿到的是字符a,代码错误
-
printf(
"%d\n", strlen(arr[
1]));
-
//同上,代码错误
-
printf(
"%d\n", strlen(&arr));
-
//取出数组的地址,但是数组地址开始也是指向首元素的地址,所以结果为
6
-
printf(
"%d\n", strlen(&arr+
1));
-
//取出数组的地址加
1,跳过整个数组,然后不知道什么时候遇到斜杠
0,所以为随机值
-
printf(
"%d\n", strlen(&arr[
0]+
1));
-
//取出数组首元素地址加
1,跳过一个字节,结果为
5
-
char *p =
"abcdef";
-
printf(
"%d\n", sizeof(p));
-
//该指针变量存放的是该字符串首字符的地址,是地址结果就为
4/
8
-
printf(
"%d\n", sizeof(p+
1));
-
//是地址结果就为
4/
8
-
printf(
"%d\n", sizeof(*p));
-
//对指针p解引用,计算的是该字符元素的大小,结果为
1
-
printf(
"%d\n", sizeof(p[
0]));
-
//同上,结果为
1
-
printf(
"%d\n", sizeof(&p));
-
//是地址,结果就为
4/
8
-
printf(
"%d\n", sizeof(&p+
1));
-
//是地址,结果就为
4/
8
-
printf(
"%d\n", sizeof(&p[
0]+
1));
-
同上,结果为
4/
8;
-
-
printf(
"%d\n", strlen(p));
-
//strlen遇到
'\0'就停止,结果为
6
-
printf(
"%d\n", strlen(p+
1));
-
//p+
1跳过一个字节,结果为
5
-
printf(
"%d\n", strlen(*p));
-
//拿到的是字符a,转为ascii吗为
97,该代码错误
-
printf(
"%d\n", strlen(p[
0]));
-
//同上,该代码错误
-
printf(
"%d\n", strlen(&p));
-
//取p的地址,不知道什么时候遇到斜杠
0,所以为随机值
-
printf(
"%d\n", strlen(&p+
1));
-
同上,结果为随机值
-
printf(
"%d\n", strlen(&p[
0]+
1));
-
取首字符的地址+
1跳过一个字节,计算的结果为
5
二维数组
-
int a[
3][
4] =
{0};
-
printf(
"%d\n",sizeof(a));
-
//结果为
48,
3*
4*
4=
48
-
printf(
"%d\n",sizeof(a[
0][
0]));
-
//计算元素的大小结果为
4
-
printf(
"%d\n",sizeof(a[
0]));
-
//a[
0]是第一行一维数组的数组名,数组名单独放在sizeof内部,计算的是第一行数组的大小,结果为
16
-
printf(
"%d\n",sizeof(a[
0]+
1));
-
//没有单独放在sizeof内部,是数组的首元素,+
1跳过四个字节,指向第一行第二列的地址,是地址就为
4/
8
-
printf(
"%d\n",sizeof(*(a[
0]+
1)));
-
//计算的是元素的大小结果为
4
-
printf(
"%d\n",sizeof(a+
1));
-
//a没有单独放在sizeof内部,是首元素的地址,是第一行的地址,+
1指向第二行的地址,是地址就为
4/
8
-
printf(
"%d\n",sizeof(*(a+
1)));
-
a没有单独放在sizeof内部,是首元素的地址,是第一行的地址,+
1指向第二行的地址,进行解引用得到第二行的数组名,计算的是第二行数组的大小结果为
16
-
printf(
"%d\n",sizeof(&a[
0]+
1));
-
取出第一行的地址,再+
1指向第二行的地址,是地址就为
4/
8
-
printf(
"%d\n",sizeof(*(&a[
0]+
1)));
-
取出第一行的地址,再+
1指向第二行的地址,再进行解引用,得到第二行的数组名,计算的是第二行数组的大小,结果为
16
-
printf(
"%d\n",sizeof(*a));
-
a是二维数组的数组名,没有单独放sizeof内部,是一维数组第一行的地址,然后进行解引用,得到第一行的数组名,计算的是第一行数组的大小,结果为
16
-
printf(
"%d\n",sizeof(a[
3]));
-
//第四行的数组名,虽然越界了但是知道了列,就知道一行有多少个元素,因为sizeof是看类型计算的大小,sizeof再编译阶段就完成了计算,越界不影响,所以结果为
16
2. 指针笔试题
笔试题1:
-
int main()
-
{
-
int a[
5] = {
1,
2,
3,
4,
5 };
-
int *ptr = (
int *)(&a +
1);
-
printf(
"%d,%d", *(a +
1), *(ptr -
1));
-
return
0;
-
}
-
//程序的结果是什么?
-
2
5
-
解释:
1.a是数组名,为数组首元素的地址,加
1跳过
4个字节,在进行解引用就得到了
2
-
2.取出数组的地址再进行+
1,跳过整个数组,因为取出数组的地址是数组指针类型,想要放在ptr里面,就需要强制类型转换。ptr-
1往回跳一个字节再进行解引用得到的结果为
5.
笔试题2:
-
//由于还没学习结构体,这里告知结构体的大小是20个字节
-
struct
Test
-
{
-
int Num;
-
char *pcName;
-
short sDate;
-
char cha[
2];
-
short sBa[
4];
-
}*p;
-
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
-
//已知,结构体Test类型的变量大小是20个字节
-
int main()
-
{
-
printf(
"%p\n", p +
0x1);
-
printf(
"%p\n", (
unsigned
long)p +
0x1);
-
printf(
"%p\n", (
unsigned
int*)p +
0x1);
-
return
0;
-
}
-
结果为:
00100014,
00100001,
00100004
-
解释:
1.因为结构体的大小为
20个字节,指针p+
1跳过
20个字节所以结果为
00100014
-
2.先将p强制类型转换为无符号整型,整型+
1就跳过一个字节,所以地址为
00100001
-
3.将p强制类型转换为无符号整型指针,无符号整型指针+
1就跳过四个字节,所以地址为
00100004
笔试题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);
-
return
0;
-
}
-
结果为:
4,
2000000
解释如图所示:
笔试题4
-
#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;
-
}
-
结果为:
1
-
解释:因为该数组里面的括号为逗号表达式,所以数组的元素为
1
3
5
0
0
0
-
p[
0]访问的是a[
0][
0]所以打印出来的是
1
笔试题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]);
-
return
0;
-
}
-
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;
-
}
解释:&p[4][2]-&a[4][2]两个指针相减得到的是-4,又因为-4放入内存是补码
则-4的补码为:11111111111111111111111111111100,所以它的地址为fffffc。用%p打印出来就是fffffc
而用%d打印就是-4.
笔试题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));
-
return
0;
-
}
-
结果为:
10
5
-
解释:
1.取出二维数组的地址+
1,跳过整个二维数组,强制类型转换为
int*,放入ptr1,然后ptr-
1再进行解引用得到的就是
10
-
2.aa是数组名,是一维数组的数组名,是第一行数组的地址,aa+
1跳过一行得到第二行的地址解引用,强制类型转换为
int*放入ptr2,ptr2-
1再进行解引用打印出来的就是
5
笔试题7
-
#include <stdio.h>
-
int main()
-
{
-
char *a[] = {
"work",
"at",
"alibaba"};
-
char**pa = a;
-
pa++;
-
printf(
"%s\n", *pa);
-
return
0;
-
}
-
结果为:at
-
解释:a数组每个元素的类型为
char*,所以需要二级指针来接收数组a的地址,然后pa++,跳过一个字节,所以pa指向了a首字符的地址,再对pa进行解引用找到了字符a利用%s打印出来就是at
笔试题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);
-
printf(
"%s\n", *--*++cpp+
3);
-
printf(
"%s\n", *cpp[-
2]+
3);
-
printf(
"%s\n", cpp[-
1][-
1]+
1);
-
return
0;
-
}
-
结果为:POINT ,ER, ST, EW
解释:cpp存放的是cp首元素的地址,cp 存放的是c的地址
1.由操作符优先级可知,先进行++cpp,所以cpp指向了c+2,然后对cpp第一次解引用得到了c+2的地址,再进行解引用找到了POINT首字符的地址,所以打印出来的是POINT
2.由于cpp已经指向了c+2,所在进行++cpp,就又指向了c+1,对他进行解引用找到了c+1的地址再进行--,所以c+1变为了(c+1-1)得到c,再进行解引用找到了ENTER首字符的地址,再进行+3,跳过三个字节,所以打印出来的是ER
3.由于cpp已经指向了c+1,而那个c+1地址又已经变为了c的地址,所以cpp[-2]本质为*(cpp-2)找到了c+3的地址再进行解引用得到了FIRST首字符的地址,再进行+3跳过了三个字节,所以打印出来的是ST
4.由于cpp已经指向了c+1,而那个c+1地址又已经变为了c的地址,所以cpp[-1][-1]本质为
*(*(cpp-1)-1)找到了NEW首字符的地址,再进行+1跳过一个字节,所以打印出EW
小编的分享到这里就结束了!如果有什么不足的地方,请大佬们指点,小编一定吸取教训,将文章质量提高!!!
转载:https://blog.csdn.net/VHhhbb/article/details/128643210