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也是跳过整个数组的大小

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







相关文章
|
15天前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
41 0
|
14天前
|
C语言
【c语言】指针就该这么学(3)
本文介绍了C语言中的函数指针、typedef关键字及函数指针数组的概念与应用。首先讲解了函数指针的创建与使用,接着通过typedef简化复杂类型定义,最后探讨了函数指针数组及其在转移表中的应用,通过实例展示了如何利用这些特性实现更简洁高效的代码。
11 2
|
15天前
|
C语言
如何避免 C 语言中的野指针问题?
在C语言中,野指针是指向未知内存地址的指针,可能引发程序崩溃或数据损坏。避免野指针的方法包括:初始化指针为NULL、使用完毕后将指针置为NULL、检查指针是否为空以及合理管理动态分配的内存。
|
15天前
|
C语言
C语言:哪些情况下会出现野指针
C语言中,野指针是指指向未知地址的指针,通常由以下情况产生:1) 指针被声明但未初始化;2) 指针指向的内存已被释放或重新分配;3) 指针指向局部变量,而该变量已超出作用域。使用野指针可能导致程序崩溃或不可预测的行为。
|
21天前
|
存储 C语言
C语言32位或64位平台下指针的大小
在32位平台上,C语言中指针的大小通常为4字节;而在64位平台上,指针的大小通常为8字节。这反映了不同平台对内存地址空间的不同处理方式。
|
21天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
21天前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
22天前
|
C语言
C语言指针(3)
C语言指针(3)
11 1
|
22天前
|
C语言
C语言指针(2)
C语言指针(2)
12 1
|
14天前
|
编译器 C语言
【c语言】指针就该这么学(2)
本文详细介绍了指针与数组的关系,包括指针访问数组、一维数组传参、二级指针、指针数组和数组指针等内容。通过具体代码示例,解释了数组名作为首元素地址的用法,以及如何使用指针数组模拟二维数组和传递二维数组。文章还强调了数组指针与指针数组的区别,并通过调试窗口展示了不同类型指针的差异。最后,总结了指针在数组操作中的重要性和应用场景。
13 0

推荐镜像

更多