C 语言内存探秘:数据存储的字节密码

news2025/1/11 23:48:15

文章目录

  • 一、数据在内存中的存储
    • 1、基本数据类型存储
    • 2、数组存储
    • 3、结构体存储
      • 1、基本存储规则
      • 2、举例说明
      • 3、查看结构体大小和成员偏移量的方法
  • 二、大小端字节序
  • 三、字节序的判断

一、数据在内存中的存储

1、基本数据类型存储

  • 整型:如int类型,通常在32位系统中占4个字节,在内存中以二进制补码的形式存储。例如,整数10的二进制表示为00000000 00000000 00000000 00001010,以小端字节序存储时,在内存中的顺序是0A 00 00 00;以大端字节序存储时,顺序是00 00 00 0A
  • 浮点型:单精度float类型一般占4个字节,双精度double类型占8个字节。浮点数在内存中的存储遵循IEEE 754标准,以符号位、指数位和尾数位的形式存储。例如,单精度浮点数3.14在内存中的存储形式与整数完全不同。
  • 字符型char类型通常占1个字节,用来存储单个字符的ASCII码值。例如,字符'A'的ASCII码值是65,在内存中存储为41(十六进制)。
  int main()
{
   printf("%zd\n", sizeof(int));
   printf("%zd\n", sizeof(char));
   printf("%zd\n", sizeof(float));
   return 0;
}

在这里插入图片描述

2、数组存储

  • 数组中的元素在内存中是连续存储的。例如,int arr[5] = {1, 2, 3, 4, 5};,数组arr的5个元素在内存中依次排列,假设数组首地址为0x1000,那么arr[0]存储在0x1000处,arr[1]存储在0x1004处,以此类推,每个元素之间的偏移量为sizeof(int)
  • 在这里插入图片描述

3、结构体存储

1、基本存储规则

  • 结构体的成员在内存中是按照定义的顺序依次存储的。每个成员的存储地址相对于结构体首地址有一定的偏移量。例如,对于结构体struct Example { int a; char b; };,首先存储int型成员a,然后存储char型成员b
  • 编译器可能会在结构体成员之间插入填充字节(Padding),这是为了满足成员的对齐要求。对齐要求通常是为了提高内存访问的效率,因为大多数计算机硬件在访问内存时,对于按照一定字节对齐的数据访问速度更快。例如,在32位系统中,int类型通常要求4字节对齐,double类型要求8字节对齐等。

2、举例说明

  • 例1:简单结构体
    • 考虑结构体struct Simple { char c; int i; };。假设char类型占1个字节,int类型占4个字节。
    • 首先存储c,其地址假设为结构体首地址0x0000,占1个字节,存储范围是0x0000
    • 由于int类型要求4字节对齐,在ci之间会插入3个填充字节。i的存储起始地址为0x0004,占4个字节,存储范围是0x0004 - 0x0007。所以整个结构体Simple占8个字节。
  • 例2:包含数组的结构体
    • 定义结构体struct ArrayStruct { int a; char arr[3]; int b; };
    • 首先存储a,假设其地址为0x0000,占4个字节,存储范围是0x0000 - 0x0003
    • 接着存储arr数组,其起始地址为0x0004,因为char数组本身没有对齐要求,且前面a已经保证了4字节对齐。arr占3个字节,存储范围是0x0004 - 0x0006
    • 对于b,由于int类型要求4字节对齐,所以在arrb之间会插入1个填充字节。b的存储起始地址为0x0008,占4个字节,存储范围是0x0008 - 0x000B。整个结构体ArrayStruct占12个字节。
  • 例3:嵌套结构体
    • 定义结构体struct Inner { char c; };struct Outer { int a; struct Inner in; char b; };
    • 首先存储Outer结构体中的a,假设其地址为0x0000,占4个字节,存储范围是0x0000 - 0x0003
    • 接着存储Inner结构体中的c,由于Inner结构体是嵌套在Outer结构体中的,c的存储起始地址为0x0004,占1个字节,存储范围是0x0004
    • 对于Outer结构体中的b,因为char类型前面已经满足了4字节对齐(由于a的存储),所以b的存储起始地址为0x0005,占1个字节,存储范围是0x0005。整个Outer结构体占8个字节。

3、查看结构体大小和成员偏移量的方法

  • 在C语言中,可以使用sizeof运算符来查看结构体的大小。例如,对于上述struct Simple结构体,可以通过printf("%d", sizeof(struct Simple));来输出结构体的大小。
  • 有些编译器提供了扩展来查看结构体成员的偏移量,如在GCC中,可以使用__attribute__((packed))来取消结构体的对齐填充,使得结构体按照紧密排列的方式存储,这样可以更清楚地看到成员的原始偏移量。不过这种方式可能会影响内存访问效率,一般用于特殊的需求,如数据存储格式有严格要求的网络协议数据包的构建等。

