【C语言进阶】内存函数和结构体内存对齐

news2025/1/17 13:57:06

目录

  • 一.strerror函数
      • 1.错误码变量errno
      • 2.strerror函数的使用
      • 3.perror函数
    • 二.memcpy函数
        • 1.函数介绍
        • 2.模拟实现
      • 三.memmove函数
          • 1.函数介绍
          • 2.模拟实现
        • 四.结构体的内存对齐

一.strerror函数

1.错误码变量errno

规定:
C语言库函数如果出现运行错误,会将对应错误信息的错误码保存到全局变量errno(头文件为errno.h)中.

2.strerror函数的使用

我们先来看strerror函数的原型:

char *strerror( int errnum );

向函数传入错误代码,他可以将错误码翻译为错误信息并将信息字符串的首元素地址返回
这里我们引入文件管理的函数来演示strerror函数的效果:

FILE *fopen( const char *filename, const char *mode );

如果打开文件成功则返回有效的指针,否则返回空指针。
演示代码如下:

#include <errno.h>

int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");//只读文件
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	fclose(pf);//关闭文件
	return 0;
}

在我创建的项目下并没有test.txt,这个错误会转换为错误码并且存在errno变量中,strerror函数则可以解析这个错误码。
打印结果如下:
在这里插入图片描述

3.perror函数

除strerror函数外还要介绍一个函数:perror直接打印错误信息,打印之前会先打印自定义信息(头文件stdio)。
对比上文:

int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	fclose(pf);

	return 0;
}

在这里插入图片描述

二.memcpy函数

1.函数介绍

在之前我们学习过strcpy和strncpy函数,他们是专门针对字符串拷贝的函数。而其他类型则不能使用,为了能够拷贝多种数据类型,C语言有这样的内存函数memcpy,memcpy函数则是以字节为单位拷贝数据。
函数原型:

void *memcpy( void *dest, const void *src, size_t count );

注意事项:

  1. 函数memcpy从src的位置开始向后复制count个字节的数据到dest的内存位置.
  2. 这个函数在遇到 ‘\0’ 的时候并不会停下来。(因为不是字符串函数)。
  3. 如果dest和src有任何的重叠,则可能会出现错误。

2.模拟实现

void* my_memcpy(void* p1, const void* p2, size_t num)
{
	assert(p1 && p2);
	void* ret = p1;
	while (num--)
	{
		*(char*)p1 = *(char*)p2;
		p1 = (char*)p1 + 1;
		p2 = (char*)p2 + 1;
	}
}

int main()
{
	int arr1[] = { 1,2,9,4,8 };
	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, 12);
	return 0;
}

三.memmove函数

1.函数介绍

函数原型

void *memmove( void *dest, const void *src, size_t count );

注意事项

  1. 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  2. 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
2.模拟实现
void* my_memmove(void* p1, const void* p2, size_t num)
{
	void* ret = p1;
	if (p2 > p1)//前--->后
	{
		while (num--)
		{
			*(char*)p1 = *(char*)p2;
			p1 = (char*)p1 + 1;
			p2 = (char*)p2 + 1;
		}
	}
	else//后--->前
	{
		while (num--)
		{
			*((char*)p1 + num) = *((char*)p2 + num);
		}
	}
	return ret;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9};
	int arr2[20] = { 0 };
	my_memmove(arr1, arr1 + 2, 16);
	return 0;
}

四.结构体的内存对齐

讲解内存对齐之前我们先看一个小问题:

#include <stdio.h>

 struct AB{
	int a;
	char b;
	short c;
	short d;
};

int main()
{
	printf("%d\n", sizeof(struct AB));
	return 0;
}

上面的代码结果是多少,很多人会这样算:4+1+2+2=9.
但是其实结果是:
在这里插入图片描述

