详解C语言-指针和数组笔试题解析,让你对指针了解的更加深刻

指针的解引用指针的概念你真的有自己的理解了吗,你真的懂了吗,这节带来的是
讲解5题指针笔试题初阶版,将会进行分析和画图讲解。如果想指针验证评估自己的指针地基是否牢固以及有兴趣的初学者,可以尝试挑战。

前言:
知识点1:
sizeof单独放【数组名】这里的数组名表示整个数组,计算的是整个数组的大小。sizeof(arr);
sizeof()单独放【&数组名】这里的数组名表示整个数组,取出的是整个数组的地址。sizeof(arr);
除此之外所有的数组名都表示首元素地址

int main() {
	char a[3] = "ha";
	printf("%d\n", sizeof(a + 0));//4//打印的是首元素地址的大小
	printf("%d\n", sizeof(a));//3//打印的是整个数组的大小
	return 0;
}

知识点2
sizeof()不会去访问括号里你内容,以及计算括号里的内容,它只会根据括号里的数据类型推断出结果,属于类型属性;

类型属性:
int main() {
	short arr = 4;
	int t = 6;
	printf("%d\n,", sizeof(arr = 2 + t));//2
	printf("%d\n", arr);//4
	return 0;
}
值属性:
int main() {
	int a = 4;
	int b = 6;
	a = a + b;
	printf("%d\n", a);//10
	return 0;
}

目录

  • 1、整型数组
    • 例题
    • 答案+解析
  • 2、字符数组
    • 例题
    • 答案+解析
  • 3、字符串数组
    • 例题
    • 答案+解析
  • 4、指针存字符串
    • 例题
    • 答案+解析
  • 5、二维数组(重难点)
    • 例题
    • 答案+解析
      • ✨二维数组经典对比

1、整型数组

例题

int main() {
	int a[] = { 1,2,3,4 };

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));

	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
	return 0;
}

答案+解析

int main() {
	int a[] = { 1,2,3,4 };

	printf("%d\n", sizeof(a));//16  这里单独放数组名,表示计算整个数组大小
	printf("%d\n", sizeof(*a));//4  这里没有单独放数组名,表示首元素地址解引用,计算1的大小
	printf("%d\n", sizeof(a + 0));//4/8  这里没有单独放数组名,表示计算首元素地址大小
	printf("%d\n", sizeof(a + 1));//4/8  这里没有单独放数组名,第二个元素地址大小
	printf("%d\n", sizeof(a[1]));//4//  计算第二个元素类型大小

	printf("%d\n", sizeof(&a));//4/8  根据前言,取出的是整个数组地址
	printf("%d\n", sizeof(*&a));//16  先取出整个数组地址,再解引用=数组a
									⭐注意:&数组名,不管有没有单独放在sizeof都是取数组地址
	printf("%d\n", sizeof(&a + 1));//4/8  是数组后面的空间的地址(也是个地址)
									⭐注意:sizeof(类型属性)是不会去计算以及访问括号里的内容
	printf("%d\n", sizeof(&a[0]));//4/8  根据优先级,先算a[0]=1,再取地址,取出1的地址,计算大小
	printf("%d\n", sizeof(&a[0] + 1));//4/8  &a[0]是1的地址,+1是第二个元素的地址
	return 0;
}
地址大小取决于编译器是32位还是64位;32=464=8

2、字符数组

例题

int main() {

	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

答案+解析

int main() {

	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));//6  单独放,表示计算整个数组的地址(字符数组没有\0)
	printf("%d\n", sizeof(arr + 0));//4/8  没有单独放,arr代表首元素地址
	printf("%d\n", sizeof(*arr));//1  没有单独放,代表首元素地址解引用计算a大小
	printf("%d\n", sizeof(arr[1]));//1  计算b大小
	printf("%d\n", sizeof(&arr));//4/8  &数组名代表取出整个数组的大小,地位再牛逼也是地址
	printf("%d\n", sizeof(&arr + 1));//4/8	数组地址+1跳过整个数组,计算数组外的地址
										⭐注意:sizeof(类型属性)是不会去计算以及访问括号里的内容
	printf("%d\n", sizeof(&arr[0] + 1));//4/8	取arr[0]首元素地址+1,计算第二个元素地址

	printf("%d\n", strlen(arr));//随机值  以数组大小为单位访问没有\0,停下来取决于后面什么时候访问到\0
	printf("%d\n", strlen(arr + 0));//随机值		以元素大小为单位,停下来取决于后面什么时候访问到\0
	printf("%d\n", strlen(*arr));//报错 错误,不是地址,把a(Ascii=97)传过去,在经过进制转化成97,
	企图将97当成地址
	printf("%d\n", strlen(arr[1]));//错误	同上个题,'b'不是地址
							⭐注意:在模拟strlen时,我们传的是指针(地址)
	printf("%d\n", strlen(&arr));//随机值	整个数组地址,+1跳过整个数组大小,遇到\0才会停
	printf("%d\n", strlen(&arr + 1));//随机值	数组地址+1,跳过数组,以数组后的地址开始找\0
	printf("%d\n", strlen(&arr[0] + 1));//随机值		&arr[0]第一个元素地址,+1第二个元素地址开始找\0
	return 0;
}

3、字符串数组

例题

int main() {

	char arr[] = "abcdef";

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));


	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

	return 0;
}

答案+解析

