c语言分层理解(c语言指针笔试题解析)(2)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 前言经过了一天的写作,终于完成了这一篇,对指针进行了练习,感觉很爽,分享一下!还望大佬多多关注!1. 一维数组和指针

3. 二维数组和指针

3.1 例题

#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]));
  return 0;
}

3.2 解析

#include <stdio.h>
int main()
{
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));
  //结果:48字节
  //解释:a是数组名,数组名单独放在sizeof内部,计算的是整个二维数组大小,所以sizeof(a)=4*3*4=48,单位是字节
  printf("%d\n", sizeof(a[0][0]));
  //结果:4字节
  //解释:a[0][0]得到的第一行第一列的元素,元素类型是int,所以sizeof(a[0][0])=sizeof(int)=4,单位是字节
  printf("%d\n", sizeof(a[0]));
  //结果:16字节
  //解释:a[0]表示二维数组的第一行,第一行是一个有四个元素的一维数组,在二维数组中a[0]就相当于一维数组名,
  //     数组名单独放在sizeof内部,计算的是整个一维数组的大小,a[0]类型是int [4],所以sizeof(a[0])=4*4=16,单位是字节
  printf("%d\n", sizeof(a[0] + 1));
  //结果:4/8字节
  //解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,在二维数组中a[0]就相当于一维数组名,并不是单独放在二维数组中,所以他就是一维数组首元素地址,地址就是指针,
  //     指针类型是int*,a[0]+1就是跳过一个int大小,得到a[0][1]的地址,地址就是指针,所以sizeof(a[0]+1)计算的是整个指针的大小,单位是字节
  printf("%d\n", sizeof(*(a[0] + 1)));
  //结果:4字节
  //解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,在二维数组中a[0]就相当于一维数组名,并不是单独放在二维数组中,所以他就是一维数组首元素地址,地址就是指针,
  //     指针类型是int*,a[0]+1就是跳过一个int大小,得到a[0][1]的地址,地址就是指针,拿到a[0][1]这个元素,元素类型是int类型,所以sizeof(*(a[0]+1))=sizeof(int),单位是字节
  printf("%d\n", sizeof(a + 1));
  //结果:4/8字节
  //解释:a是数组名,并没有单独放在sizeof内部,所以a是二维数组首行地址,地址就是指针,类型是int (*arr)[4],a+1跳过一个有4个int类型元素的数组,得到a[1],
  //     也就是二维数组第二行地址,地址就是指针,所以sizeof(a+1)计算的是指针大小
  printf("%d\n", sizeof(*(a + 1)));
  //结果:16字节
  //解释:a是数组名,并没有单独放在sizeof内部,所以a是二维数组首行地址,地址就是指针,类型是int (*arr)[4],a+1跳过一个有4个int类型元素的数组,得到a[1],
  //     也就是二维数组第二行地址,对其解引用得到的是二维数组中第二行一维数组,sizeof(*(a+1))=sizeof(a[1])=4*4=16,单位是字节
  printf("%d\n", sizeof(&a[0] + 1));
  //结果:4/8字节
  //解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,&a[0]得到的是二维数组的第一行整个数组的地址,地址就是指针,指针类型是int (*arr)[4],&a[0]+1跳过一个一维数组的大小,
  //     得到的就是二维数组中第二行整个一维数组的地址,地址就是指针,所以sizeof(&a[0]+1)计算的就是指针的大小
  printf("%d\n", sizeof(*(&a[0] + 1)));
  //结果:16字节
  //解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,&a[0]得到的是二维数组的第一行整个数组的地址,地址就是指针,指针类型是int (*arr)[4],&a[0]+1跳过一个一维数组的大小,
  //     得到的就是二维数组中第二行整个一维数组的地址,*(&a[0]+1)得到的就是二维数组中的第二行一维数组,sizeof(*(&a[0] + 1))=sizeof(a[1])=4*4=16,单位是字节
  printf("%d\n", sizeof(*a));
  //结果:16字节
  //解释:a是二维数组的数组名,数组名不没有单独放在sizeof内部,所以a是第一行的地址,地址就是指针,指针类型是int (*arr)[4],
  //     *a得到的就是二维数组中的整个第一行一维数组,sizeof(*a)=sizeof(a[0])=4*4=16,单位是字节
  printf("%d\n", sizeof(a[3]));
  //结果: 16字节
  //解释:a[3]在二维数组中就相当于拿到下标为3的一整行一维数组,a[3]也就是第四行的一维数组名,数组名在sizeof内部,计算的是整个数组的大小,
  //     虽然没有数组没有第四行,但是可以给a[3]预分配一个空间,所以给a[3]预分配一个int [4]的空间,sizeof计算的只是类型的大小,这里a[3]的类型就是int [4],所以sizeof(a[3])=4*4=16,单位是字节
  return 0;
}

