【c语言】指针和数组笔试题

简介: 【c语言】指针和数组笔试题

1.指针和数组笔试题解析

一维数组

int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));//a单独放在sizeof内表示求整个数组的字节-----16
  printf("%d\n", sizeof(a + 0));//a不是单独放在sizeof内部,表明是首元素的地址,地址占4/8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*a));//a为首元素的地址,*a就是数组第一个元素,大小为4个字节
  printf("%d\n", sizeof(a + 1));//a不是单独放在sizeof内,a表示首元素地址,+1为第二个元素地址,地址占4/8个字节,32位机器占4个字节
  printf("%d\n", sizeof(a[1]));//a[1]为第二个元素,大小为int 4个字节
  printf("%d\n", sizeof(&a));//&a表示整个数组的地址,是地址就占4/8个字节,32位机器占四个字节
  printf("%d\n", sizeof(*&a));//取地址解引用相当于sizeof(a),a单独放在sizeof内表示求整个数组的字节-----16
  printf("%d\n", sizeof(&a + 1));//&a为取出整个数组的地址,+1,直接跳过整个数组,指向数组的尾,但是还是地址,地址就占4/8个字节
  printf("%d\n", sizeof(&a[0]));//&a[0]为第一个元素地址,地址占4/8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&a[0] + 1));//&a[0]为第一个元素地址,+1为第二个元素地址,地址占4/8个字节。

字符数组

char arr[] = { 'a','b','c','d','e','f' }; 
  printf("%d\n", sizeof(arr));//arr单独放在sizeof内表示求整个数组的字节-----6
  printf("%d\n", sizeof(arr + 0));//arr不是单独放在sizeof内部,+0相当于第一个元素的地址,地址占4/8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*arr));//arr不是单独放在sizeof内部,arr为首地址,解引用拿到第一个元素,占一个字节
  printf("%d\n", sizeof(arr[1]));//第二个元素,占一个字节
  printf("%d\n", sizeof(&arr));//整个数组的地址,地址占4/8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&arr + 1)); //&arr为取出整个数组的地址, + 1,直接跳过整个数组,指向数组的尾,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]第一个元素的地址,+1为第二个元素地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", strlen(arr));//从arr地址开始找'\0',--------随机数(字符数组没带反斜杠0)
  printf("%d\n", strlen(arr + 0));//arr+0为第一个元素地址开始找'\0'-------随机数(字符数组没带反斜杠0)
  printf("%d\n", strlen(*arr));//arr为首元素地址,对其解引用拿到的是第一个元素,strlen把他当做地址往后找'\0'-------奔溃
  printf("%d\n", strlen(arr[1]));//arr[1]为第二个元素,strlen把他当做地址往后找'\0'-------奔溃
  printf("%d\n", strlen(&arr));//&arr为整个数组的地址,strlen把他当做地址往后找'\0'-------随机数
  printf("%d\n", strlen(&arr + 1)); //&arr为整个数组的地址,+1跳过数组,跳到这个地址往后找'\0'-------随机数
  printf("%d\n", strlen(&arr[0] + 1));//&arr[0]为第一个元素地址,然后+1就是第2个元素的地址开始找'\0'--------随机数(字符数组没带反斜杠0)

字符串数组

char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));//arr单独放在sizeof内表示求整个数组的字节-----7(字符串数组末尾有个反斜杠0)
  printf("%d\n", sizeof(arr + 0));//arr没单独放在内部,+0,表示第一个元素地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*arr));//arr没单独放在内部,arr为元素首地址,*arr拿到第一个元素,1个字节
  printf("%d\n", sizeof(arr[1]));//arr[1]为第二个元素,为1个字节
  printf("%d\n", sizeof(&arr));//&arr为整个数组的地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&arr + 1));//&arr为整个数组的地址,+1跳过这个数组,的地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]为第一个元素地址,+1为第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", strlen(arr));//arr为首元素地址,从arr地址往后开始找'\0'-------6
  printf("%d\n", strlen(arr + 0));//arr+0为首元素地址,从arr地址往后开始找'\0'-------6
  printf("%d\n", strlen(*arr));//arr为首元素地址,解引用为第一个元素,把第一个元素当地址往后找反斜杠0------奔溃
  printf("%d\n", strlen(arr[1]));//arr[1]为第二个元素,把第二个元素当地址往后找反斜杠0------奔溃
  printf("%d\n", strlen(&arr));//&arr为整个数组的地址,strlen把他当做地址往后找'\0'-------6
  printf("%d\n", strlen(&arr + 1));//&arr为整个数组的地址, + 1跳过数组,跳到这个地址往后找'\0'------ - 随机数
  printf("%d\n", strlen(&arr[0] + 1));//&arr[0]为第一个元素地址,然后 + 1就是第2个元素的地址开始找'\0'------5

指针保存字符串数组首地址

