问题描述
我正在创建一个查找表,它将使用两个键/索引来访问const char *。
例如:
const char* const arr[2][3]={
{"a","bb","ccc" },{"","","dddd"}
}
我担心的是这种表的内存使用情况,我计划制作的表的实际大小将为arr [〜60] [〜2000],其中包含大多数空元素。据我了解,这会创建一个指向const char *二维数组的常量指针。内存布局看起来如何,使用了多少内存?内存会简单地用作每个元素和每个元素内容的指针吗?
例如(包括终止符)2 * 3 * pointer_size +(2 + 3 + 4)+(1 + 1 + 5)
非常感谢您提供任何反馈意见。
侧面说明:我最初计划将unordered_map用于查找表,但是在使用一对整数作为键时,这需要创建自定义哈希。无论我当前的方法是否正确,我都想知道我上面想要做的事情的具体含义。
解决方法
如何使用内存
您永远不知道,直到程序被编译。仅检查汇编代码可能会给您任何答案。可以肯定的是,我通常在没有代码的情况下进行编译,并检查GNU size
实用程序的输出,并进行比较以查看代码片段对可执行文件的影响。
const char * const arr [] []的大小是多少?
我相信您知道答案-就像您提供的示例一样,它是sizeof(const char *) * first_dimension * second_dimension
个字节。
此的内存布局是什么样的
首先,显示的代码无效-[2][3]
数组的初始化符太多。更正错误后,即。删除不需要的初始化程序(因为我懒得再画3个框),因此内存布局可能如下所示:
const char *arr[2][3]
+-------+------+-------+------+------+------+
| 0x... | | | | | |
+-------+------+-------+------+------+------+
| | | | | |
| | | | | +----------->---+---+---+---+----+
| | | | | | d | d | d | d | \0 |
| | | | | +---+---+---+---+----+
| +---+ | +------+-+
| | | |
v---+----+ | +---->---+---+---v----+
| a | \0 | | | c | c | c | \0 |
+---+----+ | +---+---+---+----+
|
+-->---+---+----+
| b | b | \0 |
+---+---+----+
每个框代表一个元素,const char *arr[2][3]
下方的每个框代表一个const char *
指针,而在其他所有位置,每个框代表一个char
字节。请注意,我在arr[1][0]
的NUL字节上绘制了arr[1][1]
和"ccc"
-编译器可能会优化并合并多个字符串文字。编译器也可能不会这样做-如上所述,仅检查生成的程序集会知道到底发生了什么。
请注意,如果数组不是可变的,则最好将其设置为const
。在为裸机控制器进行编译时执行const char *const arr[2][3]
,这将允许编译器将整个阵列放置在闪存中,从而减少初始化bss
和ram的使用。字符串文字应该放在只读部分,因为它们是不可变的。在c ++中,您还可以根据需要考虑添加constexpr
(或consteval
)。
但是,直到您检查装配时,您才知道。如果将arr
的定义放在函数内,则编译器可能会决定在进入函数godbolt example时在堆栈上重新创建整个数组(还包括字符串文字)。不同的编译器优化选项起作用。
仅将内存用作指向每个元素和每个元素内容的指针吗?
好吧,通常是。