字符串在函数cal后生成NUL

时间:2018-01-25 12:51:30

标签: c string pointers

我正在尝试在C中重新创建C ++函数std::string.pop_back,其中弹出输入字符串的最后一个非NUL字符。在下面的pop_back函数中,变量out具有所需的函数输出,但尝试将*string重新分配为out会使*string成为正确的值在函数关闭之前(例如,如果我在函数末尾打印string*,它将输出Hello World),但在main()中,在pop_back()之后被叫string输出为空白。在重新分配string时我做错了什么?

#include <stdio.h>
#include <string.h>

void pop_back(char** string) {
    size_t stringLen = strlen(*string);
    char out[stringLen];

    strxfrm(out, *string, stringLen);
    // Here *string == "Hello World!"
    *string = out;
    // Here *string == "Hello World"
}

int main(int argc, char* argv[]) {
    char* string = "Hello World!";
    printf("Initial string: %s\n", string);
    pop_back(&string);
    printf("After pop_back: %s\n", string);
    return 0;
}

// Output:
// $ ./pop_back_test
// Initial string: Hello World!
// After pop_back: 

// Expected output:
// $ ./pop_back_test
// Initial string: Hello World!
// After pop_back: Hello World

3 个答案:

答案 0 :(得分:4)

使用您的代码

char out[stringLen];
...
*string = out;

“返回”(赋值给参数)指向“局部变量”的指针,即指向具有自动存储持续时间的对象的指针,其寿命在函数结束时结束。访问超出其生命周期的对象是不确定的行为。

您可能必须动态分配一个新字符串,然后您可以在函数执行结束后进行操作和使用。例如:

if (!(*string) || !(**string)) {
  // decide what to do with NULL or empty input strings.
  ...
}
else {
  size_t stringLen = strlen(*string);
  char* out = malloc(stringLen);
  memcpy(out, *string, stringLen);
  out[stringLen-1] = '\0';
} 

*string = out;

之后不要忘记释放分配的内存。顺便说一句:如果你操作副本,我建议返回(新)副本并保持输入指针不变,即我将原型更改为

char* pop_back(char* string) {
    ...
    return out;
}

答案 1 :(得分:2)

当我单步执行代码时,调试器中的消息显示在线...

*string = out;

... *string超过了数组范围,导致分配失败。 *string指向 string literal ,这意味着它无法修改。尝试修改其内容将始终失败。

有几种方法可以解决这个问题。

一种方法是修改pop_back()函数以接受char *,并返回char *,允许您传入不可变字符串并返回结果字符串。

建议实施:

char * pop_back(char *string) 
{
    size_t stringLen = strlen(string)+1;//add one for NULL
    char *out = calloc(stringLen,1);//create space for new string

    strxfrm(out, string, stringLen);
    // Here *string == "Hello World!"
    return out;//return string
    // Here *string == "Hello World"
}

int main(int argc, char* argv[]) 
{
    char *string1 = "Hello World!";         // source string
    char *string2 = {0};                    // container for local result

    printf("Initial string: %s\n", string1);
    string2 = pop_back(string1);            // get local result
    printf("After pop_back: %s\n", string2);// use local result
    free(string2);                          // free local result
    return 0;
}

答案 2 :(得分:0)

代码中的

char out[stringLen];是void pop_back(char ** string)的局部变量,超出了范围。