【问题标题】:strcat problem with char *a[10]char *a[10] 的 strcat 问题
【发布时间】:2010-07-17 08:40:35
【问题描述】:

包括

#include <string.h>

int main()
{
        char *array[10]={};
        char* token;
        token = "testing";
        array[0] = "again";
        strcat(array[0], token);
}

为什么会返回分段错误?

我有点困惑。

【问题讨论】:

  • 帮自己(和我们)一个忙,读一本关于 C 的好书。

标签: c arrays string


【解决方案1】:

从技术上讲,这不是有效的 C。(但它是有效的 C++。)

char *array[10]={};

你应该使用

char *array[10] = {0};

这声明了一个包含 10 个指向 char 的指针的数组,并将它们全部初始化为空指针。

char* token;
token = "testing";

这将 token 声明为指向 char 的指针,并将其指向一个不可修改的字符串字面量。

array[0] = "again";

这会将array 的第一个char 指针指向一个字符串文字,该字符串(再次)是一个不可修改的字符序列。

strcat(array[0], token);

strcat 将一个字符串连接到另一个字符串的末尾。要使其工作,第一个字符串必须包含在可写存储中,并且有足够的多余存储空间来包含第一个字符串中第一个终止空字符 ('\0') 处及之后的第二个字符串。对于直接指向字符串文字的array[0],这些都不成立。

你需要做的是这样的事情。 (你需要#include&lt;string.h&gt;&lt;stdlib.h&gt;。)

我已经进行了大小的运行时计算和内存的动态分配,因为我假设您正在测试将来可能不知道字符串大小的位置。使用在编译时已知的字符串,您可以在编译时避免一些(或大部分)工作;但是您也可以将"againtesting" 作为单个字符串文字。

char* token = "testing";
char* other_token = "again";

/* Include extra space for string terminator */
size_t required_length = strlen(token) + strlen(other_token) + 1;

/* Dynamically allocated a big enough buffer */
array[0] = malloc( required_length );
strcpy( array[0], other_token );
strcat( array[0], token );

/* More code... */

/* Free allocated buffer */
free( array[0] );

【讨论】:

  • 如果您使用 GNU 扩展,您可以缩短所有长度检查、分配和复制到 asprintf(&amp;array[0], "%s%s", token, other_token);
【解决方案2】:

这是如何工作的:char *array[10] 是一个由 10 个 char * 指针组成的数组(基本上与 token 有 10 个相同的东西)。

token = "testing" 在构建时在程序内存的某处创建静态空间,并将“测试”放在那里。然后在运行时,它把那个静态“测试”的地址放到token

array[0] = "again" 基本上做同样的事情。

然后,strcat(array[0], token) 获取array[0] 中的地址,并尝试将token 的内容添加到该地址的字符串中。这会给您带来段错误,因为array[0] 指向您内存中的只读数据段。

如何正确地做到这一点:

char * initial = "first"; // pointer to static "first" string
char * second = "another"; // another one
char string[20]; // local array of 20 bytes

strcpy(string, initial); // copies first string into your read-write memory
strcat(string, second); // adds the second string there

实际上,如果您不想在脚上开枪,最好的方法是执行最后两行之类的操作:

snprintf(string, sizeof(string), "%s%s", initial, second);

snprintf 然后确保您使用的 string 不超过 20 个字节。如果复制的字符串比目标空间长,strcatstrcpy 会很高兴地超过限制进入无效内存,并导致另一个运行时段错误或更糟(想想安全漏洞)。

【讨论】:

    【解决方案3】:

    要创建一个字符数组,char *array[10]={}; 应该改为 char array[10]={};

    发生分段错误是因为 array[0] 指向“再次”,一个字符串文字,并且修改字符串文字是禁止的(未定义的行为)

    【讨论】:

    【解决方案4】:

    如果您打算更改所涉及的字符串,您应该真正分配足够的内存来满足您的需要。例如,您可以使用 char token[20] = "testing"; 代替 char *token; token = "testing";,它为 19 个字符的字符串(加上末尾的空字节)留出了足够的空间。

    同样,您可以使用char array[10][20] = {"testing"}; 创建一个包含 10 个字符串的数组并将第一个字符串设置为测试。

    【讨论】:

      【解决方案5】:

      您将一个字符串放在array[0],它只有一个字符。 像这样使用array[0]='a'

      【讨论】:

      • 呃……不,不是,萨格。 array[0]char *,而不是 char。虽然将char 常量存储在char * 变量中是合法的,但这并不是很好的做法。 (你的回答没有被我否决,但也许我应该这样做。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多