C语言 —— 此去经年梦浪荡魂音 - 深入理解指针(卷五)

server/2025/3/31 12:09:54/

目录

1. sizeof 和 strlen的区别

1.1 sizeof

1.2 strlen

2. 数组和指针习题解析

2.1  一维数组

2.2 字符数组

代码1:

代码2:

代码3:

代码4:

代码5:

代码6:

2.3 二维数组

3. 指针运算笔试题解析

3.1 

3.1 

3.3

3.4 

3.5

3.6

3.7

p1

p2

p3

p4


1. sizeof 和 strlen的区别

   

1.1 sizeof

sizeof 计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小

   

sizeof 只关注占⽤内存空间的大小,不在乎内存中存放什么数据

sizeof是操作符
sizeof计算操作数所占内存的⼤⼩,单位是字节
不关注内存中存放什么数据

#include <stdio.h>int main()
{int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;
}

1.2 strlen

strlen文档链接:

  

strlen - C++ Referencehttps://legacy.cplusplus.com/reference/cstring/strlen/?kw=strlen

strlen是库函数,使⽤需要包含头⽂件 string.h
srtlen是求字符串⻓度的,统计的是 \0 之前字符的隔个数
关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能会越界

strlen 是C语言库函数,功能是求字符串长度。函数原型如下:

size_t strlen ( const char * str );

统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数,strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找

#include <stdio.h>int main()
{char arr1[3] = {'a', 'b', 'c'};char arr2[] = "abc";printf("%d\n", strlen(arr1));printf("%d\n", strlen(arr2));printf("%d\n", sizeof(arr1));printf("%d\n", sizeof(arr2));return 0;
}

这里strlen(arr1)就是没有\0所以就越界查找,产生了随机值35

如果字符串中间就有一个\0,那么就以这个\0为基准


2. 数组和指针习题解析

2.1  一维数组

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

X86和X64环境下运行结果:

代码解析:

2.2 字符数组

 注意:

代码1:

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

X86和X64环境下运行结果:

代码解析:

代码2:

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

X86和X64环境下运行结果:

代码解析:

代码3:

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

X86和X64环境下运行结果:

代码解析:

代码4:

char arr[] = "abcdef";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));

X86和X64环境下运行结果:

代码解析:

代码5:

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

X86和X64环境下运行结果:

代码解析:

代码6:

char *p = "abcdef";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));

X86和X64环境下运行结果:

代码解析:

2.3 二维数组

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

X86和X64环境下运行结果:

代码解析:

数组名的意义:

   
1. sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的大小

   
2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址

    
3. 除此之外所有的数组名都表示首元素的地址


3. 指针运算笔试题解析

   

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

3.1 

在X86环境下假设结构体的大小是20个字节程序输出的结构是什么

struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;//定义了一个指向 Test 结构体的指针 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;
}

运行结果: 

题目解析:

3.3

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

 

a[0] 指向二维数组 a 第一行,这里将 a[0] 赋值给指针 p,此时 p 就指向了数组 a 的第一行的第一个元素,也就是值为 1 的那个元素

 

3.4 

//假设环境是x86环境,程序输出的结果是啥?
#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;
}

3.5

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

3.6

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

3.7

运算符优先级博客链接:

   

 C语言 —— 愿此世如黄金般辉煌 - 进制转换与操作符详解-CSDN博客https://blog.csdn.net/hedhjd/article/details/146116491?spm=1001.2014.3001.5501

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

 

 

p1

printf("%s\n", **++cpp);

++cpp 会使 cpp 指针自增,指向 cp +1的位置,也就是数组中的第二个元素,*cpp 得到c+2,c + 2 的指针指向字符串 POINT,然后再次*得到POINT

 

p2

printf("%s\n", *-- * ++cpp + 3);

 

p3

printf("%s\n", *cpp[-2] + 3);

p4

printf("%s\n", cpp[-1][-1] + 1);


完结撒花~


http://www.ppmy.cn/server/179842.html

相关文章

RabbitMQ 学习整理1 - 基础使用

项目代码&#xff1a;RabbitMQDemo: 学习RabbitMQ的一些整理 基本概念 RabbitMQ是一种基于AMQP协议的消息队列实现框架RabbitMQ可以用于在系统与系统之间或者微服务节点之间&#xff0c;进行消息缓存&#xff0c;消息广播&#xff0c;消息分配以及限流消峰处理RabbitMQ-Serve…

云端存储新纪元:SAN架构驱动的智能网盘解决方案

一、企业存储的"不可能三角"破局 1.1 传统存储架构的困局 性能瓶颈&#xff1a;NAS架构在1000并发访问时延迟飙升300%容量限制&#xff1a;传统RAID扩容需停机维护&#xff0c;PB级存储扩展耗时超48小时成本矛盾&#xff1a;全闪存阵列每TB成本高达$3000&#xff0…

在 Ubuntu 上安装 Docker 的完整指南

1. 卸载旧版本(如有) 在安装新版本前,建议先卸载旧版本: sudo apt remove docker docker-engine docker.io containerd runc 2. 安装依赖包 更新软件包索引并安装必要的依赖: sudo apt update sudo apt install -y ca-certificates curl gnupg lsb-release 3. 添加 Do…

Spring Boot集成阿里云OSS:对象存储实战指南

Spring Boot集成阿里云OSS&#xff1a;对象存储实战指南 1. OSS是什么&#xff1f;为什么选择阿里云OSS&#xff1f; 对象存储&#xff08;OSS&#xff09; 是一种用于存储非结构化数据&#xff08;如图片、视频、日志文件&#xff09;的云服务&#xff0c;核心功能包括&#…

mapbox进阶,仿照百度,加载marker点位,移入marker点切换图标,点击展示气泡,气泡和marker联动

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️marker 标注点位 api1.3.1 ☘️构造函数…

蓝桥杯 第十二天 819 递增序列

注意注意&#xff1a;不考虑左上的情况&#xff0c;因为题目给的样例没有 public static int is1(char ch[][],int m,int n){int ans0;for (int i0;i<m;i){//起始点在哪for (int j0;j<n;j){int add1;while(jadd<n){if(ch[i][j]<ch[i][jadd]) ans; //横add;}add1…

清空数组,或删除数组还有什么方法

在 JavaScript 中&#xff0c;除了前面提到的 a [] 和 a.splice(0) &#xff0c;还有其他几种方法可以清空或删除数组&#xff0c;下面为你详细介绍&#xff1a; 1. 将数组的 length 属性设置为 0 let a [1, 2, 3, 4]; a.length 0; console.log(a); // 输出: [] 原理&…

【设计模式】抽象工厂模式(含与工厂方法模式的对比)

本期我们来学习一下设计模式之抽象工厂模式&#xff0c;在软件开发中&#xff0c;工厂模式 和 抽象工厂模式 都用于创建对象&#xff0c;但它们的应用场景和实现方式有所不同。本文将基于 C 代码&#xff0c;分析抽象工厂模式的实现&#xff0c;并对比其与工厂方法模式的区别。…