指针和数组的笔试题

目录

笔试题一:

笔试题二:

笔试题三:

笔试题四

笔试题五

笔试题六 

笔试题七:

笔试题八:

笔试题九 

笔试题十 

笔试题一:

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	int* p = a;
	int (*pa)[4] = &a;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	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));
}

温馨提示: 

1. sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小,单位是字节
2. &数组名 - 数组名也表示整个数组,取出的是整个数组的地址除了这个2个例外,所有的数组名都表示首元素的地址 

解析 

int main()
{
   int a[] = { 1,2,3,4 };
    int* p = a;
    int (*pa)[4] = &a;
    printf("%d\n", sizeof(a));//16,a作为数组名单独放在sizeof内部,计算的是数组的总大小, 单位是字节
    printf("%d\n", sizeof(a + 0));//a并非单独放在sizeof内部,也没有&,所以数组名a就是数组首元素的地址,a+0还是数组首元素的地址,是地址大小就是 4/8 个字节(32位机器位4,64位机器为8
printf("%d\n", sizeof(*a));//a是首元素的地址,*a就是首元素,sizeof(*a)就算的就是首元素的大小 - 4
printf("%d\n", sizeof(a + 1));//a是首元素的地址,a+1跳过一个整型,是第二个元素的地址,sizeof(a+1)计算的是指针的大小 - 4/8
printf("%d\n", sizeof(a[1]));//a[1]就是数组的第二个元素,sizeof(a[1])的大小 - 4个字节
printf("%d\n", sizeof(&a));//&a取出的数组的地址,数组的地址,也是地址,sizeof(&a)就是 4/8 个字节
printf("%d\n", sizeof(*&a));//&a是数组的地址,是数组指针类型,*&a是都数组指针解引用,访问一个数组的大小,相当于sizeof(*&a) ==> sizeof(a)  =16
 printf("%d\n", sizeof(&a + 1));//&a数组的地址,&a+1跳过整个数组,&a+1还是地址,是 4/8 个字节
printf("%d\n", sizeof(&a[0]));//a[0]是数组的第一个元素,&a[0]是第一个元素的地址,是 4/8 个字节
printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一个元素的地址,&a[0]+1就是第二个元素的地址,是 4/8 个字节
return 0;
}

笔试题二:

#include <string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
    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));
    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));
	return 0;
}

 温馨提示:

sizeof 是计算对象或者类型创建的对象所占内存空间的大小,单位是字节,strlen 求字符串长度的,计算的是字符串中\0之前出现的字符的个数,如果没有找到‘\0’,会继续往后找。sizeof是操作符,而strlen是库函数,需要加头文件。

解析:

#include <string.h>
int main()
{
    char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", strlen(arr));//随机值,arr是数组名,但是没有放在sizeof内部,也没&,arr就是首元素的地址
    //strlen得到arr后,从arr数组首元素的地方开始计算字符串的长度,直到直到\0,但是arr数组中没有\0,arr内存的后边是否有\0,在什么位置是不确定的,所以\0之前出现了多少个字符是随机的。
    printf("%d\n", strlen(arr + 0));//arr是数组首元素的地址,arr+0还是首元素的地址,随机值
    printf("%d\n", strlen(*arr));//arr是数组首元素的地址,*arr 是首元素 - ‘a’ - 97
    //strlen就把‘a’的ASCII码值 97 当成了地址,会非法访问内存
    printf("%d\n", strlen(arr[1]));//arr[1] - 'b' - 98 - err
    printf("%d\n", strlen(&arr));//随机值,&arr是数组的地址,数组的地址也是指向数组起始位置,和第一个案例一样
    printf("%d\n", strlen(&arr + 1));//随机值
    printf("%d\n", strlen(&arr[0] + 1));//随机值
    printf("%d\n", sizeof(arr));//arr是数组名,并且是单独放在sizeof内部,计算的是数组总大小,单位是字节 - 6
    printf("%d\n", sizeof(arr + 0));//arr是数组名,并非单独放在sizeof内部,arr表示首元素的地址,arr+0还是首元素的地址
    //是地址大小就是4/8
    printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,sizeof计算的是首元素的大小,是1字节
    printf("%d\n", sizeof(arr[1]));//arr[1]是数组的第二个元素,sizeof(arr[1])计算的是第二个元素的大小,1个字节
    printf("%d\n", sizeof(&arr));//&arr- 取出的是数组的地址,sizeof(&arr))计算的是数组的地址的大小,是地址就是4/8字节
    printf("%d\n", sizeof(&arr + 1));//&arr是数组的地址,&arr+1跳过整个数组,指向'f'的后边,&arr+1的本质还是地址,是地址就是4/8字节
    printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,是地址就是4/8字节
    return 0;

笔试题三:

#include <string.h>
//
//int main()
//{
//	char arr[] = "abcdef";
//
//	//char ch = 'w';
//	//int* pc = &ch;//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));
//
//	//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));
//
//	return 0;
//}

和上面的题很相似,不同的是这一串字符由花括号变成了双引号,有了双引号,字符串后面就有了‘\0’. 

#include <string.h>

int main()
{
    char arr[] = "abcdef";

    char ch = 'w';
    int* pc = &ch;//char*

    printf("%d\n", strlen(arr));//arr表示首元素地址,后面有‘\0’,所以为‘\0’之前字符串的长度,为6
    printf("%d\n", strlen(arr + 0));同上
    printf("%d\n", strlen(*arr));同上题,发生错误,内存无法访问
    printf("%d\n", strlen(arr[1]));同上题,无法访问
    printf("%d\n", strlen(&arr));整个数组的地址,起始地址也为首元素地址,6
    printf("%d\n", strlen(&arr + 1));跳过整个数组,‘\0’在哪里未知,随机值
    printf("%d\n", strlen(&arr[0] + 1));&arr[0] + 1),b的地址,所以大小为5

    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));

