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

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

前言

经过了一天的写作,终于完成了这一篇,对指针进行了练习,感觉很爽,分享一下!还望大佬多多关注!

1. 一维数组和指针

1.1 例题

int main()
{
  int a[] = { 1,2,3,4 };
  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));
  return 0;
}

1.2 解析

#include <stdio.h>
int main()
{
  int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));
  //结果:16字节
  //解释:数组名单独放在sizeof内部计算的是整个数组的大小,单位是字节
  printf("%d\n", sizeof(a + 0));
  //结果:4/8字节
  //解释:数组名并没有单独放在sizeof内部,所以a就是首元素地址,a+0也是首元素地址,所以计算的是一个指针的大小,单位是字节,
  //     千万不能把sizeof(a+0)当作sizeof(a)来计算
  printf("%d\n", sizeof(*a));
  //结果:4字节
  //解释:数组名并没有单独放在sizeof内部,所以a就是首元素地址,对int*指针进行解引用,拿到的是一个int类型的元素,sizeof(*a)=sizeof(int),单位是字节
  printf("%d\n", sizeof(a + 1));
  //结果:4/8字节
  //解释:数组名并没有单独放在sizeof内部,所以a就是首元素地址,因为a是int*指针,所以a+1就跳过一个int类型的元素,
  //     a+1也就是指向数组第二个元素的是指针,所以sizeof(a+1)计算的是指针的大小,单位是字节
  printf("%d\n", sizeof(a[1]));
  //结果:4字节
  //解释:a[1]拿到的是小标为1的元素,元素类型是int类型,所以sizeof(a[1])=sizeof(int),单位是字节
  printf("%d\n", sizeof(&a));
  //结果:4/8字节
  //解释:&a就是取到的整个数组的地址,是一个指向整个数组的指针,所以sizeof(&a)计算的就是指针大小,单位是字节
  printf("%d\n", sizeof(*&a));
  //结果:16字节
  //解释:*&a也就是先拿到数组a的整个数组的地址,再对&a解引用,拿到的是整个数组的大小,所以sizeof(*&a)=sizeof(a),单位是字节
  printf("%d\n", sizeof(&a + 1));
  //结果:4/8字节
  //解释:&a+1也就是拿到整个数组的地址,整个数组的指针类型是一个数组指针类型,&a+1也就跳过一个数组的大小,得到的仍然是地址,地址就是指针,
  //     所以sizeof(&a+1)也就是计算指针的大小,单位是字节
  printf("%d\n", sizeof(&a[0]));
  //结果:4/8字节
  //解释:&a[0]也就是拿到下标为0的元素的地址,也就是拿到第一个元素的地址,地址就是指针,所以sizeof(&a[0])计算的就是指针的大小
  printf("%d\n", sizeof(&a[0] + 1));
  //结果:4/8字节
  //解释:&a[0]+1,也就是拿到第一个元素的地址,再跳过这个元素,拿到下一个元素的地址,地址就是指针,所以sizeof(&a[0]+1)计算的就是指针的大小
  return 0;
}

1.3 输出结果

1.3.1 32位平台

4e1a4618d294f772260cd1b5d053c301.png

1.3.1 64位平台

3095b8de3038c0855f6773405e31900a.png

2. 字符数组和指针

