【C/C++】数据在内存中的存储(完整篇非常详细)

简介: 【C/C++】数据在内存中的存储(完整篇非常详细)

C/C++是近年来最为流行的编程语言之一,应用广泛,尤其是在嵌入式、操作系统等领域。而正是由于其广泛应用,深入了解C/C++中的数据在内存中的存储方式具有重要意义。

在C/C++中,数据的存储方式主要包括两种:栈上分配和堆上分配。同时,数据也可以按照不同的类型进行存储,例如整型、字符型、指针等,这些类型在内存中占用的空间也不尽相同。

一、栈上分配

栈(Stack)是运行程序时自动分配的一段内存,用于存储临时变量、函数返回值、函数参数和函数调用的返回地址等信息。在栈上分配的内存是自动管理的,当其作用域结束时会自动释放。

在C/C++中,通过定义变量来分配栈上内存,例如:

void func() {
int a = 1; // 在栈上分配内存
char b[] = "hello world"; // 在栈上分配内存
}
c++

在上述代码中,变量a和数组b都是在栈上分配的内存。对于整型和字符型等基本类型,在栈上分配的内存大小取决于其存储范围。以32位机器为例,int类型占用4个字节,char类型占用1个字节。

在函数调用时,传递函数参数的方式和栈上分配的方式类似。函数参数也是在栈上分配的内存,其大小和类型由函数原型决定。

void func(int a, char b[]) { // a和b在栈上分配内存
...
}
c++

二、堆上分配

堆(Heap)是程序在运行时自由分配的一段内存,用于存储动态分配的数据。在堆上分配的内存需要手动管理,使用完后要及时释放。

在C/C++中,通过使用new操作符来在堆上分配内存,例如:

int* p = new int;
c++

上述代码中,通过new操作符在堆上分配了一个整型变量,并将其地址赋值给指针变量p。当不再需要使用该变量时,需要手动使用delete操作符释放内存,例如:

delete p;
c++

同时,在堆上分配数组的方式有所不同,需要使用数组形式的new操作符。例如:

int* arr = new int[10];
c++

上述代码中,通过使用数组形式的new操作符,在堆上分配了一个由10个整型变量组成的数组。同样地,当不再需要使用该数组时,需要手动使用delete[]操作符释放内存,例如:

delete[] arr;
c++

三、数据类型在内存中的存储

在C/C++中,各种数据类型在内存中存储的方式不尽相同,以下是各种数据类型在内存中存储的方式和占用空间大小:

基本数据类型

char类型:占用1个字节,存储在内存中的方式为补码形式。
short类型:占用2个字节,存储在内存中的方式为二进制补码形式。
int类型:占用4个字节,存储在内存中的方式为二进制补码形式。
long类型:占用4个字节或8个字节,存储在内存中的方式为二进制补码形式。
float类型:占用4个字节,存储在内存中的方式为IEEE754标准的32位浮点数表示法。
double类型:占用8个字节,存储在内存中的方式为IEEE754标准的64位浮点数表示法。

数组类型

数组类型在内存中的存储方式为连续存储,即数组元素在内存中的地址是连续的。例如,定义一个由n个整型变量组成的数组,其中a[0]的内存地址为p,则a[i]的内存地址为:

p + i * sizeof(int)

指针类型

指针类型在内存中的存储方式为存储被指向对象的内存地址。例如,定义一个整型指针变量,则指针变量所占用的空间为4个字节(32位机器),其中存储的是指向整型变量的地址。

结构体类型

结构体类型在内存中的存储方式为按照定义顺序依次存储各个成员变量,并按照数据类型的对齐规则进行对齐,使各个成员变量的内存地址合理

相关文章
|
4天前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
24 11
|
13天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
36 4
|
27天前
|
监控 算法 应用服务中间件
“四两拨千斤” —— 1.2MB 数据如何吃掉 10GB 内存
一个特殊请求引发服务器内存用量暴涨进而导致进程 OOM 的惨案。
|
26天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
56 1
|
1月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
1月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
5天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
27 5
|
11天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
40 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
24 4