二、大小端字节序

  • 概念
    • 大端字节序(Big-Endian):也叫大端序或大字节序,数据的高位字节存于低地址,低位字节存于高地址。例如,对于整数0x12345678,高位字节0x12存于内存低地址,接着依次是0x340x560x78存于更高地址,就像按从左到右(高位在前)的顺序存储。
    • 小端字节序(Little-Endian):又称小端序或小字节序,与大端字节序相反,数据的低位字节存于低地址,高位字节存于高地址。对于0x12345678,在小端字节序下,0x78存于内存低地址,接着是0x560x340x12存于更高地址,如同从右到左(低位在前)存储。
  • 影响:不同的字节序在多字节数据的存储和传输中会产生影响。在网络编程中,通常规定使用大端字节序进行数据传输,以保证不同主机之间数据的一致性。如果两台主机的字节序不同,在进行数据通信时就需要进行字节序的转换。

三、字节序的判断

  • 利用指针类型转换判断:通过将一个多字节数据的地址转换为char *类型指针,然后访问该指针指向的字节,根据第一个字节的值来判断字节序。例如:
#include <stdio.h>

int main() {
    int num = 1;
    char *ptr = (char *)&num;
    if (*ptr == 1) {
        printf("小端字节序\n");
    } else {
        printf("大端字节序\n");
    }
    return 0;
}
  • 利用联合体判断:联合体的所有成员共用同一块内存空间,可以利用这一特性来判断字节序。例如:
#include <stdio.h>

union EndianTest {
    int num;
    char bytes[4];
};

