简体   繁体   English

指向(定义了指针数组)字符串的指针数组:字符串是否按顺序存储在 memory 中?

[英]Pointer array to (with pointer array defined) strings: Are the strings stored sequential in memory?

I wondering about how strings are stored in memory, when define them with/through an array of pointers, which point to them.我想知道字符串是如何存储在 memory 中的,当使用/通过指向它们的指针数组定义它们时。

For example:例如:

char *pa[] = { "Hello World!", "foo","bar","huhu","Let´s talk about that" };

Are the strings (or better: their characters) stored sequential in memory, one after another?字符串(或更好:它们的字符)是否按顺序存储在 memory 中,一个接一个?

Like, for example in this case:例如,在这种情况下:

The first character byte of the second string "foo" which is f is stored directly inside the byte after the \0 -Null character of the first string "Hello World!"第二个字符串"foo"的第一个字符字节f直接存储在第一个字符串"Hello World!"\0 -Null 字符之后的字节内。 . .

OR或者

Are the strings stored separated in memory?, like for example:存储在 memory 中的字符串是否分开存储?例如:

\0 -Null character of the first string "Hello World!" \0 - 第一个字符串"Hello World!"的空字符- sequence of Bytes between - f character of second string "foo" ? - 第二个字符串"foo"f字符之间的字节序列?

OR或者

Is it even so, that the storage is dependent from the situation, compiler, platform, etc. and its one time directly-sequential and one time not?即便如此,存储是否取决于情况、编译器、平台等,并且一次是直接顺序的,一次不是?

Can it furthermore occure also, that fe the first character f of the second string "foo" is stored directly after the \0 -character of the first string "Hello World!"是否还会发生,第二个字符串"foo"的第一个字符f直接存储在第一个字符串"Hello World!"\0字符之后。 , meaning they are stored sequential, and between the \0 -character of the second string "foo" and the first character of the third string "bar" , which is b is a gap of to the string-group non-affiliated bytes, dependent from the compiler, platform, etc.? ,这意味着它们是按顺序存储的,并且在第二个字符串"foo"\0字符和第三个字符串"bar"的第一个字符之间,即b是字符串组非附属字节的间隙,依赖于编译器、平台等?

Question is for C and C++, as i work with both.问题是针对 C 和 C++ 的,因为我同时使用两者。 If the answers between those two alter, please mention which language is in focus.如果这两者之间的答案发生变化,请说明重点关注哪种语言。

Hope you can understand, what i mean.希望你能明白,我的意思。 Thank you very much for any answer.非常感谢您的任何回答。

No, you cannot assume anything.不,你不能假设任何事情。 It is implementation-defined whether they are stored in contiguous memory or not.它们是否存储在连续的 memory 中由实现定义。

If you really want the strings to be like that, try如果您真的希望字符串是那样的,请尝试

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

or, as @SteveSummit suggests或者,正如@SteveSummit 建议的那样

const char *pa[] = { base, base + 6, base + 10 };

Furthermore, if you had此外,如果你有

char *pa[] = { "testing", "testing", "more testing" };

it would be possible for the compiler to store just one copy of the string "testing" , and point to it from both pa[0] and pa[1] .编译器可以只存储字符串"testing"的一份副本,并从pa[0]pa[1]指向它。 (In fact, I just tried it with two modern compilers, and both of them did exactly that.) (事实上,我只是用两个现代编译器尝试过,它们都做到了。)

Theoretically it would be possible for a really clever compiler to store just the string "more testing" and have pa[0] and pa[1] point into the middle of it.从理论上讲,一个非常聪明的编译器可以只存储字符串"more testing"并让pa[0]pa[1]指向它的中间。

I assume you were asking out of curiosity, but if by any chance you were thinking of writing code that somehow depended on the ordering of string constants in memory, the immediate and simple answer is: Don't .我假设您是出于好奇而询问,但如果您有任何机会考虑编写代码,该代码以某种方式依赖于 memory 中字符串常量的顺序,那么直接而简单的答案是:不要

What Steve Summit answered, plus: If multiple strings are stored, they could be in any order, or far apart from each other. Steve Summit 的回答是:如果存储了多个字符串,它们可以按任何顺序排列,也可以彼此相距很远。

In addition, comparing pointers to these strings using ">", ">=" etc. is undefined behaviour.此外,使用“>”、“>=”等比较指向这些字符串的指针是未定义的行为。 So you may check for example if p1 = "testing", p2 = "testing", whether p2 == p1 + 8 (which will produce 0 or 1 without any guarantees), but not whether p2 >= p1 + 8.因此,您可以检查例如 p1 = "testing"、p2 = "testing"、p2 == p1 + 8 是否(在没有任何保证的情况下会产生 0 或 1),但不能检查 p2 >= p1 + 8 是否。

As others mentioned, the memory layout is implementation defined.正如其他人提到的,memory 布局是实现定义的。

Extending pmg 's approach and doing C you could do it like this:扩展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;
}

Use it like:像这样使用它:

#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]);
   }
 }

And get:并得到:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM