【问题标题】:In C, how can I change the memory address a pointer is pointing to?在 C 中,如何更改指针指向的内存地址?
【发布时间】:2013-05-28 21:43:56
【问题描述】:

例如,我有一个 char ** 数组,它有 3 个指针。 比方说:

array[0] has abc (points to "a", which lives in address 0x80033de0)
array[1] has def (points to "d", which lives in address 0x80033d)
array[2] has NULL 

假设我已将数组字符串复制到不同的内存位置

0x7ffffff8 has abc (points to "a")
0x7ffffffc has def (points to "d")

如何更改 array[0] 使其指向 0x7ffffff8 而不是 0x80033de0?

还有 array[1] 指向 0x7ffffffc 而不是 0x80033d?

我已经尝试过不同类型的投射,但无法让它发挥作用。

编辑:

感谢大家看我的问题。我问这个的原因是因为我正在使用内核,我需要将参数从内核空间复制到用户空间。我想我可以通过将 arg 字符串复制到用户空间然后更改原始 args 指针在内核空间中指向的内存地址来做到这一点。我想这不是一个好主意。

【问题讨论】:

  • 你试过什么?你应该能够做到array[0] = (char*)0x7FFFFFF8
  • “我已经尝试过不同类型的投射,但无法让它发挥作用。” - 然后向我们展示代码和错误。
  • 实际上想做什么?您想拥有char** 的深层副本吗?你想拥有复制感知结构吗?请多解释一下。
  • 到目前为止的两个答案都假设0x7ffffff8 有一定的意义;我怀疑情况是否如此。描述你想要做什么,而不是展示具有特定无意义内存地址的示例。

标签: c pointers memory memory-management


【解决方案1】:

我有一个 char ** 数组,它有 3 个指针

不,你没有。您有一个包含三个值的数组。这些值恰好是指针。数组没有 指针。

假设您为这个数组(指向 char 的指针)分配内存:

char **array = malloc( 3 * sizeof(char*)); // 3 values in the array

然后为每个字符串分配内存:

array[0] = malloc(4 * sizeof(char) ); // 3 + 1 null terminator
array[1] = malloc(4 * sizeof(char) );
array[2] = 0;

最后你自己设置了字符串的值:

strcpy( array[0], "abc" );
strcpy( array[1], "def" );

现在您要制作副本。实际上是一个 deep 副本,因为您不仅为新数组(指向 char 的指针)分配内存,而且还为新字符串分配内存。 您执行完全相同的分配:

char **array2 = malloc( 3 * sizeof(char*));
array2[0] = malloc(4 * sizeof(char) );
array2[1] = malloc(4 * sizeof(char) );
array2[2] = 0;

现在你复制实际的字符串:

strcpy( array2[0], array[0] );
strcpy( array2[1], array[1] );

如果您的代码与上述代码不同,请编辑您的问题并提供更多详细信息。

棘手的部分是让array[0] 保存array2[0] 中的地址(array[1] 和array2[1] 相同)。问题在于您通过malloc 分配的内存需要通过free 释放。

所以你不能只做

array[0] = array2[0];

因为您丢失了对您分配的第一个字符串的所有引用。那段内存泄露了

改为这样做:

free(array[0]);
array[0] = array2[0];

这将释放用于第一个字符串的内存并复制副本的地址。

现在你在两个变量中有相同的指针(值)。这也很棘手,因为(当您不再需要它时)您仍然需要释放为副本分配的内存:

free(array2[0])

棘手的部分是array[0] 现在拥有一个指向已释放内存的指针,该指针无法使用。使用它会导致错误。

最好不要让多个变量(在同一范围内)持有相同的指向已分配内存的指针。这可能会导致难以推断指针的有效性。

【讨论】:

    【解决方案2】:

    char ** array 是指针中的一个指针。 在这种情况下,它被分配了一个 char 指针数组,每个指针都包含最终 cstrings 的第一个 char 的地址。

    因此,您可以只使用等号,就像使用其他常规指针一样:

    array[0] = (char*)0x7ffffffc;

    array[1] = (char*)0x80033d;

    【讨论】:

    • 不,char** 永远不会变成数组。它可能指向数组的第一个元素。阅读comp.lang.c FAQ 的第 6 节。
    • 更好,但char** 不会“等同于”char 的地址。
    • 有点,但您假设十六进制地址是有意义的。我知道这就是 OP 所要求的,但 OP 实际问题的解决方案应该只涉及指针分配。很难说 OP 的问题到底是什么。
    • 更多观察:“指针的指针”没有多大意义; char** 是一个指针的指针。 “被分配了一个 char 指针数组”——嗯,是的,也不是。您可以进行类似array = foo; 的赋值,其中foochar* 的数组——但foo 的值被转换为指向数组第一个元素的指针,那就是分配给(可以说是错误命名的)指针对象array 的内容。由于我们谈论的是 C,而不是 C++,所以不需要术语“cstrings”;它们只是字符串。
    【解决方案3】:

    基本上,数组是指向起始地址的指针。因此array[n] 等于*(array+n)。如果你想移动你的整个数组,你可以这样做

    array = newPointer; //newPointer is something like char *newPointer;
    //notice the array without brackets because you want the pointer!
    

    【讨论】:

    • C 中的数组不可赋值。
    • 数组不是指针。请参阅comp.lang.c FAQ 的第 6 节。
    猜你喜欢
    • 1970-01-01
    • 2022-08-22
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多