int main() {
    union EndianTest test;
    test.num = 1;
    if (test.bytes[0] == 1) {
        printf("小端字节序\n");
    } else {
        printf("大端字节序\n");
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2275180.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

双因素身份验证技术在NPI区域邮件安全管控上的解决思路

在制造业中&#xff0c;NPI&#xff08;New Product Introduction&#xff0c;新产品导入&#xff09;区域是指专门负责新产品从概念到市场推出全过程的部门或团队。NPI 的目标是确保新产品能够高效、高质量地投入生产&#xff0c;并顺利满足市场需求。在支撑企业持续创新和竞争…

浙江安吉成新的分布式光伏发电项目应用

摘 要&#xff1a;分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上&#xff0c;利用太阳能进行发电的一种可再生能源利用方式&#xff0c;与传统的大型集中式光伏电站相比&#xff0c;分布式光伏发电具有更灵活的布局、更低的建设成本和更高…

更新Office后,LabVIEW 可执行程序生成失败

问题描述&#xff1a; 在计算机中&#xff0c;LabVIEW 开发的源程序运行正常&#xff0c;但在生成可执行程序时提示以下错误&#xff1a; ​ A VI broke during the build process from being saved without a block diagram. Either open the build specification to include…

mysql-operator容器化部署mysql8

基础组件容器化 前一段时间容器化了容器的s3和pika。由于已经有开源方案&#xff0c;本次mysql直接以operator容器化。使用的是[presslabs的mysql-operator]https://github.com/presslabs/mysql-operator。 主要特征 presslabs/mysql-operator自动化搭建主从集群。使用XtraBack…

web-app uniapp监测屏幕大小的变化对数组一行展示数据作相应处理

web-app uniapp监测屏幕大小的变化对数组一行展示数据作相应处理 1.uni.getSystemInfoSync().screenWidth; 获取屏幕宽度 2.uni.onWindowResize&#xff08;&#xff09; 实时监测屏幕宽度变化 3.根据宽度的大小拿到每行要展示的数量itemsPerRow 4.为了确保样式能够根据 items…

[OPEN SQL] 限定选择行数

本次操作使用的数据库表为SCUSTOM&#xff0c;其字段内容如下所示 航班用户(SCUSTOM) 该数据库表中的部分值如下所示 指定查询多少行数据&#xff0c;我们可以使用语法UP TO n ROWS来实现对数据前n项的查询 语法格式 SELECT * FROM <dbtab> UP TO n ROWS 参数说明 db…

金融项目实战 02|接口测试分析、设计以及实现

目录 ⼀、接口相关理论 二、接口测试 1、待测接口&#xff1a;投资业务 2、接口测试流程 3、设计用例理论 1️⃣设计方法 2️⃣工具 4、测试点提取 5、测试用例&#xff08;只涉及了必测的&#xff09; 1️⃣注册图⽚验证码、注册短信验证码 2️⃣注册 3️⃣登录 …

74 mysql having 的实现

前言 这里 我们主要是 看一下 having 的相关实现 having 经常是配合 group by 这边进行使用, 进行一个基于 group by 之后的结果的一个, 条件限定 我们这里 以最简单的 group by having 来进行调试, 他会分为 两个阶段, 一个阶段是 group by 之后的结果输出到临时表, 另外…

Google发布图像生成新工具Whisk:无需复杂提示词,使用图像和人工智能将想法可视化并重新混合

Whisk 是 Google Labs 的一项新实验&#xff0c;可使用图像进行快速而有趣的创作过程。Whisk不会生成带有长篇详细文本提示的图像&#xff0c;而是使用图像进行提示。只需拖入图像&#xff0c;即可开始创建。 whisk总结如下&#xff1a; Whisk 是 Google 实验室最新的生成图像实…

K8s Pod OOMKilled,监控却显示内存资源并未打满

1. 问题现象 pod一直重启&#xff0c;通过grafana查看&#xff0c;发现内存使用率并没有100%。 2. 排查过程 2.1 describe查看pod最新一次的状态 可以明显看到&#xff0c;最近一次的重启就是因为内存不足导致的。 2.2 describe 查看node节点状态 找到原因了&#xff0c;原来…

33.3K 的Freqtrade:开启加密货币自动化交易之旅

“ 如何更高效、智能地进行交易成为众多投资者关注的焦点。” Freqtrade 是一款用 Python 编写的免费开源加密货币交易机器人。它就像一位不知疲倦的智能交易助手&#xff0c;能够连接到众多主流加密货币交易所&#xff0c;如 Binance、Bitmart、Bybit 等&#xff08;支…

vscode开启调试模式,结合Delve调试器调试golang项目详细步骤

1.前期准备 (1).在vs code中的扩展程序中搜索并安装Go扩展程序 (2).安装 Delve 调试器 go install github.com/go-delve/delve/cmd/dlvlatest (3).打开vs code的命令面板&#xff0c;输入Go: Install/Update Tools&#xff0c;并单击该命令执行&#xff0c;安装或更新Go语…

Postman接口测试03|执行接口测试、全局变量和环境变量、接口关联、动态参数、断言

目录 七、Postman 1、安装 2、postman的界面介绍 八、Postman执行接口测试 1、请求页签 3、响应页签 九、Postman的环境变量和全局变量 1、创建环境变量和全局变量可以解决的问题 2、postman中的操作-全局变量 1️⃣手动设置 2️⃣代码设置 3️⃣界面获取 4️⃣代…

Python Matplotlib教程-Matplotlib 多子图布局

Python Matplotlib 多子图布局 Matplotlib 是 Python 中最常用的数据可视化库&#xff0c;它提供了强大的功能来绘制不同类型的图表。在实际应用中&#xff0c;通常需要将多个图表绘制在同一个画布上&#xff0c;这就需要用到 多子图布局。本篇文章将详细介绍如何使用 Matplot…

【Java项目】基于SpringBoot的【校园新闻系统】

【Java项目】基于SpringBoot的【校园新闻系统】 技术简介&#xff1a;本系统使用采用B/S架构、Spring Boot框架、MYSQL数据库进行开发设计。 系统简介&#xff1a;主要包括二大功能模块&#xff0c;即用户功能模块和管理员功能模块。系统中的核心用户是管理员&#xff0c;管理员…

c++入门之 命名空间与输入输出

1、命名空间 1.1使用命名空间的原因 先看一个例子&#xff1a; #include <iostream>int round 0;int main() {printf("%d", round);return 0; }请问&#xff0c;这个程序能跑起来吗&#xff1f; 答案是否定的 原因是&#xff0c;当我们想创建一个全局变量 …

【网络安全渗透测试零基础入门】之XSS攻击获取用户cookie和用户密码(实战演示)

前言 大家好&#xff0c;我是demon 这是demon给粉丝盆友们整理的网络安全渗透测试入门阶段XSS攻击教程。 本阶段主要讲解XSS攻击获取用户cookie和用户密码。 喜欢的朋友们&#xff0c;记得给晓晓点赞支持和收藏一下&#xff0c;关注我&#xff0c;学习黑客技术。 简介 该…

HarmonyOS开发:ArkTS初识

ArkTS基本语法 ArkTS语言简介 ArkTS是鸿蒙生态的应用开发语言。基本语法风格与TypeScript&#xff08;简称TS&#xff09;相似&#xff0c;在TS的生态基础上进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 基本语法概述 扩展能力 基础语法&#xff1a…

【YOLOv8杂草作物目标检测】

YOLOv8杂草目标检测 算法介绍模型和数据集下载 算法介绍 YOLOv8在禾本科杂草目标检测方面有显著的应用和效果。以下是一些关键信息的总结&#xff1a; 农作物幼苗与杂草检测系统&#xff1a;基于YOLOv8深度学习框架&#xff0c;通过2822张图片训练了一个目标检测模型&#xff…

【python A* pygame 格式化 自定义起点、终点、障碍】

- pip install pygame test.py(chatgpt版本) 空格键&#xff1a;运行 A* 算法。CtrlC 键&#xff1a;清空路径。CtrlS 键&#xff1a;保存当前地图到 map.json 文件。CtrlL 键&#xff1a;从 map.json 文件加载地图。 import pygame import json from queue import PriorityQ…