使用指向 char 的指针时出现分段错误

Segmentation fault while using pointer to pointer to a char

在编译和执行以下程序时,我在编译期间收到警告,在执行期间收到段错误。

警告

program.c: In function main:
program.c:17: warning: passing argument 2 of convertString from incompatible pointer type

第 17 行是对 convertString(input, &output);

的调用

附加调试器可以看到段错误发生在下面的行

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400521 in convertString (input=0x7fffffffd100 "abcdefg", output=0x7fffffffd0f0) at program.c:9
9           **output = *input;
(gdb) s

#include<stdio.h>
#include<string.h>
void convertString(char *input, char **output)
{
    if(strlen(input)== 0)
    {
        return;
    }
    **output = *input;
    (*output)++;
    convertString(input+1,output);
}
int main()
{
    char input[] = "abcdefg";
    char output[sizeof(input)];
    convertString(input, &output);
    printf("%s", output);
    return 0;
}

请大家帮我看看哪里做错了

问题是 output 不是一个指针,它是一个数组,并且在数组上使用地址运算符会给你一个指向数组的(单个)指针(在你的类型 char (*)[8]).为了澄清:(void *) output == (void *) &output,数组的衰减指针和指向数组的指针都相等。

所以你并不是真的将指向 char 的指针传递给函数。


除此之外,我看不出函数应该采用指向指针的指针,一个普通的单个指针就足够了。否则,在 printf 调用中使用 output 时,您会得到错误的结果,因为 output 会指向字符串末尾之外。

此外,您不终止 output 字符串。

正如 aleardy 所指出的 Mr. JP in ,问题是 &output 没有给你一个 char **,在这种情况下它给了一个 char (*)[8],这将用作函数参数时衰减为 char *

在你的例子中,你不需要一个指向指针的指针来改变该指针指向的内存区域的内容。一个简单的指针就可以了。你可以改变

void convertString(char *input, char **output)

void convertString(char *input, char *output)  //output is of type char*

和其他出现的 output 类似,并称其为

convertString(input, output);

应该可以。

就是说,您应该以 null 终止 output 以使其用作 字符串

#include<stdio.h>
#include<string.h>
void convertString(char *input, char *output)
{
    if(strlen(input)== 0)
    {
        return;
    }
    *output = *input;
    output++;
    convertString(input+1,output);
}
int main()
{
    char input[] = "abcdefg";
    char output[sizeof(input)];
    convertString(input, output);
    printf("%s\n", output);
    return 0;
}

这可能就是你想要做的?

这里你真的不需要指向输出缓冲区的双指针,一个简单的 char* 就足够了:

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

void convertString(char *input, char *output)
{
    if(!(*output = *input)) // Copy the zero terminator as well.
        return;
    convertString(input + 1, output + 1);
}

int main()
{
    char input[] = "abcdefg";
    char output[sizeof(input)];
    convertString(input, output);
    printf("%s", output);
    return 0;
}

字符数组 output 的类型 char [sizeof( "abcdefg" ) ] 等同于 char[8]。所以函数调用中的表达式&output

convertString(input, &output);

的类型为 char ( * )[8],而函数的相应参数的类型为 char **。它们是不兼容的类型,编译器指出了这个错误。

将此参数声明为 char ** 类型没有任何意义。它必须声明为 char *.

void convertString(char *input, char *output);

同样在函数内,终止零不会从输入字符串复制到输出字符串。该函数直接退出。

if(strlen(input)== 0)
{
    return;
}

并且在每次递归中计算字符串的长度是低效的。您至少可以将此条件替换为

if ( input[0] == '[=13=]' )

if ( *input == '[=14=]' )

if ( !*input )

也不清楚为什么函数被命名为 convertString 而不是例如 copyString.

考虑到字符串函数 return 指向它们处理的字符串的指针有一个共同约定。 函数可以定义的更简单。

这是一个演示程序

#include <stdio.h>

char * copyString( char *output, const char *input )
{
    if ( ( *output = *input ) ) copyString( output + 1, input + 1 );
    return output;
}

int main(void) 
{
    char input[] = "abcdefg";
    char output[sizeof(input)];

    puts( copyString( output, input ) );    

    return 0;
}

程序输出为

abcdefg