006 从不同的角度理解数组名的意义——“C”

2023-11-04

 

 

一、数组名的意义是什么?

引入

1.数组名的意义sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小

&数组名。这里的数组名表示整个数组。取出的是整个数组的地址

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

2.strlen函数基本用法:size_t strlen ( const char * str );

strlen: Returns the length of the C string str.

返回字符串的长度

The length of a C string is determined by the terminating null-character: A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).

字符串的长度取决于空字符\0的所在位置,字符串的长度包括给定的字符串起始位置到\0处,不包含\0

3.sizeof运算符基本用法:以字节为单位返回类型或值的大小,该值为无符号整数

二、使用步骤

1.从数组元素为单个字符的形式理解数组名的意义

int main()
{
	char arr[] = {'a','b','c','d','e','f'};
	printf("%d\n", sizeof(arr));
// sizeof(数组名):整个数组的大小,6个字节
	printf("%d\n", sizeof(arr+0));   
//  数组首元素地址,地址是编号,大小为4/8个字节
	printf("%d\n", sizeof(*arr)); 
// 不是只有arr(数组名)放在里面  取地址*arr是首元素的大小,计算的是首元素的大小
// 字节为1
	printf("%d\n", sizeof(arr[1])); 
// 数组的第二个元素大小,1个字节
	printf("%d\n", sizeof(&arr)); 
// 取出整个数组的地址,4/8
	printf("%d\n", sizeof(&arr+1));
//4个字节
// &数组名:取出整个数组的地址,+1:跳过整个数组后的地址,依旧是地址
// sizeof不会真的去访问地址,
	printf("%d\n", sizeof(&arr[0]+1)); 
 //取出第一个元素的地址,+1第二个元素的地址   4/8
	return 0;
}

 

 

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));
	//随机值,不知\0的位置
	printf("%d\n", strlen(arr + 0));
	//传给str首元素的地址从后数   
//	printf("%d\n", strlen(*arr));
// 	   arr:数组首元素的地址,*解引用地址=97
	//传给str字符‘a’=97,代码是有问题的,str把97当作地址
	//这一块地址不是arr的,把地址传给str,会形成非法访问0X000061=16
//	printf("%d\n", strlen(arr[1]));
// 	   字符'b'=98
	//把字符‘b’当作地址,形成非法访问,str
	printf("%d\n", strlen(&arr));
	//随机值 虽然是数组地址,但传给Str就知道从起始位置开始数
	printf("%d\n", strlen(&arr + 1));
	//随机值 跳过一个数组,从数组末尾开始数,随机值-6
	printf("%d\n", strlen(&arr[0] + 1));
	//从b的位置往后数,随机值-1
	return 0;
}

2.从数组元素为字符串的形式理解数组名的意义

      int main() 
{
char arr[] = { "abcdef" };
printf("%d\n", sizeof(arr));
//只有数组名,表示整个数组的大小
//数组的大小,7个元素,7个字节
printf("%d\n", sizeof(arr + 0));   
//arr数组名不是单独放在括号里面,表示数组首元素的地址
//地址是编号,4/8个字节
printf("%d\n", sizeof(*arr)); 
//arr数组名不是单独放在括号里面
//arr数组首元素的地址 *arr是首元素,计算的是首元素的大小:char类型:1个字节
printf("%d\n", sizeof(arr[1])); 
//数组的第二个元素大小,1个字节
printf("%d\n", sizeof(&arr)); 
//&取地址数组名,取出数组的地址,4/8
printf("%d\n", sizeof(&arr + 1));
//跳过整个数组后仍然是地址,大小为4/8字节
printf("%d\n", sizeof(&arr[0] + 1));
//4/8  &arr[0]:数组首元素的地址 +1:下一个元素的地址  
printf("%d\n", strlen(arr));
//6个字节
//数组名表示数组首元素地址 
//传入一个数组名的时候,strlen默认在数组起始位置开始统计,到\0结束
printf("%d\n", strlen(arr +  0));
//6个字节
//数组名表示数组首元素地址  +0:依旧是数组首元素的地址传给strlen作为起始位置

//printf("%d\n", strlen(*arr));
//传给str字符‘a’=97,代码是有问题的,str把97当作地址
//这一块地址不是arr的,把地址传给str,strlen要访问地址找到起始位置
//会形成非法访问 err

//printf("%d\n", strlen(arr[1])); 
//把字符‘b’=98当作地址,形成非法访问,err



printf("%d\n", strlen(&arr));
//6
//取出的是整个数组的地址 类型应该是指针类型  数组指针char (*)[7]
//strlen的类型是const char*类型 
//但传给Str就把数组首元素地址当作起始位置

printf("%d\n", strlen(&arr + 1));
//&数组名:表示整个数组,取出的是整个数组的地址   
//随机值 跳过一个数组,从数组末尾开始数,随机值-6
printf("%d\n", strlen(&arr[0] + 1));
//从b到\0大小为5个字节
return 0;
}  

 

 3.从指针的角度理解数组名的意义

