C 将 char 附加到 char*
Posted
技术标签:
【中文标题】C 将 char 附加到 char*【英文标题】:C appending char to char* 【发布时间】:2012-10-08 00:13:15 【问题描述】:所以我尝试将char
附加到char*
。
例如我有char *word = " ";
我也有char ch = 'x';
我做append(word, ch);
用这个方法..
void append(char* s, char c)
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
它给了我一个分段错误,我明白我为什么这么想。因为s[len]
越界了。我如何使它起作用?如果我要使用 char word[500]; 之类的东西,我还需要大量清除 char*
一旦它附加了一些字符,我将如何清除它?它的strlen
总是500
吗?提前致谢。
【问题讨论】:
“因为 s[len] 超出范围。” @H2CO3s[len + 1]
超出范围。 s[len]
为空字节,strlen
不计入。
@pmr 是的,技术上是正确的。我应该改写sizeof(s)
。
字符串litteral的const性质不应该触发编译器警告whan传递给函数吗?
@H2CO3 绝对不是,那可能是 4 或 8 并且反映了指针的大小。
【参考方案1】:
您不能真正安全地附加到任意字符串,因为首先,字符串常量往往位于只读内存中,因此尝试写入它们可能会导致分段错误,其次,您没有保证如果他们给了你一个缓冲区,你还没有射过它。
特别是,如果您这样做 字符 x[500];
无法保证 strlen(x) 会返回 500。它会返回从 x 的开头开始向前计数的字符数,然后才达到 null。它可能会返回 0、1 ... 500、501 ...,具体取决于 x 中的内容。
真的,您唯一的选择是使用您要附加到的缓冲区的大小调用 append(因此如果缓冲区已满,您可以做一些适当的事情),或者每次调用 append 时都分配一个新缓冲区,在在这种情况下,您当然需要再次释放缓冲区。
【讨论】:
【参考方案2】:是的,您所做的假设是 - 几乎 - 正确 - 崩溃可能是因为您试图超出字符串的范围(实际上只有 s[strlen(s) + 1]
超出范围,因为 s[strlen(s)]
仍然是有效位置 - 终止 NUL 字节存储在那里)。但是您也不能修改字符串文字,因为它通常位于进程内存的某个只读部分中。这两种行为都会导致调用未定义的行为,这可能会导致崩溃。您可以通过将字符串复制到动态分配的存储空间然后修改副本来解决此问题。此外,您应该在函数的参数中使用const char *
,因为char *
建议不能传入只读字符串。
char *append(const char *orig, char c)
size_t sz = strlen(orig);
char *str = malloc(sz + 2);
strcpy(str, orig);
str[sz] = c;
str[sz + 1] = '\0';
return str;
另外,当不再需要返回的字符串时,不要忘记free()
。
【讨论】:
【参考方案3】:很难在 C 中就地附加到字符串。试试这样:
char *append(const char *s, char c)
int len = strlen(s);
char buf[len+2];
strcpy(buf, s);
buf[len] = c;
buf[len + 1] = 0;
return strdup(buf);
请务必在完成后释放返回的字符串。
仅供参考:可能是因为您传递的字符串存储在只读内存中,所以出现了段错误。但你是对的,你也是在结束([len+1]
写,而不是[len]
一个)。
【讨论】:
char buf[len+2] 可能无法编译,这取决于他的编译器版本【参考方案4】:典型的 C 实践如下:
//returns 1 if failed, 0 if succeeded
int append(char*s, size_t size, char c)
if(strlen(s) + 1 >= size)
return 1;
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
return 0;
当传递一个数组来修改函数时,在编译时并不知道它有多少空间。 C 中的通常做法是也传递数组的长度,如果函数无法在其拥有的空间中完成工作,函数将信任此边界并失败。另一种选择是重新分配并返回新数组,您需要返回char*
或将char**
作为输入,但您必须仔细考虑在这种情况下如何管理堆内存。但是如果没有重新分配,是的,如果在没有剩余空间时要求追加,您的函数必须以某种方式失败,如何失败由您决定。
【讨论】:
这是一个错误的答案,因为您不知道 *s 是否包含字符串文字。它们通常存储在只读存储器中,如果您修改它们可能会导致访问冲突。您的代码可能有效,但它被视为未定义的行为。 @user1888162 如果你传入大量的大小,它也是UB。 我得到:'append' 从没有强制转换的指针中生成整数 [-Werror=int-conversion] name, strlen(nickname), " ");【参考方案5】:如果你要进来
append("foo", 'X');
它会崩溃,因为 foo 通常放在只读存储中。即使不是,它也可能会覆盖一些不好的东西! 在这种情况下,编译器应该警告你从 const char * 到 char * 的转换,这将是一个线索。
【讨论】:
以上是关于C 将 char 附加到 char*的主要内容,如果未能解决你的问题,请参考以下文章
如何将原始数据附加到 boost::shared_array<char>?