//sizeof同上题

    return 0;
}
}

笔试题四

#include<stdio.h>
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]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
}

int main()
{
    //二维数组
    int a[3][4] = { 0 };
    printf("%d\n", sizeof(a));//a是二维数组的数组名,数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节,48
    printf("%d\n", sizeof(a[0][0]));//a[0][0]是一个整型元素,大小是4个字节
    printf("%d\n", sizeof(a[0]));//把二维数组的每一行看做一维数组的时候,a[0]是第一行的数组名,第一行的数组名单独放在sizeof内部
    //计算的是第一行的总大小,单位是字节 - 16

    printf("%d\n", sizeof(a[0] + 1));//a[0]虽然是第一行的数组名,但是并非单独放在sizeof内部
    //a[0]作为第一行的数组名并非表示整个第一行这个数组,a[0]就是第一行首元素的地址,a[0]--> &a[0][0] - int*
    //a[0]+1,跳过一个int,是a[0][1]的地址  4/8字节

    printf("%d\n", sizeof(*(a[0] + 1)));//a[0]+1是第一行第二个元素的地址,所以*(a[0]+1)就是a[0][1],大小是4个字节
    
    printf("%d\n", sizeof(a + 1));//a是二维数组的数组名,没单独放在sizeof内部,也没有&,所以a就是数组首元素的地址
    //二维数组,我们把它想象成一维数组,它的第一个元素就是二维数组的第一行
    //a就是第一行的地址,a+1 是第二行的地址,是地址,大小就是 4/8 个字节
    //a - &a[0]
    //a+1 - &a[1]
    //a+2 - &a[2]

    printf("%d\n", sizeof(*(a + 1)));//a+1是第二行的地址,*(a+1) 找到的就是第二行,sizeof(*(a + 1))计算的就是第二行的大小
    //16
    //*(a+1) --> a[1]
    //sizeof(*(a + 1)) --> sizeof(a[1])

    printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0]+1就是第二行的地址,sizeof(&a[0] + 1)计算的第二行地址大小
    //单位是字节 - 4/8
    printf("%d\n", sizeof(*(&a[0] + 1)));//&a[0] + 1是第二行的地址,*(&a[0] + 1)拿到的就是第二行,大小就是16个字节
    //*(&a[0]+1) --> a[1]

    printf("%d\n", sizeof(*a));//a表示首元素的地址,就是第一行的地址 - &a[0]
    //*a - 拿到的就是第一行 - 大小就是16个字节
    //*a -> *(a+0) -> a[0]

    printf("%d\n", sizeof(a[3]));//代码没问题
    //a[3]是二维数组的第4行,虽然没有第四行,但是类型能够确定,大小就是确定的。大小就是一行的大小,单位是字节 - 16
    //能够分析出 a[3]的类型是:int [4] 
    //任何一个表达式有2个属性
    //3+5
    //值属性:8
    //类型属性:int

    return 0;
}

笔试题五

int main()
{
  int a[5] = { 1, 2, 3, 4, 5 };
  int *ptr = (int *)(&a + 1);
  printf( "%d,%d", *(a + 1), *(ptr - 1));
  return 0;
}
//程序的结果是什么?

分析:&a取整个数组的地址,+1后跳过整个数组,a是首元素地址,+1跳过一个int ,所以结果为2,5. 

笔试题六 

#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;
}

分析:此二维数组初始化内容是逗号表达式,实质上为int a[3][2]={1,3,5};  a[0]是第一行的地址,怕p[0]也就是a[0][0] ,结果为1

笔试题七:

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;
}

分析:p是数组指针,指向有四个元素的一维数组 ,a是第一行的地址,类型为int(*)[5],把a给p ,p的类型为int(*)[4],类型虽然不同,但是强制转换的话p说了算

地址-地址,得到的答案是中间元素的个数,答案为-4,%p求-4的地址 

 内存为16进制,二进制转换为16进制至少需要四位二进制,所以地址为FF FF FF FC

笔试题八:

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;
}

分析:&aa取整个二维数组的地址,+1跳过整个二维数组,aa数组名首元素地址,在二维数组中就是第一行的地址,+1跳过第一行,指向第二行第一个元素,*(ptr1-1)相当于aa[1][5],*(ptr2-1)相当于aa[0][5]

笔试题九 

#include <stdio.h>
int main()
{
char *a[] = {"work","at","alibaba"};
char**pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}

笔试题十 

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;
}

%x是以16进制打印出来

 假设首地址为0x00000015,这是16进制,强制类型转换成十进制就是21 ,加一22,再强制类型转换为int*,十六进制为16,一个地址一个字节,那就是只跳过一个字节,,再画一个更准确的图,假设是小端存储(关于大小端可以看之前的博客)

 

答案为4,2000000

 

  • 15
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值