2.1 形式1(char arr[] = {‘#’,‘#’,‘#’,‘#’,‘#’})

2.1.1 例题

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

2.1.2 解析

#include <stdio.h>
#include <string.h>
int main()
{
  char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", sizeof(arr));
  //结果:6字节
  //解释:arr是数组名,单独的数组名在sizeof内部,计算的是数组的大小,数组只分配了6个字节的空间,所以数组大小是6,单位是字节
  printf("%d\n", sizeof(arr + 0));
  //结果:4/8字节
  //解释:arr是数组名,但是并没有单独在sizeof内部,所以arr是首元素地址,arr+0拿到的还是首元素的地址,地址就是指针,所以sizeof计算的是指针的大小,单位是字节
  printf("%d\n", sizeof(*arr));
  //结果:1字节
  //解释:arr是数组名,但是并没有单独在sizeof内部,所以arr是首元素地址,指针类型是char*,对指针解引用就拿到第一个元素,
  //     第一个元素的大小是1个字节,sizeof(*arr)=sizeof(arr[0])
  printf("%d\n", sizeof(arr[1]));
  //结果:1字节
  //解释:arr[1]就是下标为1的元素,也就是数组中第二个元素,元素类型是char,所以sizeof(arr[1])=sizeof(char),单位是字节
  printf("%d\n", sizeof(&arr));
  //结果:4/8字节
  //解释:&arr,拿到的是整个数组的地址,地址就是指针,所以sizeof(&arr)计算的是指针的大小
  printf("%d\n", sizeof(&arr + 1));
  //结果:4/8字节
  //解释:&arr,拿到的是整个数组的地址,地址就是指针,指针类型是数组指针类型,指向的是整个数组,&arr+1也就是跳过一个数组指针的大小,
  //     也就是跳一个数组,得到的仍然是一个地址,地址就是指针,所以sizeof(&arr+1)计算的就是指针的大小,单位是字节
  printf("%d\n", sizeof(&arr[0] + 1));
  //结果:4/8字节
  //解释:&arr[0]得到的是一个下标为0的元素的地址,也就是得到的是数组中第一个元素的地址,地址就是指针,指针类型是int*,&arr[0]+1,
  //     跳过的就是一个整形的大小,得到的仍然是一个地址,地址就是指针,单位是字节
  //strlen库函数计算的是字符串中字符'\0'之前的元素个数
  printf("%d\n", strlen(arr));
  //结果:随机值
  //解释:strlen库函数计算的是字符串中字符'\0'之前的元素个数,但是在数组中我们用的是一块连续的空间,
  //     这块空间的后面都是随机值,arr是数组名,是首元素地址,从数组名这个地址向下找到'\0'字符,在此数组内部这6个元素中没有'\0',
  //     就在数组内存空间的后面继续查找'\0'字符,直到找到'\0'结束,所以这是一个随机值,不确定
  printf("%d\n", strlen(arr + 0));
  //结果:随机值
  //解释:arr是数组名,是首元素地址,arr+0仍然是首元素地址,strlen库函数计算的是字符串中字符'\0'之前的元素个数,
  //     所以要从数组名这个地址向下找到'\0'字符,内存是随机分配的数据,所以不知道'\0'字符的位置,所以是随机值。
  printf("%d\n", strlen(*arr));
  //结果:err
  //解释:arr是首元素地址,*arr就是对第一个元素解引用得到字符'a','a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。
  printf("%d\n", strlen(arr[1]));
  //结果:err
  //解释:arr[1]得到的就是数组的第二个元素'b','b'的ASCII值是98,strlen库函数把98当作地址,非法访问。
  printf("%d\n", strlen(&arr));
  //结果:随机值
  //解释:&arr得到的是整个数组的地址,也就是数组的起始地址,一样也是随机值,不知道'\0'在内存的哪里。
  printf("%d\n", strlen(&arr + 1));
  //结果:随机值
  //解释:&arr得到的是整个数组的地址,地址就是指针,指针类型是一个数组指针类型,&arr+1跳过的是整个数组,同样从数组的末尾地址向下寻找'\0'字符,
  //     任然是个随机值,不确定'\0'在内存中的位置。
  printf("%d\n", strlen(&arr[0] + 1));
  //结果:随机值
  //解释:&arr[0]拿到的是数组第一个元素的地址,地址就是指针,类型是char*,跳过一个char大小,也就得到第二个元素的地址,
  //     在内存中往下寻找'\0'字符,不知道内存中'\0'的位置,所以是随机值。
  return 0;
}

2.1.3 输出结果

说明:因为有两个是error的,所以屏蔽了这两段代码。具体显示是strlen库函数中函数参数是const char*的和这里的char的参数不一致,同时这里的隐藏错误就是非法访问地址。

2.1.3.1 32位平台

17c11fef9e5428d46c80a8dff2f02278.png

2.1.3.2 64位平台

image.png

2.2 形式2(char arr[] = “####”)

2.2.1 例题

#include <stdio.h>
#include <string.h>
int main()
{
  char arr[] = "abcdef";
  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));
  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));
  return 0;
}

2.2.2 解析