char* p = "abcdef";
  printf("%d\n", sizeof(p));//p保存的是字符串首元素的地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(p + 1)); //p保存的是字符串首元素的地址,+1为第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*p)); //p保存的是字符串首元素的地址,对他解引用得到的是第一个元素,占一个字节
  printf("%d\n", sizeof(p[0]));//p[0]相当于*(p+0),第一个元素占一个字节
  printf("%d\n", sizeof(&p)); //p指针的地址,但是还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&p + 1)); //p指针的地址+1,还是地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(&p[0] + 1));//p[0]相当于第一个元素,&p[0]相当于第一个元素地址,&p[0] + 1为第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", strlen(p));//p保存的是字符串首元素的地址,从首元素地址开始往后找反斜杠0--------6
  printf("%d\n", strlen(p + 1));//p保存的是字符串首元素的地址,+1为第二个元素地址开始往后找反斜杠0--------5
  printf("%d\n", strlen(*p));//p保存的是字符串首元素的地址,解引用为第一个元素,strlen把他当地址开始往后找反斜杠0------奔溃
  printf("%d\n", strlen(p[0]));//p[0]为首元素,将a的ascll码值当地址开始往后找反斜杠0------奔溃
  printf("%d\n", strlen(&p));//p指针的地址,开始往后找反斜杠0-----随机值
  printf("%d\n", strlen(&p + 1)); //p指针的地址+1,开始往后找反斜杠0-----随机值
  printf("%d\n", strlen(&p[0] + 1));//p[0]相当于第一个元素,&p[0]相当于第一个元素地址,&p[0] + 1为第二个元素地址开始往后找反斜杠0-------5

二维数组

int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));//a单独放在sizeof内表示求整个数组的字节------3*4*4=48
  printf("%d\n", sizeof(a[0][0]));//第一个元素,大小为4个字节
  printf("%d\n", sizeof(a[0]));//a[0]相当于数组名---*(a+0)---*a,如果是一维数组a表示首元素的地址,二维数组a表示第一行数组的地址,相当于把第一行整个数组放在sizeof内部,*a表示第一行元素,4*4=16;
  printf("%d\n", sizeof(a[0] + 1));//a[0]相当于数组名,但是没有单独放在sizeof内部,相当于第一行第一个元素地址,+1为第一行第二个元素地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*(a[0] + 1)));//上一个说(a[0] + 1)这个是第二个元素的地址,对其解引用得到的是第二个元素,为4个字节
  printf("%d\n", sizeof(a + 1));//a没有单独放在sizeof内,表示第一行的地址,+1表示第二行的地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*(a + 1)));//上一个说a + 1为第二行的地址,对其解引用得到第二行,4*4=16;
  printf("%d\n", sizeof(&a[0] + 1));//&a[0]为第一行的地址,&a[0] + 1为第二行的地址,地址就占4 / 8个字节,32位机器占4个字节
  printf("%d\n", sizeof(*(&a[0] + 1)));//第二行的地址解引用得到第二行,4*4=16;
  printf("%d\n", sizeof(*a));//a没有单独放在sizeof内,a表示第一行的地址,*a得到是第一行,4*4=16;
  printf("%d\n", sizeof(a[3]));//sizeof(a[3])直接会被替换成sizeof(a[0]),不会访问a[3]的地址,不会越界访问--16

2.总结

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址。

3.指针笔试题

笔试题1:

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

分析:

笔试题2

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
  int Num;
  char* pcName;
  short sDate;
  char cha[2];
  short sBa[4];
}*p;
//假设p 的值为0x100000。如下表表达式的值分别为多少?
int main()
{
  printf("%p\n", p + 0x1);
  printf("%p\n", (unsigned long)p + 0x1);
  printf("%p\n", (unsigned int*)p + 0x1);
  return 0;
}

分析:1. p为结构体指针,+1相当于跳过一个结构体大小,这里告知结构体的大小是20个字节,p + 0x1按16进制打印出来是0x100014

2. p转化为无符号 长整型,并非指针,+1,就是+1,0x100001

3. p转化为无符号整型类型指针+1跳过四个字节。0x100004

由于以%p打印,第一个00100014,第二个00100001,第三个00100004

他这里的p的值为0x000000

笔试题3:

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

分析:

笔试题4:

int main()
{
  int a[3][2] = { (0, 1), (2, 3), (4, 5) }; 
  int* p;
  p = a[0];
  printf("%d", p[0]); 
  return 0;
}

分析:==注意里面不是这种{}==所以是逗号表达式

笔试题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;
}

分析:

笔试题6:

int main()
{
    intaa[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;
}

分析:

笔试题7:

int main() 
{
  char* a[] = { "work","at","alibaba" };
  char** pa = a;
  pa++;
  printf("%s\n", *pa);
  return 0;
}

分析

笔试题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;
}

分析

目录
相关文章
|
11月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
368 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
9月前
|
存储 人工智能 Java
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
176 0
|
11月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
1306 9
|
11月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
353 7
|
12月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
12月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
12月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
709 3
|
12月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
237 1
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
1094 13