[英]Pointer array to (with pointer array defined) strings: Are the strings stored sequential in memory?
我想知道字符串是如何存儲在 memory 中的,當使用/通過指向它們的指針數組定義它們時。
例如:
char *pa[] = { "Hello World!", "foo","bar","huhu","Let´s talk about that" };
字符串(或更好:它們的字符)是否按順序存儲在 memory 中,一個接一個?
例如,在這種情況下:
第二個字符串"foo"
的第一個字符字節f
直接存儲在第一個字符串"Hello World!"
的\0
-Null 字符之后的字節內。 .
或者
存儲在 memory 中的字符串是否分開存儲?例如:
\0
- 第一個字符串"Hello World!"
的空字符 - 第二個字符串"foo"
的f
字符之間的字節序列?
或者
即便如此,存儲是否取決於情況、編譯器、平台等,並且一次是直接順序的,一次不是?
是否還會發生,第二個字符串"foo"
的第一個字符f
直接存儲在第一個字符串"Hello World!"
的\0
字符之后。 ,這意味着它們是按順序存儲的,並且在第二個字符串"foo"
的\0
字符和第三個字符串"bar"
的第一個字符之間,即b
是字符串組非附屬字節的間隙,依賴於編譯器、平台等?
問題是針對 C 和 C++ 的,因為我同時使用兩者。 如果這兩者之間的答案發生變化,請說明重點關注哪種語言。
希望你能明白,我的意思。 非常感謝您的任何回答。
不,你不能假設任何事情。 它們是否存儲在連續的 memory 中由實現定義。
如果您真的希望字符串是那樣的,請嘗試
const char *base = "hello\0foo\0bar";
const char *hello = base;
const char *foo = base + 6; // hello + strlen(hello) + 1
const char *bar = base + 10; // foo + strlen(foo) + 1
或者,正如@SteveSummit 建議的那樣
const char *pa[] = { base, base + 6, base + 10 };
此外,如果你有
char *pa[] = { "testing", "testing", "more testing" };
編譯器可以只存儲字符串"testing"
的一份副本,並從pa[0]
和pa[1]
指向它。 (事實上,我只是用兩個現代編譯器嘗試過,它們都做到了。)
從理論上講,一個非常聰明的編譯器可以只存儲字符串"more testing"
並讓pa[0]
和pa[1]
指向它的中間。
我假設您是出於好奇而詢問,但如果您有任何機會考慮編寫代碼,該代碼以某種方式依賴於 memory 中字符串常量的順序,那么直接而簡單的答案是:不要。
Steve Summit 的回答是:如果存儲了多個字符串,它們可以按任何順序排列,也可以彼此相距很遠。
此外,使用“>”、“>=”等比較指向這些字符串的指針是未定義的行為。 因此,您可以檢查例如 p1 = "testing"、p2 = "testing"、p2 == p1 + 8 是否(在沒有任何保證的情況下會產生 0 或 1),但不能檢查 p2 >= p1 + 8 是否。
正如其他人提到的,memory 布局是實現定義的。
擴展pmg的方法並做 C 你可以這樣做:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
char ** create_pointer_array_pointing_to_sequential_data(char ** ppa)
{
char ** result = NULL;
if (NULL == ppa)
{
errno = EINVAL;
}
else
{
size_t s = 0;
size_t l = 0;
while (NULL != ppa[l])
{
s += strlen(ppa[l]);
++l;
}
result = malloc((l + 1) * sizeof *result);
if (NULL != result)
{
result[0] = malloc(s + l + 1);
if (NULL != result[0])
{
for (size_t i = 0; i < l; ++i)
{
strcpy(result[i], ppa[i]);
result[i + 1] = result[i] + strlen(result[i]) + 1;
}
result[l] = NULL;
}
else
{
int errno_save = errno;
free(result);
errno = errno_save;
result = NULL;
}
}
}
return result;
}
像這樣使用它:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char ** create_pointer_array_pointing_to_sequential_data(char ** ppa);
int main(void)
{
char ** pa = create_pointer_array_pointing_to_sequential_data(
(char*[]){"Hello World!",
"foo",
"bar",
"huhu",
"Let's talk about that",
NULL}
);
if (NULL == pa)
{
perror("create_pointer_array_pointing_to_sequential_data() failed");
exit(EXIT_FAILURE);
}
for (size_t i = 0; NULL != pa[i]; ++i)
{
printf("pa[%zu] starts at %p and ends at %p: %s\n",
i, (void*) pa[i], (void*)(pa[i] + strlen(pa[i])), pa[i]);
}
}
並得到:
pa[0] starts at 0x6000003f0 and ends at 0x6000003fc: Hello World!
pa[1] starts at 0x6000003fd and ends at 0x600000400: foo
pa[2] starts at 0x600000401 and ends at 0x600000404: bar
pa[3] starts at 0x600000405 and ends at 0x600000409: huhu
pa[4] starts at 0x60000040a and ends at 0x600000420: Let's talk about that
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.