#include <stdio.h>
#include <string.h>
int main()
{
  char arr[] = "abcdef";
  printf("%d\n", sizeof(arr));
  //结果:7字节
  //解释:arr数组名单独放在sizeof内部,计算的是整个数组大小,数组包含abcdef\07个字符,所以是7个字节大小
  printf("%d\n", sizeof(arr + 0));
  //结果:4/8字节
  //解释:arr不是单独放在sizeof内部,所以arr是首元素地址,arr+0仍然是首元素地址,地址就是指针,sizeof(arr+0)计算的就是指针的大小,单位是字节
  printf("%d\n", sizeof(*arr));
  //结果:1字节
  //解释:*arr拿到的是第一个元素,元素类型是char,所以sizeof(*arr)=sizeof(char),单位是字节
  printf("%d\n", sizeof(arr[1]));
  //结果:1字节
  //解释:arr[1]拿到的是数组中第二个元素,类型是char,所以sizeof(arr[1])=sizeof(char),单位是字节
  printf("%d\n", sizeof(&arr));
  //结果:4/8字节
  //解释:&arr拿到的是整个数组的地址,地址就是指针,所以sizeof(&arr)计算的就是指针的大小
  printf("%d\n", sizeof(&arr + 1));
  //结果:4/8字节
  //解释:&arr拿到的是整个数组的地址,地址就是指针,指针类型是数组指针,&arr+1跳过的是整个数组,仍然得到的是地址,地址就是指针,所以sizeof(&arr+1)计算的就是指针的大小
  printf("%d\n", sizeof(&arr[0] + 1));
  //结果:4/8字节
  //解释:&arr[0]得到的是一个下标为0的元素的地址,也就是得到的是数组中第一个元素的地址,地址就是指针,指针类型是char*,&arr[0]+1,
  //     跳过的就是一个字符型的大小,得到的仍然是一个地址,地址就是指针,单位是字节
  printf("%d\n", strlen(arr));
  //结果:6字节
  //解释:strlen是计算'\0'之前的元素个数,字符串结束标志就是'\0',元素个数是6,所以strlen(arr)=6,单位是字节
  printf("%d\n", strlen(arr + 0));
  //结果:6字节
  //解释:arr是数组名,也就是首元素地址,从字符串第一个元素向后找到'\0'结束,字符串结束标志是'\0',所以strlen(arr+0)=6,单位是字节
  printf("%d\n", strlen(*arr));
  //结果:err
  //解释:arr是数组名,也就是首元素地址,*arr拿到第一个元素'a','a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。
  printf("%d\n", strlen(arr[1]));
  //结果:err
  //解释:arr[1]得到的就是数组的第二个元素'b','b'的ASCII值是98,strlen库函数把98当作地址,非法访问。
  printf("%d\n", strlen(&arr));
  //结果:6字节
  //解释:&arr得到的是整个数组的地址,也就是数组的起始地址,一样向后找到'\0'停止,strlen(&arr)=6,单位是字节
  printf("%d\n", strlen(&arr + 1));
  //结果:随机值
  //解释:&arr得到的是整个数组的地址,地址就是指针,指针类型是一个数组指针类型,&arr+1跳过的是整个数组,同样从数组的末尾地址向下寻找'\0'字符,
  //     任然是个随机值,不确定'\0'在内存中的位置。
  printf("%d\n", strlen(&arr[0] + 1));
  //结果:5字节
  //解释:&arr[0]拿到的是数组第一个元素的地址,地址就是指针,类型是char*,跳过一个char大小,也就得到第二个元素的地址,
  //     在内存中往下寻找'\0'字符,字符串结束表示'\0',所以strlen(&arr[0] + 1))=5,单位是字节
  return 0;
}

2.2.3 输出结果

说明:说明:因为有两个是error的,所以屏蔽了这两段代码。具体显示是strlen库函数中函数参数是const char*的和这里的char的参数不一致,同时这里的隐藏错误就是非法访问地址。

2.2.3.1 32位平台

947221722186c55056857bc3e9d422eb.png

2.2.3.2 64位平台

f7f769a959424f29877f362897de90b6.png

