前言
指针和数组在许多编程场景中经常结合使用,比如通过指针来访问数组的元素、通过指针来遍历数组等。指针和数组的灵活应用可以帮助我们更好地处理和操作数据,提高程序的性能和效率,指针和数组在C语言中具有重要的地位和作用,它们是程序设计中不可或缺的重要概念。本文将详细解析指针和数组相关笔试题!!
1. 一维数组和指针相关笔试题
题目及解析:
int main() { int a[] = { 1,2,3,4 }; printf("%d\n", sizeof(a)); //数组名单独放在sizeof内部,这里a表示整个数组,计算的是整个数组,为16(4*4)个字节 printf("%d\n", sizeof(a + 0));//a表示首元素的地址,a+0还是表示首元素地址,是地址就是4/8个字节 printf("%d\n", sizeof(*a)); //a表示首元素地址,*a表示首元素,大小为4个字节 printf("%d\n", sizeof(a + 1));//a表示首元素地址,arr+1跳过一个整型长度指向第二个元素(2)的地址,是地址大小就是4/8个字节 printf("%d\n", sizeof(a[1]));//a[1]取出的是第二个元素2,为int类型,大小为4个字节 printf("%d\n", sizeof(&a)); //&a取出的是整个数组的地址,但只要是地址,大小都是4/8个字节 printf("%d\n", sizeof(*&a)); //解读一:sizeof(*&a) ---> sizeof(a) ---> 同第一个为16字节 //解读二:由于我们熟知对整型指针进行解引用得到的是整型;对字符指针进行接引用得到的是一个字符 // 这里&a表示数组指针,类型为int (*)[4],对它进行解引用操作得到的是一个数组,即*&a表示整个数组,大小为4*4即16个字节 printf("%d\n", sizeof(&a + 1)); //&a取出的是整个数组,&a+1跳过整个数组,指向的是第四个元素4的下一个元素的地址 //但是地址大小就是4/8个字节 printf("%d\n", sizeof(&a[0]));//&a[0]取出的是第一个元素1的地址,大小为4/8个字节 printf("%d\n", sizeof(&a[0] + 1));//&a[0]+1表示取出首元素地址后向后移动一个整型字长,指向第二个元素2的地址,为4/8个字节 return 0; }
x64环境下运行结果:
2. 字符数组和指针相关笔试题
2.1 题型一:
题目及解析:
int main() { char arr[] = { 'a','b','c','d','e','f' }; printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,总共6个字节 printf("%d\n", sizeof(arr + 0));//arr表示数组首元素的地址,arr+0还是数组首元素的地址,是地址就是4/8个字节 printf("%d\n", sizeof(*arr));//arr表示数组首元素的地址,*arr就是首元素,大小1个字节 printf("%d\n", sizeof(arr[1]));//arr[1]就是第二个元素,大小是1个字节 printf("%d\n", sizeof(&arr));//&arr是数组的地址,但是数组的地址也是地址,是地址就是4/8 printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过整个数组后的地址,是地址就是4/8个字节 printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是4/8个字节 return 0; }
x64环境下运行结果:
2.2 题型二:
题目及解析:
int main() { char arr[] = { 'a','b','c','d','e','f' }; printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结果就是随机值 printf("%d\n", strlen(arr + 0));//arr + 0是首元素的地址,和第一个一样,也是随机值 //printf("%d\n", strlen(*arr));//err, arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97 //strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ascii码值是97,那就是将97作为地址传参 //strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了 //printf("%d\n", strlen(arr[1]));//err printf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的 //那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计,结果为随机值 printf("%d\n", strlen(&arr + 1));//&arr+1,跳过整个数组,结果为随机值 printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,结果为随机值 return 0; }
x64环境下运行结果:
2.3 题型三:
题目及解析:
int main() { char arr[] = "abcdef";//[a b c d e f \0] printf("%d\n", sizeof(arr));//数组中共有7个元素,结果为7 printf("%d\n", sizeof(arr + 0));//arr + 0是首元素的地址,结果为4/8 printf("%d\n", sizeof(*arr));//*arr其实就是首元素,1个字节 //*arr--> *(arr+0) -- arr[0] printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,1个字节 printf("%d\n", sizeof(&arr));//&arr是数组的地址,是地址就是4/8个字节 printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过一个数组的地址,4/8 printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8 return 0; }
x64环境下运行结果:
2.4 题型四:
题目及解析:
int main() { char arr[] = "abcdef";//[a b c d e f \0] printf("%d\n", strlen(arr));//6 printf("%d\n", strlen(arr + 0));//6 //printf("%d\n", strlen(*arr));//err,传的是首元素a //printf("%d\n", strlen(arr[1]));//err,传的是第二个元素b //strlen需要传过去的是指针,如果传字符会造成非法访问内存,报错 printf("%d\n", strlen(&arr));//6 printf("%d\n", strlen(&arr + 1));//&arr+1跳过整个数组,导致数组后面\0没有明确位置,导致结果为随机值 printf("%d\n", strlen(&arr[0] + 1));//从第二个元素开始向后访问,结果为5 return 0; }
x64环境下运行结果:
3. 指针和字符串相关面试题
3.1 题型一:
题目及解析:
int main() { char* p = "abcdef"; printf("%d\n", sizeof(p));//p是一个指针变量,大小就是4/8个字节 printf("%d\n", sizeof(p + 1));//p+1是'b'的地址,是地址大小就是4/8个字节 printf("%d\n", sizeof(*p));//*p 就是'a',就是1个字节 printf("%d\n", sizeof(p[0]));//p[0]--> *(p+0) --> *p ,大小为1个字节 printf("%d\n", sizeof(&p));//&p -- char**,二级指针也是指针大小为4/8个字节 printf("%d\n", sizeof(&p + 1));//*p+1本质上还是一个指针,大小为4/8个字节 printf("%d\n", sizeof(&p[0] + 1));//4/8 , &p[0] + 1得到是'b'的地址 return 0; }
x64环境下运行结果:
3.2 题型二:
**题目及解析:
//由于原理和上面完全一样,所以在此就不再累赘了 int main() { char* p = "abcdef"; printf("%d\n", strlen(p));//6 printf("%d\n", strlen(p + 1));//5 //printf("%d\n", strlen(*p));//err //printf("%d\n", strlen(p[0]));//err printf("%d\n", strlen(&p));//随机值 printf("%d\n", strlen(&p + 1));//随机值 printf("%d\n", strlen(&p[0] + 1));//5 return 0; }
x64环境下运行结果:
4. 二位数组和指针相关面试题
**题目及解析:
int main() { int a[3][4] = { 0 }; printf("%d\n", sizeof(a));//sizeof(数组名)不管是一维数组还是二维数组都是表示整个数组,结果为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)); //a[0]作为第一行的数组名,没有单独放在sizeo内部,没有& //a[0]表示数组首元素的地址,也就是a[0][0]的地址 //所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节 // printf("%d\n", sizeof(*(a[0] + 1)));//4 //计算的是就是第一行第2个元素的大小 printf("%d\n", sizeof(a + 1));//4 / 8 //a是数组首元素的地址,是第一行的地址 int(*)[4] //a+1 就是第二行的地址 printf("%d\n", sizeof(*(a + 1)));//16 //*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小 //a+1 --> 是第二行的地址,int(*)[4] //*(a+1) 访问的第二行的数组 printf("%d\n", sizeof(&a[0] + 1));//4/8 //&a[0]是第一行的地址 int(*)[4] //&a[0]+1 是第二行的地址 int(*)[4] printf("%d\n", sizeof(*(&a[0] + 1)));//16 计算的是第二行的大小 printf("%d\n", sizeof(*a));//计算的是第一行的大小-16 //a是数组首元素的地址,就是第一行的地址 //*a 就是第一行 //*a --> *(a+0) --> a[0] printf("%d\n", sizeof(a[3]));//16 //sizeof在计算其大小时,其背后原理是sizeof操作符只关心其类型,根据类型来计算大小 //并不会真正的访问内存,所以在此所谓的数组越界对sizeof计算其大小并没有太大关系 return 0; }
x64环境下运行结果:
5. 总结
1. sizeof(数组名),这里的数组表示的是整个数组,不管是一维数组还是二维数组计算的都是整个数组的大小。
2. &数组名,这里的数组名表示的也是整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名表示的都是首元素的地址。
4. sizeof计算大小时,其工作原理是根据其类型来判断的,并不会真正访问内存来计算大小。所以在计算数组大小过程中,即使出现数组越界,但对sizeof来说没有影响,依然可以计算其大小。
6. 结尾
本篇文章到此就结束了。创作不易,如果对你有帮助记得点赞加收藏哦。感谢您的支持!!