【问题标题】:How to get the memory size of an array of strings?如何获取字符串数组的内存大小?
【发布时间】:2017-11-09 15:39:01
【问题描述】:

我会尝试用一个例子来解释:

假设我想创建一个固定数字 3 的消息列表。

char* p_msglist[3];

此列表中的每条消息都应以固定大小存储(例如 16 个字符,因此每条消息在内存中保存 16 个字节,总共 48 个字节)。

char msg[16] = "first message";
char msg2[16] = "second message";
char msg3[16] = "third message";

在列表中指向这些消息中的每一个后,我打印了sizeof第一条消息和列表:

p_msglist[0] = msg;
p_msglist[1] = msg2;
p_msglist[2] = msg3;
printf("%lu\n", sizeof(msg));
printf("%lu\n", sizeof(p_msglist));

输出:

16  //size of msg is ok. 
24

我知道一个 char 指针 包含 8 个字节,我们的消息列表用 3 个元素初始化,最后一行打印出 24。我想问:

  • 有没有办法让我的列表包含3*16=48 字节。试图问:我可以确定我的列表在内存中包含 48 个字节吗?

  • 如果我想分配内存(malloc 等),我应该关心列表的指针和列表本身(24 字节 + 48 字节)吗?

提前致谢。

【问题讨论】:

  • 如果存储在p_msglist 中的指针的目标总是与p_msglist 相关联并且总是16 个字节,那么您可能需要一个多维数组(char p_msglist[3][16];)而不是一个指针数组。指针数组不关心它指向什么或谁管理该存储。
  • “我知道一个 char 指针包含 8 个字节”不,char * 可能是 8 个字节。它也经常是 4 个字节。或者它可以完全是别的东西。
  • 是的,我也知道 :) 我的意思是,就我而言,它是 8 个字节。但你是对的,我应该写那个。

标签: c arrays memory


【解决方案1】:

第一个问题的答案是否定的。您无法从指针本身获取大小。

这取决于:-

  1. 如果你想分配那些char*,那么你需要考虑。

  2. 如果您确定拥有 3 个char* 就足够了,那么您无需考虑no

但在这两种情况下,您都需要分配内存来存储字符串。例如,您将在此处分配用于存储 16 个字符的空间。

(或简单地将其分配给某个字符串文字)。

【讨论】:

    【解决方案2】:

    您对指针数组的工作方式有一个非常基本的误解。它持有指向内存的指针,而不是内存本身。 (它不能这样做,因为在您声明 p_msglist 时,消息的大小还不知道。)

    char* p_msglist[3];
    

    这是一个由三个指针组成的数组。这些指针中的每一个都表示一个地址。地址通常(但不是在每个硬件上)都是 32 位或 64 位大的;分别是 4 或 8 个字节。

    您正在使用 64 位机器,因此您的三个指针数组是 3 x 8 = 24 字节。

    现在进入重点:

    三个指针中的每一个都可以指向不同的地址。 没有必要也不能保证你的三个消息在内存中甚至彼此靠近。指向消息的内存包含在sizeof p_msglist 中——也不应该,真的。

    如果你想malloc 整个p_msglist 的内存消息,你必须:

    • p_msglist分配24个字节;那么
    • 分别为每条消息分配 16 个字节,并将该消息的地址分别存储在 p_msglist 的元素中

    当再次释放内存时,您必须在每条消息上调用free()(即free( p_msglist[0] )free( p_msglist[1] )free( p_msglist[2] )),free( p_msglist )本身。 (重要提示:首先释放消息,然后释放数组。反之则为未定义行为。)

    如果要确保消息在内存中是连续的,则需要为消息分配 3 * 16 = 48 个字节(假设将其存储在 msg_mem 中),并将 msg_mem 存储在 @987654335 中@,将msg_mem + 16 存储在p_msglist[1] 中,并将msg_mem + 32 存储在p_msglist[2] 中。

    当释放那个时,你不能在单个消息上调用free(),只能在p_msglist[0](和p_msglist,如果你为此分配了内存)动态)。您只能在之前从分配函数之一获得的相同地址上调用 free()

    如果您希望消息 p_msglist 在连续和分配的内存中,则必须分配 48 + 24 = 72 字节的内存 (sizeof( p_msglist ) + sizeof( msg ) + sizeof( msg2 ) + sizeof( msg3 ))... 和当然仅限之后free( p_msglist )


    如果你不想malloc内存并且仍然希望内存在一个块中,你可以声明...

    char p_msglist[3][16] = { { "first message" }, { "second message" }, { "third message" } };
    

    这将分配一个 3 x 16 字符的二维数组,并按指示初始化它们。然而,这当然只是一个 local 对象,它像任何其他局部变量一样超出范围(与动态分配的内存相反,它在free()d 之前一直有效)。

    关于后一种构造的“有趣”之处在于,因为 p_msglist 是一个“直接”二维数组,而不是保存三个指向 individual 数组的指针,所以 sizeof p_msglist 在这种情况下是,实际上,3 x 16 = 48...

    【讨论】:

    • 感谢您的解释性回答:)
    • @ErselEr:我清楚地记得在我“得到”指针之前我必须让自己经历的精神扭曲,那时在原始时代......我知道如果你不这样做会多么令人困惑有人让你走上正轨,给你一点推动力。 ;-)
    • 是的,你是对的。再次感谢 :) 顺便说一句,我刚刚开始积极使用 stackoverflow,非常感谢你
    猜你喜欢
    • 2013-09-14
    • 1970-01-01
    • 2015-11-27
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    相关资源
    最近更新 更多