2.3 形式3(char* p = “####”)

2.3.1 例题

#include <stdio.h>
#include <string.h>
int main()
{
  char* p = "abcdef";
  printf("%d\n", sizeof(p));
  printf("%d\n", sizeof(p + 1));
  printf("%d\n", sizeof(*p));
  printf("%d\n", sizeof(p[0]));
  printf("%d\n", sizeof(&p));
  printf("%d\n", sizeof(&p + 1));
  printf("%d\n", sizeof(&p[0] + 1));
  printf("%d\n", strlen(p));
  printf("%d\n", strlen(p + 1));
  printf("%d\n", strlen(*p));
  printf("%d\n", strlen(p[0]));
  printf("%d\n", strlen(&p));
  printf("%d\n", strlen(&p + 1));
  printf("%d\n", strlen(&p[0] + 1));
  return 0;
}

2.3.2 解析

#include <stdio.h>
#include <string.h>
int main()
{
  char* p = "abcdef";
  printf("%d\n", sizeof(p));
  //结果:4/8字节
  //解释:p是字符串首元素地址,地址就是指针,指针类型是char*,所以sizeof(p)计算的是指针的大小
  printf("%d\n", sizeof(p + 1));
  //结果:4/8字节
  //解释:p是字符串首元素地址,地址就是指针,指针类型是char*,p+1就跳过一个char大小,也就是得到第二个元素'b'的地址,
  //     地址就是指针,所以sizeof(p+1)计算的就是指针的大小,单位是字节
  printf("%d\n", sizeof(*p));
  //结果:1字节
  //解释:p是字符串首元素地址,地址就是指针,对p解引用拿到'a','a'的类型就是char,所以sizeof(*p)=sizeof(char),单位是字节
  printf("%d\n", sizeof(p[0]));
  //结果:1字节
  //解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a','a'的类型是char,所以sizeof(p[0])=sizeof(char),单位是字节
  printf("%d\n", sizeof(&p));
  //结果:4/8字节
  //解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,所以sizeof(&p)计算的就是指针的大小,单位是字节
  printf("%d\n", sizeof(&p + 1));
  //结果:4/8字节
  //解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,二级指针类型是char**,&p+1跳过一个char*大小,得到的仍然是一个地址,地址就是指针,所以siezof(&p+1)计算的就是指针大小
  printf("%d\n", sizeof(&p[0] + 1));
  //结果:4/8字节
  //解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a',&p[0]就是拿到第一个元素的地址,地址就是指针,指针类型是char*,&p[0]+1跳过一个char类型大小,也就是拿到第二个元素'b'的地址,地址就是指针,所以sizeof(&p[0]+1)计算的就是指针大小
  printf("%d\n", strlen(p));
  //结果:6字节
  //解释:p是字符串首元素地址,也就相当于数组名,strlen是计算'\0'之前的元素个数,字符串结束标志就是'\0',元素个数是6,所以strlen(arr)=6,单位是字节
  printf("%d\n", strlen(p + 1));
  //结果:5字节
  //解释:p是首元素地址,地址就是指针,指针类型是char*,p+1跳过一个char大小,得到的是第二个元素'b'的地址,strlen是计算'\0'之前的元素个数,字符串结束标志就是'\0',所以strlen(p+1)=5
  printf("%d\n", strlen(*p));
  //结果:err
  //解释:p是首元素地址,地址就是指针,指针类型是char*,对其解引用拿到'a'字符,'a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。
  printf("%d\n", strlen(p[0]));
  //结果:err
  //解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a','a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。
  printf("%d\n", strlen(&p));
  //结果:随机值
  //解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,二级指针类型是char**,地址不是从p开始向下寻找了,所以不知道内存中'\0'的位置,所以是随机值,单位是字节
  printf("%d\n", strlen(&p + 1));
  //结果:随机值
  //解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,二级指针类型是char**,跳过一个char*大小,得到的地址也不是从p开始向下寻找了,
  //     所以不知道内存中'\0'的位置,所以是随机值,单位是字节
  printf("%d\n", strlen(&p[0] + 1));
  //结果:5字节
  //解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a',&p[0]拿到第一个元素'a'的地址,地址就是指针,指针类型是char*,&p[0]+1就是跳过一个char大小,得到第二个元素'b'的地址,从这里往后找,找到'\0'停止,字符串结束标志是'\0',所以strlen(&p[0] + 1))=5,单位是字节
  return 0;
}

2.3.3 输出结果

说明:因为有两个是error的,所以屏蔽了这两段代码。具体显示是strlen库函数中函数参数是const char*的和这里的char的参数不一致,同时这里的隐藏错误就是非法访问地址。

2.3.3.1 32位平台

9bb4339ffba4d1bd3c5eb8b84004bd2e.png

2.3.3.2 64位平台

aeb720b738e5d557bdd6319b1c8f2510.png
































相关文章
|
1月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
27 0
|
1月前
|
程序员 编译器 数据处理
【C语言】深度解析:动态内存管理的机制与实践
【C语言】深度解析:动态内存管理的机制与实践
|
1月前
|
Serverless 编译器 C语言
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
|
3月前
|
程序员 C语言
位操作在C语言中的解析与应用
位操作在C语言中的解析与应用
91 0
|
3月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
3月前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
35 3
|
14天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
30 6

推荐镜像

更多
下一篇
无影云桌面