3.3 输出结果

3.3.1 32位平台

8874ee4b2ed73fd478c2d8987647f9b9.png

3.3.2 64位平台

0a7a9343ecc578d1bf97971df96e2511.png

4. 例题4.指针

4.1 例题

#include <stdio.h>
int main()
{
  int a[5] = { 1, 2, 3, 4, 5 };
  int* ptr = (int*)(&a + 1);
  printf("%d,%d", *(a + 1), *(ptr - 1));
  return 0;
}

4.2 解析

b6fd378f4ec7c2c8a44e2cf268775d14.png

5. 例题5.指针

5.1 例题

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

5.2 解析

ccfe48d6e6d3cda20226ee90445220fe.png

6. 例题6.指针

6.1 例题

#include <stdio.h>
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;
}

6.2 解析

fcc5dae4c0261debea1862e20a588962.png

7. 例题7.指针

7.1 例题

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

7.2 解析

ac1fd92cc463cadc227c4149757d1beb.png

8. 例题8.指针

8.1 例题

#include <stdio.h>
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;
}

8.2 解析

4d8fb7eebd7c965c0effbb807a76ba29.png

9. 例题9.指针

9.1 例题

#include <stdio.h>
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;
}

9.2 解析

d8feb9d62ebed8a635ae9c9a8daf1853.png

10. 例题10.指针

10.1 例题

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

10.2 解析

b88a46054400d5101bf154b0834c3718.png

11. 例题11.指针

11.1 例题

#include <stdio.h>
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.2 解析

![](https://ucc.alicdn.com/images/user-upload-01/img_convert/24baf958d698b0ac8197755d5762942d.png

12. 总结

sizeof计算大小的时候,首先关心计算对象,是一个变量还是一个数组名,还是什么,这里重点放在计算数组上,如果sizeof内部包含一个单独的数组名,说明这个sizeof计算的是整个数组的大小,否则不是,单位是字节,这个很重要,假如说sizeof(arr[2][2]),这个二维数组的类型是int,那么这个sizeof(arr[2][2])= 224=16,单位是字节。计算字符串数组的时候,sizeof(arr)计算包含’\0’的计算,'\0’也是占空间。

strlen计算的是’\0’之前的元素个数,在数组中,数组中不包含’\0’的话,一般这里就是随机值,另外注意strlen库函数再求一个字符解引用的时候会出现报错,原因就是非法访问。

&数组名,取的是整个数组的地址,&arr+1也是跳过整个数组的大小

对指针进行解引用的时候,要关注指针对应的元素类型,这决定了拿取多少个字节的空间,指针±操作的时候要关注类型,决定步长。







相关文章
|
2天前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
8天前
|
存储 安全 C语言
C语言 二级指针应用场景
本文介绍了二级指针在 C 语言中的应用,
|
23天前
|
存储 编译器 C语言
【C语言篇】深入理解指针2
代码 const char* pstr = "hello world."; 特别容易让初学者以为是把字符串 hello world.放 到字符指针 pstr ⾥了,但是本质是把字符串 hello world. 首字符的地址放到了pstr中。
|
23天前
|
存储 程序员 编译器
【C语言篇】深入理解指针1
assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为“断⾔”。
|
26天前
|
存储 搜索推荐 C语言
C语言中的指针函数:深入探索与应用
C语言中的指针函数:深入探索与应用
|
19天前
|
程序员 C语言
位操作在C语言中的解析与应用
位操作在C语言中的解析与应用
59 0
|
23天前
|
C语言
【C语言】指针速览
【C语言】指针速览
15 0
|
29天前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
29天前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
13天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件

推荐镜像

更多