int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));  
	//指针p中存放的是a的地址,起始位置为a,6个字节大小
	printf("%d\n", strlen(p + 1)); 
	//p+1是‘b’的地址  字节大小为5
	printf("%d\n", strlen(*p));  
	//err 将aAscll码值当作地址,非法访问
	printf("%d\n", strlen(p[0]));
	//相当于*(p+0)  将aAscll码值当作地址 非法访问 err
	/printf("%d\n", strlen(&p));
	//随机值

	printf("%d\n", strlen(&p + 1));
	//随机值,跳过p变量
	printf("%d\n", strlen(&p[0] + 1)); //'b'的地址,5
	return 0;
}

 非法访问err

 屏蔽掉代码后成功运行

int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));  
 //指针变量是用来存放地址的
 //一个指针变量的大小4/8字节
	printf("%d\n", sizeof(p+1)); 
	//‘b’的地址,4/8个字节
	printf("%d\n", sizeof(*p)); 
	//解引用,字节大小为1,一个字符的大小
	printf("%d\n", sizeof(p[0]));
	//相当于*(p+0)  表示字符'a'  1个字节
	printf("%d\n", sizeof(&p));
	//4/8个字节
	//指针p中存放地址类型为char*  &p--char** 把&p的地址取出来放到二级指针中去
	//char**pp    *pp表明pp是指针,
	//char*说明pp指向的是p,p的类型是char*

	printf("%d\n", sizeof(&p+1));
	//pp指向的是char*的数据,+1跳过一个char*的数据,4/8个字节
	printf("%d\n", sizeof(&p[0] + 1)); //'b'的地址,4/8个字节
	return 0;
}

 

 

 4.从二维数组的角度理解数组名的意义

int main()
{
	int a[3][4] = { 0 };  //定义一个二维数组
	printf("%d\n", sizeof(a));
	//48个字节  a这个二维数组的数组名单独放在sieof内部,计算整个数组的大小
	printf("%d\n", sizeof(a[0][0]));
	//第一行的第一个元素,4个字节
	printf("%d\n", sizeof(a[0]));
	//a[0]作为第一行的数组名,这个时候数组名单独放在sizeof内部,计算的第一行的数组大小
	//一行4个整型,16个字节

	printf("%d\n", sizeof(a[0]+1));
	//a[0]是第一行的数组名,a[0]不是单独放在sizeof内部,表示首元素的地址,即第一行第一个元素的地址
	//+1第一行第二个元素的地址
	//4个字节
	printf("%d\n", sizeof(*(a[0]+1)));
	//解引用 a[0][1]大小为4个字节
	printf("%d\n", sizeof(a+1));
	//第二行的地址,依旧是地址,大小为4个字节
	//a+1是跳过一行,指向了第二行
	// a作为二维数组的数组名并非单独放在sizeof内部,所以表示二维数组首元素的地址
	// 二维数组首元素地址是第一行的地址
	//二维数组的首元素是第一行,这里的a就是第一行的地址--类型为int(*)[4]数组指针
	//+1类型不变,还是数组指针
	//并不是指向第一行第二个元素,第一行第二个元素是整形指针,指向一个整形
	printf("%d\n", sizeof(*(a+1)));
	//对数组第二行解引用得到第二行的大小,16个字节
	printf("%d\n", sizeof(&a[0]+1));
	//&a[0]是第一行的地址
	//&a[0]+1是第二行的地址,4个字节
	printf("%d\n", sizeof(*(&a[0]+1)));
	//解引用第二行的地址,字节大小为16个字节
	printf("%d\n", sizeof(*a));
	//数组名不是单独放在里面,相当于二维数组首元素的地址--第一行的地址
	//解引用大小为16个字节
	//*a==*(a+0)==a[0]
	printf("%d\n", sizeof(a[3]));
	//大小为16个字节
	//sizeof不会真的访问。不越界
	//根据类型属性就判断出a[3]与a[1]类型属性相同,不会去访问第四行
	return 0;
}

