指针和数组常见面试题

我们这篇博客主要用来写一些指针和数组的题.
问题涉及到指针和数组,我们就有些注意事项先要了解一下:
1.C语言中,数组名经常会隐式转化为指针;
指针也可以用[ ]的方式取下标,行为上类似于数组。

2.指针的大小为固定值(32位:4字节 64位;8字节),只要是指针,就是这么大,无论你是字符指针,数组指针还是二级指针.
3.sizeof()就是求字节数的.
4.strlen的类型是const char *–要注意只有匹配此数据类型才可以求解字符串长度.(注意是字符串)也就是说花括号定义的不可以!!

(花括号int的sizeof())

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    
    
int arr[] = {
    
     1, 2, 3, 4 };
	printf("%d\n", sizeof(arr)); // 16
	printf("%d\n", sizeof(arr + 0)); // 4 求 sizeof(int*)
	printf("%d\n", sizeof(*arr)); // 4, 求 sizeof(int)
	printf("%d\n", sizeof(arr + 1)); // 4, 求 sizeof(int*)
	printf("%d\n", sizeof(arr[1])); // 4, 求 sizeof(int)
	printf("%d\n", sizeof(&arr));// 4, 求 sizeof(int(*)[4]);
	printf("%d\n", sizeof(*&arr));// 16, 求 sizeof(int[4]);
	printf("%d\n", sizeof(&*arr));// 4, 求 sizeof(int*)
	printf("%d\n", sizeof(&arr + 1)); // 4, 求 sizeof(int(*)[4])
	printf("%d\n", sizeof(&arr[0])); // 4, 求 sizeof(int*)
	printf("%d\n", sizeof(&arr[0] + 1)); // 4, 求 sizeof(int*)
	system("pause");
	return 0;
}

在这里插入图片描述

1.求的是数组整体的元素所占的字节数,为int;
2.因为涉及加减,隐式转换发生,为* int;
3.* arr解引用,证明arr隐式转换,在解引用,是1,为int;
4.同2
5.arr[1]是取下标操作,就是2这数字,为int;
6.数组指针,为int(*)[4];
7. *&arr,数组指针解引用指向数组整体;求int[4];
8. & *arr;(首元素)1的地址;
9. 数组指针+1也是指针,所以是4;
10. 0号元素,也就是数字1的地址。所以也是4。
11.第二个元素,数字2的地址。

(花括号ichar的sizeof())

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    
    
char arr[] = {
    
     'a', 'b', 'c', 'd', 'e', 'f' };
	printf("%d\n", sizeof(arr)); // 6, sizeof(char[6])
	printf("%d\n", sizeof(arr + 0)); // 4, sizeof(char*)
	printf("%d\n", sizeof(*arr)); // 1, sizeof(char)
	printf("%d\n", sizeof(arr + 1)); // 4
	printf("%d\n", sizeof(arr[1]));// 1, sizeof(char)
	printf("%d\n", sizeof(&arr));// 4, sizeof(char(*)[6])
	printf("%d\n", sizeof(*&arr)); // 6, sizeof(char[6])
	printf("%d\n", sizeof(&*arr));// 4, sizeof(char*)
	printf("%d\n", sizeof(&arr[1] + 1)); // 4, sizeof(char*)
	printf("%d\n", sizeof(&arr + 1)); // 4, sizeof(char(*)[6]);

	 //此处的操作是未定义行为. arr 就不是一个 "字符串" 
	 //必须是带有 \0 的 char 数组才是字符串. 
	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));
	system("pause");
	return 0;
}

在这里插入图片描述

1.就是求元素个数(char1字节)
2.arr可以+0,证明发生了隐式转换,现在求的就是首元素地址,是个 -----指针,所以为4
3.解引用也证明了发生了隐式转换,现在就是求第一个元素的字节数
4.和2 同理,只不过是下一个元素的地址
5.正常的数组取下标,所以是1
6.数组名前取地址证明是–数组指针,也是4
7.先取地址证明是数组指针,在解引用也就是数组本身-6
8.先解引用证明发生了隐式转换,先取首元素元素再取地址,所以4
9.先简单取下标,再取地址,在+1,是‘c’的地址~
10.数组名前取地址证明是–数组指针,再加一也是数组指针,4

注意:{ }定义的数组不包含’\0’,所以这个的strlen都是未定义行为。

(字符串char的sizeof()和strlen)

char arr[] = "abcdef";
	printf("%d\n", sizeof(arr)); // 7, sizeof(char[7]);
	printf("%d\n", sizeof(arr + 0)); // 4, sizeof(char*)
	printf("%d\n", sizeof(*arr)); // 1, sizeof(char)
	printf("%d\n", sizeof(arr[1])); // 1, sizeof(char)
	printf("%d\n", sizeof(&arr[0] + 1)); // 4, sizeof(char*)
	printf("%d\n", sizeof(&arr)); // 4 sizeof(char(*)[7])
	printf("%d\n", sizeof(*&arr)); // 7 sizeof(char[7])
	printf("%d\n", sizeof(&*arr)); // 4 sizeof(char*)
	printf("%d\n", sizeof(&arr + 1)); // 4 sizeof(char(*)[7])

	printf("%d\n", strlen(arr)); // 6
	printf("%d\n", strlen(arr + 1)); // 5
	printf("%d\n", strlen(&arr + 1)); // 随机值 类型不匹配
	printf("%d\n", strlen(&arr)); // 6  类型不匹配
	printf("%d\n", strlen(&arr[0])); // 6
	printf("%d\n", strlen(*&arr)); // 6
	printf("%d\n", strlen(&*arr)); // 6
	printf("%d\n", strlen(&arr[1] + 1));//4

在这里插入图片描述

sizeof()操作:

1.字符串表示所以自带’\0’—7
2.首元素地址
3.可以解引用证明隐式转化发生,就是首元素本身
4.普通的数组取下标操作
5.先取下标,再取地址,再加1,这时是元素b的地址
6…数组名前取地址证明是–数组指针,也是4
7.数组指针解引用,还是数组本身
8.发生隐式转换,先解引用再取地址,还是首元素地址
9.数组名前取地址证明是–数组指针,再加一也是数组指针,4

strlen操作:

1.普通的求字符串长度的操作
2.arr隐式转换,+1指向第二个元素位置,所以是少一个长度
12,类型不匹配,const char * 和char( * )[7]。
6,类型不匹配,const char * 和char( * )[7]。
5.a–f
6.a–f
7.a–f
8.c–f

(指针的sizeof()和strlen)

char* p = "abcdef";

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

	printf("%d\n", strlen(p)); // 6
	printf("%d\n", strlen(p + 1)); // 5
	printf("%d\n", strlen(*p)); // 类型不匹配
	printf("%d\n", strlen(p[1])); // 类型不匹配
	printf("%d\n", strlen(&p)); // 类型不匹配. 
	printf("%d\n", strlen(&p[1] + 1)); // 4
	printf("%d\n", strlen(*&p)); // 6
	printf("%d\n", strlen(&*p)); // 6

sizeof():

1.p是指针,首元素的地址
2.第二个元素的地址
3.首元素a
4.数组取下标操作
5.二级指针
6.指向第二元素是的指针
7.首元素地址
8.首元素地址

strlen:
(注意类型不匹配的要先注释掉才可以运行下面的)

1.普通的求字符串长度的操作
2.arr隐式转换,+1指向第二个元素位置,所以是少一个长度
3.类型不匹配,const char * 和char 。
4.类型不匹配,const char * 和char 。
5.类型不匹配,const char * 和char ** 。
6.c到f 。
7.a到f 。
8.a到f。

(花括号二维数组int的sizeof())

int arr[3][4] = {
    
     0 };
	printf("%d\n", sizeof(arr)); // 48  sizeof(int[3][4])
	printf("%d\n", sizeof(arr[0])); // 16 sizeof(int[4])
	// arr[0] int[4], 再 + 1, 就把 int[4] 转成 int* 了
	printf("%d\n", sizeof(arr[0] + 1)); // 4 sizeof(int*)
	printf("%d\n", sizeof(&arr[0] + 1)); // 4 sizeof(int(*)[4])
	printf("%d\n", sizeof(arr[0][0])); // 4 sizeof(int)
	printf("%d\n", sizeof(*arr[0])); // 4, sizeof(int)
	// arr 是二维数组 int[3][4] => int(*)[4] => * => int[4]
	 printf("%d\n", sizeof(*arr)); // 16 sizeof(int[4])
	// arr + 1 => int(*)[4] => * => int[4]
	printf("%d\n", sizeof(*(arr + 1))); // 16 sizeof(int[4])
	// arr => int[3][4] => int(*)[4] => * => int[4] => +1 => int*
	printf("%d\n", sizeof(*arr + 1));
	// arr[0] => int[4] => & => int(*)[4] => +1 => int(*)[4]
	printf("%d\n", sizeof(&arr[0] + 1)); // 4 sizeof(int(*)[4])
	 //arr[0] => int[4] => +1  => int*  => * => int
	printf("%d\n", sizeof(*(arr[0] + 1)));

在这里插入图片描述

1.sizeof(int[3][4]) 。
2.sizeof(int[4])。
3.sizeof(int*),arr[0]得到int[4],再+1,就把 int[4] 转成 int* 。
4.sizeof(int( * )[4]),数组指针 。
5.sizeof(int) 。
6.sizeof(int)。
7.sizeof(int[4]),arr 是二维数组 int[3][4]转换成int( * )[4]解引用得到int[4]。
8.sizeof(int[4]),arr + 1转换成int( * )[4]解引用得到int[4]。
9.arr是int [3][4]取地址得到int( * )[4],解引用得到int[4],再+1转换成int * 。
10.sizeof(int( * )[4]),arr[0]得到int[4]取地址得到int ( * )[4],再+1转换成int( * )[4]。
11.sizeof(int),arr[0]得到int[4],+1转换成int * ,解引用得到 int。

强制转化

	int a[5] = {
    
     1, 2, 3, 4, 5 };
	int *ptr = (int *)(&a + 1);
	// *(a + 1) => a[1]
	printf("%d,%d", *(a + 1), *(ptr - 1));

在这里插入图片描述这个题稍稍复杂一点,我们来细致分析一下:
先看*(a+1):先看a+1,证明发生了隐式转换,此时指向的是第二个元素,在解引用,得到第二个数字2.

*(ptr-1)的求解:我们先分析int *ptr = (int *)(&a + 1);
(&a+1),转化为了数组指针,+1表示的是跳过一个“a[5]”大小的空间后的地址, 即:a[5]的最 后一个元素的后面 。
int *)是强制类型转换。ptr - 1得到a[5]最后一个元素的地址,对它解引用得到a[5]最后一个元素5。
在这里插入图片描述

括号表达式

// 由于后面的初始化语句都是 逗号表达式, 
	// 实际有效的值只是 1, 3, 5
	int a[3][2] = {
    
     (0, 1), (2, 3), (4, 5) };
	int *p;
	p = a[0];
	printf("%d", p[0]);

在这里插入图片描述逗号表达式的简单应用.

一个难题

	int a[4] = {
    
     1, 2, 3, 4 };
	int *ptr1 = (int *)(&a + 1);
	int *ptr2 = (int *)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);

在这里插入图片描述ptr1[-1]和第六例题中的数组指针一样.
我们主要看*ptr2:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhaocx111222333/article/details/109710265