这里就需要学习关于结构体的内存对齐问题,结构体在内存的存储并不是想数组那样连续的内存存放。而是与编译环境的对齐数有关而且结构体在内存中的存放有偏移量的概念偏移量从起始地址开始从0开始一字节加一
有如下规定:

  1. 结构体的第一个成员,对齐到结构体在内存中存放位置的0偏移处
  2. 从从第二个成员开始,每个成员都要对齐到(一个对齐数) 的整数倍处对齐数: 结构体成员自身大小和默认对齐数的较小值默认对齐
  3. 结构体的总大小,必须是所有成员的对齐数中最大对齐数的整数倍
  4. 如果结构体中嵌套了结构体成员,要将嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处。结构体的总大小必须是最大对齐数整数倍,这里的最大对齐数是: 包含嵌套结构体成员中的对齐数,的所有对齐数中的最大值。

举几个例子:

eg1:对齐数为4的环境下:
在这里插入图片描述
eg2:对齐数为8的环境下:
在这里插入图片描述

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

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

相关文章

联邦学习 (FL) 中常见的3种模型聚合方法的 Tensorflow 示例

联合学习 (FL) 是一种出色的 ML 方法&#xff0c;它使多个设备&#xff08;例如物联网 (IoT) 设备&#xff09;或计算机能够在模型训练完成时进行协作&#xff0c;而无需共享它们的数据。 “客户端”是 FL 中使用的计算机和设备&#xff0c;它们可以彼此完全分离并且拥有各自不…

基于Java springmvc+mybatis酒店信息管理系统设计和实现

基于Java springmvcmybatis酒店信息管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取…

程序员接私活的几个平台和建议,避免掉坑!

大家对于程序员接私活这件事的看法&#xff0c;褒贬不一。但是你如果确实用钱&#xff0c;价格又合适&#xff0c;那就大胆去接。 如果不那么缺钱&#xff0c;那么接私活之前先考虑清楚&#xff0c;如果自己将空余时间用在接私活所产生的价值是不是大于提升自己。如果是的话&a…

2022年 大学生工程训练比赛[物料搬运]

本人和团结参加了2022年大学生工程训练(简称工训赛)校赛选拔&#xff0c;准备了几个月的时间和花费了较多的资金&#xff0c;由于疫情等多种情况&#xff0c;很遗憾未能参加湖南省省赛&#xff0c;过了这么久还是写个博客记录参赛准备和调试过程。 目录 一、比赛要求 二、整体…

第十章面向对象编程(高级部分)

10.1 类变量和类方法&#xff08;关键字static&#xff09; 10.1.31类变量快速入门 思考: 如果,设计一个 int count 表示总人数,我们在创建一个小孩时&#xff0c;就把 count 加 1,并且 count 是所有对象共享的就 ok 了! package com.hspedu.static_;public class ChildGame {…

MS【1】:Metric

文章目录前言1. Dice Loss1.1. Dice coefficient1.2. F1 score - Dice1.3. Dice Loss2. Sensitivity & Specificity2.1. Sensitivity2.2. Specificity3. Hausdorff distance3.1. 概念3.2. 单向 Hausdorff distance3.3. 双向 Hausdorff distance3.4. 部分 Hausdorff distanc…

使用ResNet18实现CIFAR100数据集的训练

如果对你有用的话&#xff0c;希望能够点赞支持一下&#xff0c;这样我就能有更多的动力更新更多的学习笔记了。&#x1f604;&#x1f604; 使用ResNet进行CIFAR-10数据集进行测试&#xff0c;这里使用的是将CIFAR-10数据集的分辨率扩大到32X32&#xff0c;因为算力相关的…

二、数据仓库模型设计

数据仓库模型设计一、数据模型二、关系模型三、维度模型1、事实表&#xff08;1&#xff09;事务事实表&#xff08;2&#xff09;周期快照事实表&#xff08;3&#xff09;累计快照事实表&#xff08;4&#xff09;无事实的事实表2、维度表3、维度模型类型&#xff08;1&#…

LVGL学习笔记16 - 进度条Bar

目录 1. Parts 2. 模式 2.1 LV_BAR_MODE_SYMMETRICAL&#xff1a;对称模式 2.2 LV_BAR_MODE_RANGE&#xff1a;范围模式 3. 动画 4. 样式 4.1 方向 4.2 渐变色 4.3 增加边框 4.4 滚动条方向 进度条有一个背景和一个指示器组成&#xff0c;通过lv_bar_create创建对象。…

mysql多表查询