ps:注意区分a+1与a[0]+1的区别:

a代表二维数组的数组名,二维数组的数组名表示二维数组首元素的地址即第一行的地址

 a[0]是第一行的数组名表示第一行首元素的地址,即第一行第一个的元素,+1为第一行第二个元素。

总结
以上就是今天要讲的内容:

从strlen()函数与操作符sizeof入手结合二维数组,指针,字符数组的角度来理解数组名的意义同时加强对strlen()函数,sizeof,二维数组,指针理解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

006 从不同的角度理解数组名的意义——“C” 的相关文章

  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐

  • PCM音频 && I2S音频

    PCM Pulse Code Modulation 也被称为脉码编码调制 PCM中的声音数据没有被压缩 如果是单声道的文件 采样数据按时间的先后顺序依次存入 关于PCM的详细细节可以参考http blog csdn net yue76038
  • 在Java中操作MySQL(JDBC)

    准备工作 idea mysql 官方的 jdbc 驱动 先在 idea 中建立一个新的 java 工程 直到这一步之前 一直按下一步就行了 把名字改改直接 finish 在这个工程下面建立一个名字为 lib 的空文件夹 去官方下载依赖的包
  • VSCode 集成chatGPT插件

    VSCode 是一款常用的编辑器 可以通过安装插件来扩展其功能 ChatGPT 是一款基于 OpenAI 的 GPT 3 语言模型的聊天机器人插件 可以让 VSCode 具备聊天机器人的功能 要在 VSCode 中集成 ChatGPT 插件
  • 配置类和配置文件修改ribbon的负载均衡策略

    Ribbon框架自带的负载策略类 配置类修改负载均衡策略 第一步 新建一个不会被 ComponentScan组件扫描到的包 如 com ribbon 第二步 在该包下新建自己的负载均衡算法的规则类 package ribbon import
  • 工厂七大浪费是指什么?生产计划与排程APS系统是如何解决的?

    一 工厂的七大浪费 1 不良品的浪费 以人 机 料 法 环的说法 可以将不良产品形成的原因分为三个方面 一是人员方面 大多数工厂作业人员流动大 新员工多 长时间的工作疲劳 工作不细致 不按标准执行 缺乏培训 过度依赖于人为经验发现问题等因素
  • uniapp蓝牙连接操作详解

    初始化蓝牙 openBluetoothAdapter uni openBluetoothAdapter 打开蓝牙适配器接口 success res gt 已打开 fail err gt 未打开 uni showToast icon none
  • linux的mysql如何删除用户_linux mysql增加用户,删除用户,以及用户权限

    一些基本的命令 登录 mysql u username p 显示所有的数据库 show databases 使用某一个数据库 use databasename 显示一个数据库的所有表 show tables 退出 quit 删除数据库和数据
  • 为什么kafka 需要 subscribe 的 group.id?我们是否需要使用 commitSync 手动提交偏移量?

    目录 一 为什么需要带有 subscribe 的 group id 二 我们需要使用commitSync手动提交偏移量吗 三 如果我想手动提交偏移量 该怎么做 一 为什么需要带有 subscribe 的 group id 消费概念 Kafk
  • 获取当前系统的时间

    1 time函数 函数原型 time t time time t t 函数功能 获取当前系统的时间 函数的返回值和参数都是time t类型的变量 且都可以获取当前系统的时间 使用前先定义一个time t类型的变量 例 time t t ti
  • 优秀logo设计解析_产品设计中十种常见LOGO工艺处理手法解析

    在制造业当中 一个产品中logo的如何应用 更能够体现这个品牌的形象 所谓细节决定成败 logo的处理更是产品设计细节中的细节 而产品设计师在完成产品设计时会考虑到logo的位置 样式以及工艺处理 作为一个优秀设计师那肯定需要了解LOGO的
  • Java中Lock锁的基本使用

    1 创建锁 2 加锁 3 解锁 package com liu demo01 import java util concurrent locks Lock import java util concurrent locks Reentran
  • Qt开发 之 抓取崩溃信息(读这一篇就够了)

    文章目录 1 简介 1 1 常见崩溃 1 2 BreakPad 1 2 1 源码 1 2 2 原理 1 3 用BreakPad处理崩溃具体流程 2 Qt中加入BreakPad 2 1 在项目中引入BreakPad模块 2 2 google
  • 入门级题解:2000. 反转单词前缀

    题目 给你一个下标从 0 开始的字符串 word 和一个字符 ch 找出 ch 第一次出现的下标 i 反转 word 中从下标 0 开始 直到下标 i 结束 含下标 i 的那段字符 如果 word 中不存在字符 ch 则无需进行任何操作 思
  • 软件测试职业生涯需要编写的全套文档模板,收藏这一篇就够了 ~

    作为一名测试工程师 在整个的职业生涯中 会涉及到各种不同类型的文档编写 大体包括如下 对应文档模板及文档编写视频如下 一 测试岗位必备的文档 在一个常规的软件测试流程中 会涉及到测试计划 测试方案 测试用例 测试报告的编写 这些文档也是软件
  • el-select绑定值赋值后,页面无法显示对应label值

    el select绑定值赋值后 页面无法显示对应label值 this lunwen achmId 1 页面也显示1 无法显示1对应的label值 这种情况大多数是数据类型不统一 比如页面绑定为number类型 而赋值为string类型 或
  • 多模态深度学习综述总结 与 目标检测多模态融合领域论文推荐

    文章目录 一 多模态学习定义及应用 二 模态表示 2 1 单模态表示 2 1 1 语句模态表示 2 1 2 视觉模态表示 2 1 3 声音模态表示 略 2 2 多模态表示 2 2 1 模态共作用语义表示 联合表示 2 2 2 模态约束语义表
  • 无公网IP,在外公网远程访问RabbitMQ服务「内网穿透」

    文章目录 前言 1 安装erlang 语言 2 安装rabbitMQ 3 内网穿透 3 1 安装cpolar内网穿透 支持一键自动安装脚本 3 2 创建HTTP隧道 4 公网远程连接 5 固定公网TCP地址 5 1 保留一个固定的公网TCP
  • Leedcode编程题283:移动零----C++实现

    目的 旨在记录在Leedcode网上刷题的过程 记录心得 题目 给定一个数组 nums 编写一个函数将所有 0 移动到数组的末尾 同时保持非零元素的相对顺序 示例 输入 0 1 0 3 12 输出 1 3 12 0 0 说明 必须在原数组上
  • SpringBoot连接超时导致的502错误案例

    1 问题描述 内部系统之间通过Nginx来实现路由转发 但最近发现有一个系统 经常报502错误 每天达到上百次 完全无法忍受 2 原因排查 于是进行排查 发现配置人员把连接超时时间 server tomcat connection time
  • 006 从不同的角度理解数组名的意义——“C”

    一 数组名的意义是什么 引入 1 数组名的意义 sizeof 数组名 这里的数组名表示整个数组 计算的是整个数组的大小 数组名 这里的数组名表示整个数组 取出的是整个数组的地址 除此之外所有的数组名都表示首元素的地址 2 strlen函数基