面经--C语言——sizeof和strlen,数组和链表,#include <>和 #include ““ #define 和typedef 内存对齐概述
文章目录
- `sizeof` 和 `strlen`
- 数组和链表
- 总结
- #include <>和 #include ""
- #define 和typedef
- 内存对齐概述
- 对齐规则
- 示例:结构体的内存对齐
- 分析:
- 内存对齐的常见规则:
- 填充字节的计算
- 对齐影响的实际例子
sizeof 和 strlen
| 特性 | sizeof | strlen |
|---|---|---|
| 定义 | 运算符,也是关键字,用于获取类型或变量所占的字节数 | 函数,用于计算 C 风格字符串的长度(不包括 '\0') |
| 用途 | 返回对象或数据类型在内存中占用的字节数 | 返回 C 风格字符串的字符数量(不包括 '\0') |
| 计算方式 | 在编译时确定,求值过程是静态的 | 在运行时计算,需遍历字符串逐字符计数 |
| 适用类型 | 适用于所有类型,包括数组、结构体、指针、基本数据类型等 | 仅适用于 C 风格字符串(以 '\0' 结尾的字符数组) |
| 返回值 | 返回的是字节数,通常是 size_t 类型 | 返回字符串中字符的数量,不包括 '\0' 字符 |
| 操作对象 | 数据类型、变量、数组、结构体等 | C 风格字符串(const char* 或 char[]) |
是否包括 '\0' | 包括 '\0'(例如对字符数组使用 sizeof 会计算整个数组大小) | 不包括 '\0'(只计算实际字符数) |
| 适用场景 | 获取类型或数组的内存大小,计算静态数据结构的大小 | 获取字符串的实际长度(不包括结束符 '\0') |
| 示例代码 | sizeof(int) 返回 4(通常情况下) | strlen("Hello") 返回 5 |
| 计算复杂度 | 常数时间复杂度,编译时计算 | 线性时间复杂度,需要遍历整个字符串 |
数组和链表
| 特性 | 数组 | 链表 |
|---|---|---|
| 定义 | 数组是一种线性数据结构,它包含固定大小的连续元素 | 链表是一种线性数据结构,它由节点组成,每个节点包含数据和指向下一个节点的指针 |
| 内存结构 | 在内存中分配一个连续的块 | 每个节点在内存中不一定是连续的,节点通过指针连接 |
| 存储方式 | 静态存储方式(大小固定) | 动态存储方式(可以动态增加或删除节点) |
| 元素类型 | 所有元素类型相同(通常是基本数据类型) | 每个节点可以存储不同类型的数据,节点可以包含不同的结构 |
| 访问方式 | 通过索引直接访问元素,时间复杂度为 O(1) | 通过指针遍历,每次只能访问当前节点,时间复杂度为 O(n) |
| 插入与删除 | 插入或删除元素时需要移动元素,时间复杂度为 O(n) | 插入和删除操作在头部和尾部的时间复杂度为 O(1),在中间位置为 O(n) |
| 内存分配 | 在定义数组时就分配固定大小的内存 | 节点可以在运行时动态分配和释放内存 |
| 大小变动 | 大小固定,无法在运行时调整 | 可以动态增减节点,大小可以灵活变化 |
| 内存浪费 | 如果数组大小过大,可能会浪费内存 | 如果链表很长且有很多空节点,可能会浪费指针的内存 |
| 优缺点 | 优:访问快速;缺:插入和删除操作不灵活 | 优:插入和删除操作灵活;缺:访问速度较慢 |
总结
- 数组 是一种高效的、固定大小的线性数据结构,适合需要快速访问的场景,但它不适合频繁的插入和删除操作。
- 链表 适合需要频繁动态插入和删除的场景,尽管它的访问速度较慢,但它提供了更大的灵活性,尤其在内存使用方面。
#include <>和 #include “”
| 特性 | #include <> | #include "" |
|---|---|---|
| 用途 | 用于包含系统或标准库的头文件 | 用于包含用户定义的头文件或当前目录下的头文件 |
| 查找顺序 | 编译器首先查找标准库路径中的头文件 | 编译器首先查找当前目录中的头文件,若找不到,再查找标准库路径 |
| 适用场景 | 用于包含标准库或第三方库的头文件(如 #include <iostream>) | 用于包含项目中的自定义头文件(如 #include "myheader.h") |
#define 和typedef
#define 和 typedef 都是 C/C++ 中常用的预处理指令和关键字,主要用于定义常量、宏和类型别名。它们有不同的功能和使用方式,下面是详细的比较:
| 特性 | #define | typedef |
|---|---|---|
| 用途 | 用于定义宏(常量、函数、代码片段) | 用于定义类型别名(为现有类型起别名) |
| 作用范围 | 在宏定义之后,它的作用范围是整个文件 | 在定义之后,它的作用范围通常是当前作用域或文件 |
| 类型检查 | 不进行类型检查,纯粹的文本替换 | 进行类型检查,确保新类型的合法性 |
| 宏定义的作用 | 定义常量、简单函数或复杂的代码块 | 不支持宏功能,只有类型别名 |
| 宏展开时机 | 宏在预处理阶段展开(编译前) | typedef 只是定义别名,不会进行宏展开 |
| 调试支持 | 宏没有调试信息(因为宏只是简单的文本替换) | typedef 可以像普通类型一样调试 |
| 示例 | #define PI 3.14 | typedef int Integer; |
内存对齐概述
内存对齐(Memory Alignment)是计算机体系结构中对数据存储方式的一种要求,它规定了数据类型的存储地址必须是某个特定值的倍数。
在现代计算机中,通常要求数据按照一定的对齐方式存储,例如 4 字节对齐、8 字节对齐等。对齐通常会影响结构体和数组的内存布局,从而决定其内存占用的大小。
对齐规则
-
基本对齐规则:
- 每个数据类型的存储地址应当是该数据类型大小的倍数。例如:
char类型通常是 1 字节,通常可以存储在任何地址。int类型通常是 4 字节,存储地址必须是 4 的倍数。double类型通常是 8 字节,存储地址必须是 8 的倍数。
- 每个数据类型的存储地址应当是该数据类型大小的倍数。例如:
-
结构体对齐:
- 对结构体中的成员进行对齐时,结构体的总大小将是最大成员对齐要求的倍数。
- 结构体中每个成员的起始地址需要满足其对齐要求。如果某个成员的起始地址不符合其对齐要求,编译器会在它和下一个成员之间插入填充字节(padding bytes)来保证对齐。
-
结构体总大小:
- 结构体的总大小应该是最大对齐要求的倍数。如果结构体中的成员总和大小不满足最大对齐要求,编译器会在结构体末尾添加填充字节,以使结构体的总大小是对齐要求的倍数。
示例:结构体的内存对齐
考虑以下代码:
#include <stdio.h>typedef struct {char c; // 1 字节int i; // 4 字节double d; // 8 字节
} Example;
分析:
char c占 1 字节。int i占 4 字节。double d占 8 字节。
在 Example 结构体中:
char c需要 1 字节,但是由于int需要 4 字节对齐,编译器会在char c后插入 3 个填充字节,使int i能够正确地以 4 字节对齐。int i占 4 字节,按照 4 字节对齐。double d占 8 字节,按照 8 字节对齐。- 结构体的总大小应是 8 的倍数(由于
double的 8 字节对齐要求)。因此,结构体的总大小会扩展到 24 字节(1 + 3 + 4 + 8 + 8 的填充)。
结果:该结构体的大小是 24 字节,而不是成员大小的总和 13 字节。
内存对齐的常见规则:
| 数据类型 | 对齐方式 | 描述 |
|---|---|---|
char | 1 字节 | char 类型的对齐方式为 1 字节。 |
short | 2 字节 | short 类型的对齐方式为 2 字节。 |
int | 4 字节 | int 类型的对齐方式为 4 字节。 |
float | 4 字节 | float 类型的对齐方式为 4 字节。 |
double | 8 字节 | double 类型的对齐方式为 8 字节。 |
long | 4 字节或8字节 | long 类型的对齐方式依赖于系统架构。 |
long long | 8 字节 | long long 类型的对齐方式为 8 字节。 |
填充字节的计算
考虑以下结构体定义:
typedef struct {char c; // 1 字节int i; // 4 字节
} MyStruct;
-
char c占 1 字节,紧接着是int i,但是int类型要求 4 字节对齐。因此,编译器会在char后插入 3 个填充字节,使int的起始地址是 4 的倍数。 -
所以,
int i占 4 字节,整个结构体的大小需要为 4 字节对齐。因此,结构体的总大小将是 8 字节。
对齐影响的实际例子
#include <stdio.h>typedef struct {char c;int i;double d;
} Example;int main() {printf("Size of Example: %zu\n", sizeof(Example));return 0;
}
假设:
char c占 1 字节。int i占 4 字节(要求 4 字节对齐)。double d占 8 字节(要求 8 字节对齐)。
计算结构体内存:
char c占 1 字节。- 插入 3 字节填充,使
int i能够 4 字节对齐。 int i占 4 字节。double d占 8 字节,且由于对齐要求,double的起始地址必须是 8 的倍数。- 结构体的总大小会被扩展到 16 字节,以满足 8 字节对齐。
输出结果:
Size of Example: 16
以最大类型所占内存分配内存空间。
相关文章:
面经--C语言——sizeof和strlen,数组和链表,#include <>和 #include ““ #define 和typedef 内存对齐概述
文章目录 sizeof 和 strlen数组和链表总结 #include <>和 #include ""#define 和typedef内存对齐概述对齐规则示例:结构体的内存对齐分析: 内存对齐的常见规则:填充字节的计算对齐影响的实际例子 sizeof 和 strlen 特性size…...
使用 Kotlin 将 Vertx 和 Springboot 整合
本篇文章目的是将 Springboot 和 Vertx 进行简单整合。整合目的仅仅是为了整活,因为两个不同的东西整合在一起提升的性能并没有只使用 Vertx 性能高,因此追求高性能的话这是在我来说不推荐。而且他们不仅没有提高很多性能甚至增加了学习成本 一、整合流…...
线性回归算法-01
线性回归简介 学习目标 了解线性回归的应用场景知道线性回归的定义 1 线性回归应用场景 房价预测销售额度预测贷款额度预测 2 什么是线性回归 2.1 定义与公式 线性回归(Linear regression)是利用 回归方程(函数)对 一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模…...
洛谷 P1130 红牌 C语言
题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂,一共包括 N 个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程,每一步政府都派了 M 个工作人员来检查材料。不幸的是&…...
虚幻UE5手机安卓Android Studio开发设置2025
一、下载Android Studio历史版本 步骤1:虚幻4.27、5.0、5.1、5.2官方要求Andrd Studio 4.0版本; 5.3、5.4、5.5官方要求的版本为Android Studio Flamingo | 2022.2.1 Patch 2 May 24, 2023 虚幻官网查看对应Andrd Studiob下载版本: https:/…...
线性代数复习笔记
1. 课程学习 1.1 3Blue1Brown 线性代数 2. 基本术语 eigenvector(特征向量):线性变换中方向保持不变的向量 可以视作3D旋转矩阵形成的旋转的轴...
你需要更深层次的解放
先谈一谈理性认知中的属性替换原则。简单来说,属性替换就是用简单的问题取代难题。 当人们需要评估属性A时,却发现评估属性B更容易一些(A与B之间存在一定的关系),于是就改为评估属性B。这叫做属性替换。 作为一种认知…...
机器学习算法在网络安全中的实践
机器学习算法在网络安全中的实践 本文将深入探讨机器学习算法在网络安全领域的应用实践,包括基本概念、常见算法及其应用案例,从而帮助程序员更好地理解和应用这一领域的技术。"> 序言 网络安全一直是信息技术领域的重要议题,随着互联…...
Qt事件处理:理解处理器、过滤器与事件系统
1. 事件 事件 是一个描述应用程序中、发生的某些事情的对象。 在 Qt 中,所有事件都继承自 QEvent ,并且每个事件都有特定的标识符,如:Qt::MouseButtonPress 代表鼠标按下事件。 每个事件对象包含该事件的所有相关信息ÿ…...
DeepSeek相关技术整理
相关介绍 2024年12月26日,DeepSeek V3模型发布(用更低的训练成本,训练出更好的效果)671B参数,激活37B。2025年1月20日,DeepSeek-R1模型发布(仅需少量标注数据(高质量长cotÿ…...
DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”
当算力博弈升级为网络战争:拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下,网络已然成为人类社会运转的关键基础设施,深刻融入经济、生活、政务等各个领域。从金融交易的实时清算…...
蓝桥杯之c++入门(二)【输入输出(上)】
目录 前言1.getchar和 putchar1.1 getchar()1.2 putchar() 2.scanf和 printf2.1 printf2.1.1基本用法2.1.2占位符2.1.3格式化输出2.1.3.1 限定宽度2.1.3.2 限定小数位数 2.2 scanf2.2.1基本用法2.2.2 占位符2.2.3 scanf的返回值 2.3练习练习1:…...
消息队列应用示例MessageQueues-STM32CubeMX-FreeRTOS《嵌入式系统设计》P343-P347
消息队列 使用信号量、事件标志组和线标志进行任务同步时,只能提供同步的时刻信息,无法在任务之间进行数据传输。要实现任务间的数据传输,一般使用两种方式: 1. 全局变量 在 RTOS 中使用全局变量时,必须保证每个任务…...
算法题(55):用最少数量的箭引爆气球
审题: 本题需要我们找到最少需要的箭数,并返回 思路: 首先我们需要把本题描述的问题理解准确 (1)arrow从x轴任一点垂直射出 (2)一旦射出,无限前进 也就是说如果气球有公共区域(交集&…...
谭浩强C语言程序设计(4) 8章(下)
1、输入三个字符串按照字母顺序从小到大输出 #include <cstdio> // 包含cstdio头文件,用于输入输出函数 #include <cstring> // 包含cstring头文件,用于字符串处理函数#define N 20 // 定义字符串的最大长度为20// 函数:…...
AlexNet论文代码阅读
论文标题: ImageNet Classification with Deep Convolutional Neural Networks 论文链接: https://volctracer.com/w/BX18q92F 代码链接: https://github.com/dansuh17/alexnet-pytorch 内容概述 训练了一个大型的深度卷积神经网络…...
62.病毒在封闭空间中的传播时间|Marscode AI刷题
1.题目 问题描述 在一个封闭的房间里摆满了座位,每个座位东西向和南北向都有固定 1 米的间隔。座位上坐满了人,坐着的人可能带了口罩,也可能没有带口罩。我们已经知道房间里的某个人已经感染了病毒,病毒的传播速度是每秒钟感染距…...
Elixir语言的安全开发
Elixir语言的安全开发 引言 在当今这个互联网高度发展的时代,软件的安全性变得越来越重要。随着网络攻击的增多,软件漏洞的频繁暴露,开发者面临着前所未有的安全挑战。Elixir,作为一种现代化的函数式编程语言,以其高…...
Rust 条件语句
Rust 条件语句 在编程语言中,条件语句是进行决策和实现分支逻辑的关键。Rust 语言作为一门系统编程语言,其条件语句的使用同样至关重要。本文将详细介绍 Rust 中的条件语句,包括其基本用法、常见场景以及如何避免常见错误。 基本用法 Rust…...
小红的合数寻找
A-小红的合数寻找_牛客周赛 Round 79 题目描述 小红拿到了一个正整数 x,她希望你在 [x,2x] 区间内找到一个合数,你能帮帮她吗? 一个数为合数,当且仅当这个数是大于1的整数,并且不是质数。 输入描述 在一行上输入一…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
