【问题标题】:Correct way to pass the char pointer to helper fuction and assign the value in C将 char 指针传递给辅助函数并在 C 中赋值的正确方法
【发布时间】:2020-12-15 10:48:49
【问题描述】:

我有一些关于在辅助函数中将值分配给 char* 的问题。如果我有以下代码

int main() {
    char *p = malloc(6* sizeof(char));
    changeValue(p);
    printf("value of p=%s\n", p);

    return 0;
}

如果我定义以下函数,那么它不起作用:

void changeValue(char* input){
    input = "hello";
}

我的第一个问题是我们不能直接为指针赋值的原因是什么? 我之前的理解是因为空间“hello”只在changeValue作用域内创建,一旦脱离changeValue函数,就被销毁了。但是,如果我使用指针的指针来分配它的值。似乎“你好”空间没有被破坏:

void changeValue(char ** input){
    *input = "hello";
}

主要我需要更改为:

char **p2 = malloc(sizeof(char*));
changeValue(p2);
printf("value of p2=%s\n", *p2);

而且它工作正常。我的第二个问题是,第二个函数发生了什么才能使其正常工作,我之前的逻辑中哪个部分出错了?

我还找到了以下赋值方式:

changeValue函数保持不变:

void changeValue(char ** input){
    *input = "hello";
}

在主 cpp 中我做了以下操作:

char *p = malloc(6* sizeof(char));
changeValue(&p);
printf("value of p=%s\n", p);

似乎它也可以正常工作,但对我来说没有任何意义。我的第三个问题是输入是内存中 p 的地址,如何取消引用地址并为其赋值?

在辅助函数中分配 char* 值的正确方法是什么?

谢谢

【问题讨论】:

  • "hello" 是一个字符串字面量,它的生命周期是整个程序的持续时间
  • 你所有的例子都泄露了malloc分配的内存
  • "我的第一个问题是我们不能直接为指针赋值的原因是什么?" 你可以。您只是分配给在函数参数列表中创建的指针的 copy,因为 C 总是按值/副本传递。所以外面看不到变化。要更改在函数外部看到的值,您必须传递一个指向它的指针,在这种情况下是一个指向指针的指针。然后,您可以取消引用该指针以获取其指向的可修改左值。抱歉,这是基本的指针用法,应该在对指针概念的任何半体面的介绍中进行解释。
  • 您可以使用void changeValue(char *input) { strcpy(input, "hello"); } 完成第一个版本。这会更改input(以及main() 中的p)指向的6 字节块,而不是更改指针本身。
  • 这取决于你想做什么。当然,您可以复制指向字符串文字的指针。只要确保你永远不会通过指针修改字符串文字的内容,因为这会导致未定义的行为。

标签: c pointers char dereference


【解决方案1】:

在第一个版本中,'p' 指向 malloc'ed 内存(6 字节)。在第 2 版中,p2 指向将包含地址的内存。

在您的辅助函数的第一个版本中:

void changeValue(char* input){
    input = "hello";
}

在该函数之外,'p' 仍然指向 malloc 的内存。当程序进入 changeValue() 函数时,“p”的值被压入堆栈,现在它被一个名为“input”的新字段引用……它只存在于堆栈中。因此,通过为其分配文字“hello”,您已将 'p' 替换为字符串文字“hello”的地址。

同时,'p' 的位置与'input' 不同。一旦函数返回,临时分配给 'input' 的内存已被弹出,不再相关。

也许图表可以提供帮助:

起初:

char *p = malloc(6* sizeof(char));


 (Stack)                 (Heap)

+-------+          +------------------+
|   p   +--------> | 6 * sizeof(char) |
+-------+          +------------------+

接下来,调用:

changeValue(p); // first version

影响以下:

 (Stack)                 (Heap)
+-------+
| input +----+
+-------+    |     +------------------+
|   p   +----+---> | 6 * sizeof(char) |
+-------+          +------------------+

然后:

input = "hello";

 (Stack)              (Heap)               (DataSegment)

+-------+                                    +-------+
| input +----------------------------------->|"hello"|
+-------+       +------------------+         +-------+
|   p   +-----> | 6 * sizeof(char) |
+-------+       +------------------+

从“changeValue”退出后,堆栈被展开,“输入”不再相关。

 (Stack)                 (Heap)

+-------+          +------------------+
|   p   +--------> | 6 * sizeof(char) |
+-------+          +------------------+

在 main 函数的最后,你现在有内存泄漏(malloc'ed 内存没有被释放)。

使用辅助函数的一个正确方法是:

int main() {
    char *p = malloc(6* sizeof(char));

    changeValue(p, 6* sizeof(char) );   

    printf("value of p=%s\n", p);

    free( p ) ;        // <<<<<< avoid memory leak

    return 0;
}

void changeValue(char * input, size_t maxSize){
    // ... Copy "hello" into the space pointed to by input, taking
    //     care not to overrun the memory
    strncpy( input, "hello", maxSize ) ;
}

【讨论】:

  • 其中一张图看起来像是input 指向p
  • 感谢您的回复。你能解释一下changeValue(&p)吗?我有点困惑为什么 &p 可以被视为 **char 作为输入并正常工作?抱歉问了这么愚蠢的问题
  • changeValue(&p) 是我的错误。我在答案中更改了它。最初,只有当你想改变 'p' 指向的位置时,你才会传递 '&p'。但是在您的示例中,您只想修改“p”指向的内存内容,而不是“p”本身。
【解决方案2】:

关于这个问题,我认为存储指针s的内存(大小取决于系统)和指针s指向的内存(分配6字节大)是两个不同的概念。

“第三位代码 (char p = malloc(6 sizeof(char));changeValue(&p);) 是错误的,因为 p 指向的内存可能不够大拿着指针。在具有 64 位指针的系统上,sizeof(char *) 通常为 8,大于您分配的 6 * sizeof(char)。顺便说一句,sizeof(char) 定义为 1,所以 malloc(6 * sizeof(char)) 与 malloc(6) 相同。 ”

【讨论】:

    猜你喜欢
    • 2013-10-27
    • 1970-01-01
    • 2011-05-22
    • 2016-06-09
    • 2021-09-07
    • 2012-07-28
    • 1970-01-01
    • 2021-12-02
    • 2016-03-27
    相关资源
    最近更新 更多