int main() {

	char arr[] = "abcdef";

	printf("%d\n", sizeof(arr));//7		计算数组大小,有\0
	printf("%d\n", sizeof(arr + 0));//4/8	数组名没有单独,arr=首元素地址
	printf("%d\n", sizeof(*arr));//1	数组名没有单独,arr=首元素地址,解引用='a'
	printf("%d\n", sizeof(arr[1]));//1	计算b类型大小
	printf("%d\n", sizeof(&arr));//4/8	 数组地址
	⭐知识:取出的地址类型应该是char(*)[7]
		printf("%d\n", sizeof(&arr + 1));//4/8	  数组地址+1跳过整个数组,计算数组地址后的地址大小
	printf("%d\n", sizeof(&arr[0] + 1));//4/8	&arr[0]第一个元素地址,+1计算第二个元素地址大小


	printf("%d\n", strlen(arr));//6		单独放,计算整个数组长度
	printf("%d\n", strlen(arr + 0));//6		不单独放,代表首元素地址,于是从首元素地址开始找\0
	printf("%d\n", strlen(*arr));//错误		arr代表首元素地址,解引用找到具体值'a'字符,
	传输过程转化成ASCii(97),97不能当地址
		⭐注意:在模拟strlen时,我们传的是指针(地址)
		printf("%d\n", strlen(arr[1]));//错误	同上,找到'b'字符,不是地址
	printf("%d\n", strlen(&arr));//6   数组地址和首元素地址一样,
	strlen接收从数组地址开始数以char* 大小开始数
		⭐知识回忆:我们知道,模拟strlen传参,形参的创建不会创建一模一样大小,很浪费空间,于是传'a'的地址,地址 + 1,跳过4个字节,到下个'b'地址
		所以根本不会跳过整个数组大小,跳多少字节形参决定了
		printf("%d\n", strlen(&arr + 1));//随机		不同与上一题,在传之前已经跳到了整个数组后面的地址,找到\0才会停止
	printf("%d\n", strlen(&arr[0] + 1));//5		&arr[0]得到'a'地址,+1得到'b'地址;开始找\0;

	return 0;
}

4、指针存字符串

例题

int main() {

	char* p = "abcdef";

	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));

	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1));
	printf("%d\n", strlen(*p));

	return 0;
}

答案+解析

int main() {

	char* p = "abcdef";

	printf("%d\n", sizeof(p));//4/8		计算的是指针变量p的大小,类型4\8个字节
	printf("%d\n", sizeof(p + 1));//4/8		'a'地址+1,计算'b'地址大小
	printf("%d\n", sizeof(*p));//1		a地址解引用找到'a',计算字符a大小
	printf("%d\n", sizeof(p[0]));//1	计算'a'大小
	printf("%d\n", sizeof(&p));//4/8	整个数组
	printf("%d\n", sizeof(&p + 1));//4/8	首地址+1,计算'b'地址大小
	printf("%d\n", sizeof(&p[0] + 1));//4/8		首元素&地址,+1计算'b'大小

	printf("%d\n", strlen(p));//6	传地址p,p存放'a'的地址
									⭐注意:&p取的才是存放p变量的地址
	printf("%d\n", strlen(p + 1));//5	'a'地址+1,从'b'开始找\0
	printf("%d\n", strlen(*p));//arr	p存'a'的地址,解引用找到'a',企图把97当成地址

	return 0;
}

5、二维数组(重难点)

例题

int main() {

	int a[3][4] = { 0 };

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0])));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));

	
	return 0;
}

答案+解析

int main() {

	int a[3][4] = { 0 };

	printf("%d\n", sizeof(a));//48		没什么好说
	printf("%d\n", sizeof(a[0][0]));//4		第一行第一个元素大小
	printf("%d\n", sizeof(a[0]));//16	这里的arr[0]=数组名(一维数组数组名),单独放,
																计算一维数组大小=16
										或者这么理解⭐:如下图
	printf("%d\n", sizeof(a[0] + 1));//4/8	一维数组数组名没有单独放,表示一维数组首元素地址,+1
																		一维数组第二个元素地址
	printf("%d\n", sizeof(*(a[0] + 1)));//4		*(第一行第2个元素地址)
	printf("%d\n", sizeof(a + 1));//4/8		没有但单独放,代表首元素第一行一维数组地址,+1第二行地址
	printf("%d\n", sizeof(*(a + 1)));//16    a没有单独放,+1第二行整个数组地址,解引=arr[2]数组名
	printf("%d\n", sizeof(&a[0] + 1));//4/8		a[0]首元素地址,&一维数组名地址,+1第二个数组名地址
	printf("%d\n", sizeof(*(&a[0])));//16	⭐:a[0]是一维数组数组名,没单独放,是一维数组第一个元素arr[0][0]的地址,取地址取出一维数组数组名的地址,解引用得到一维数组数组名
	printf("%d\n", sizeof(*(&a[0] + 1)));//16		二维数组名地址解引用得到二维数组名,计算数组大小
	printf("%d\n", sizeof(*a));//16		没有单独放,代表二维数组的-第一个元素地址【一维数组地址】,解引用得到一维数组的数组名
	printf("%d\n", sizeof(a[3]));//16  sizeof()属于类型属性,它不会去访问这个地址,只会根据你给的类型推断出结果

	return 0;
}

详解C语言-指针和数组笔试题解析,让你对指针了解的更加深刻_第1张图片

✨二维数组经典对比

int main() {

	经典:
	int a[3][4] = { 0 };

	printf("%d\n", sizeof(a[0]));//16
	printf("%d\n", sizeof(*a));//16
	printf("%d\n", sizeof(*(&a[0])));//16

}

你可能感兴趣的:(经验分享,c语言)