一、关联查询&#xff08;联合查询&#xff09; 1.1 什么是关联查询 关联查询&#xff1a;两个或者多个表&#xff0c;一起查询。 前提条件&#xff1a; 这些一起查询的表之间是有关系的&#xff08;一对一、一对多&#xff09;&#xff0c;它们之间一定是有关联字段&#x…

初识IL2CPP

在Unity中进行打包时&#xff0c;有两种打包方式选择&#xff1a;Mono和IL2CPP Mono和IL2Cpp是Unity的脚本后处理方式,通过脚本后处理实现Unity的跨平台 1.Mono (1). Mono组成组件&#xff1a; C#编辑器&#xff0c;CLI虚拟机&#xff0c;以及核心类别程序库 (2).跨平台过程 Mo…

【Linux】多线程概念

目录&#x1f308;前言&#x1f338;1、Linux线程概念&#x1f361;1.1、概念&#x1f362;1.2、线程的优点&#x1f367;1.3、线程的缺点&#x1f368;1.4、线程的异常和用途&#x1f33a;2、Linux下进程 vs 线程&#x1f308;前言 这篇文章给大家带来线程的学习&#xff01;…

PID算法入门(一)

&#xff11;.简介 PID是Proportional(比例), Integral(积分), Differential(微分)的首字母缩写,他是一种结合比例,积分,微分三个环节于一体的闭环控制算法. &#xff12;.PID各环节 &#xff12;.&#xff11;比例环节 成比例地反应控制系统的偏差信号&#xff0c;即输出&a…

Codeforces Round #843 (Div. 2) A1 —— D

题目地址&#xff1a;Dashboard - Codeforces Round #843 (Div. 2) - Codeforces一个不知名大学生&#xff0c;江湖人称菜狗 original author: jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2023.1.11 Last edited: 2023.1.11 目录 ​编辑 A1. Gardener…

读论文——day61 目标检测模型的决策依据与可信度分析

目标检测模型的决策依据与可信度分析本文贡献及原文1 相关工作&#xff08;略看&#xff09;1.3 目标检测模型2 背景知识&#xff08;LIME&#xff09;2.2 LIME3 目标检测决策依据及可信度分析3.1 决策依据3.2 对目标检测模型的预测进行可信度评价4 基于 LIME 的目标检测模型解…

(第四章)OpenGL超级宝典学习:必要的数学知识

必要的数学知识 前言 在本章当中&#xff0c;作者着重介绍了几个和3D图形学重要的数学知识&#xff0c;线性代数基础好的同学可以直接绕过本章&#xff0c;说实话这篇博客写到这里&#xff0c;我是非常犹豫的&#xff0c;本章节的内容可以说是很基础&#xff0c;但是相当…

SSM框架01_Spring

有一个效应叫知识诅咒&#xff1a;自己一旦知道了某事&#xff0c;就无法想象这件事在未知者眼中的样子。00-Spring课程介绍01-初识Spring今天所学的Spring其实是Spring家族中的Spring Framework;Spring Fra是Spring家族中其他框架的底层基础&#xff0c;学好Spring可以为其他S…

Morse1题解

原理摩尔斯电码和电报简单说一下电报和摩尔斯电码的原理最简单的电报模型就是一个电源&#xff0c;一个开关和一个电磁铁当需要长距离使用时候&#xff0c;需要用到继电器按下开关&#xff0c;电磁铁会吸引磁铁长按开关&#xff0c;电磁铁就会闭合一段时间&#xff0c;留下一划…

Jenkins集成GitLab Webhooks自动化构建

JenkinsGitLab Webhooks自动构建项目1 构建步骤1.1 Jenkins中设置构建触发器1.2 Build Authorization Token Root插件安装1.3 GitLab配置Webhooks2 测试webhooks2.1 测试推送事件2.2 测试合并请求事件2.3 代码修改提交测试1 构建步骤 1.1 Jenkins中设置构建触发器 这里先随便写…

Markdown与DITA比较

Markdown是一种轻量级标记语言&#xff0c;创始人为John Gruber。它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成有效的HTML文档。这种语言吸收了很多在电子邮件中已有的纯文本标记的特性。由于Markdown的轻量化、易读易写特性&#xff0c;并且对于图片&am…