在 C 中修改 const char *
Modify const char * in C
我正在练习面试。我目前遇到的问题是反转 C 中的常量字符串。我知道由于 str2 是常量,所以我可以修改 str2 指向的位置,但不能修改它的值。我在下面有一个名为 reverse_const 的函数。它将原地反转 const char *str_const 并打印它。但是,当我尝试从 main 方法反转后打印 st2 时,字符串不再反转。就像 reverse_const() 临时改变了 str2 的内存位置。我在这里做错了什么?
#include <stdio.h>
#include <string.h>
void reverse(char *str){
int c_size = strlen(str);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for(i = 0; i < c_size / 2; i++){
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
}
void reverse_const(const char *str_const){
int c_size = strlen(str_const);
char str[c_size];
strcpy(str, str_const);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for(i = 0; i < c_size / 2; i++){
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
str_const = str;
printf("%s\n", str_const);
}
int main(){
char str1[] = "Indiana";
char *str2 = "Kentucky";
printf("TESTS:\nString 1 pre-reversal: %s\n", str1);
reverse(str1);
printf("String 1 post-reversal: %s\n", str1);
printf("Constant string 2 pre-reversal: %s\n", str2);
reverse_const(str2);
printf("Constant string 2 post-reversal: %s\n", str2);
}
这里的问题是您修改了传递给 reverse_const
的参数,但是 C 中的参数是按值传递的,这意味着它们被复制了。你在函数中修改的变量是原指针的副本,改变一个副本当然不会改变原来的
C 没有这里需要的 pass by reference,但是可以使用指针 emulated,在这种情况下你的函数需要传递一个指向指针的指针,然后使用解引用运算符 *
修改指向指针指向的指针,并在调用函数时使用寻址运算符 &
。
当你传递参数时,函数会得到一个副本。 str_const = str;
分配给该副本。您可以将指针传递给指针,以便能够在函数外部更改指针的值,但是您正在堆栈上分配字符串副本,因此一旦离开 [=11= 的范围,字符串副本就会变得无效] 所以这在这里没有意义。
如果您想要一个在 reverse_const
结束后仍然存在的字符串副本,请使用 malloc
分配数组或使用 strdup
进行分配和复制。您必须以某种方式 return malloc'ed
指针(通过指向指针参数的指针的 return 值),然后调用者将有责任 free
malloc
' 完成记忆后。
你需要编写你的函数,这样你就有办法return修改参数。
一个这样的解决方案是传递引用:
void reverse_const(const char **str_const){
const char *in = *str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
*str_const = out;
}
但更好的方法是使用 return 值:
char *reverse_const(const char *str_const){
const char *in = str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
return out;
}
return 类型可以是 const char *
,但这是不必要的限制,因为您知道可以安全地修改 returned 字符串。
请注意,两个示例都使用 malloc
。在 C 中,不能以这种方式传回数组,因为它们存在于堆栈中,并在函数退出时被销毁。
每当长运行 程序使用malloc
时,确实应该在代码中的某处匹配free
,否则会发生内存泄漏。这很痛苦,但是所有 C 程序员都必须掌握的东西。
如果你想在 main()
中返回反转的 str2
,你需要将一个足够大的缓冲区传递给 reverse_const
来保存反转的字符串,或者你需要在 reverse_const
中为其动态分配存储(局部可变长度数组不会这样做):
#include <stdlib.h>
...
void reverse_const (const char **str_const)
{
int c_size = strlen (*str_const);
char *str = calloc (c_size + 1, sizeof *str);
strcpy (str, *str_const);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for (i = 0; i < c_size / 2; i++) {
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
*str_const = str;
printf ("%s\n", *str_const);
}
int main (void) {
char str1[] = "Indiana";
char *str2 = "Kentucky";
printf ("TESTS:\nString 1 pre-reversal: %s\n", str1);
reverse (str1);
printf ("String 1 post-reversal: %s\n", str1);
printf ("Constant string 2 pre-reversal: %s\n", str2);
reverse_const ((const char **)&str2);
printf ("Constant string 2 post-reversal: %s\n", str2);
free (str2);
return 0;
}
输出
$ ./bin/revconststr
TESTS:
String 1 pre-reversal: Indiana
String 1 post-reversal: anaidnI
Constant string 2 pre-reversal: Kentucky
ykcutneK
Constant string 2 post-reversal: ykcutneK
返回指针
您有一个额外的选项,可以 return 将指向 str
的指针分配给 main()
中的 str2
。这是您通常希望看到的更多内容。如果您有任何问题,请告诉我:
char *reverse_const2 (const char **str_const)
{
int c_size = strlen (*str_const);
char *str = calloc (c_size + 1, sizeof *str);
strcpy (str, *str_const);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for (i = 0; i < c_size / 2; i++) {
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
//*str_const = str;
printf ("%s\n", *str_const);
return str;
}
int main (void)
{
char str1[] = "Indiana";
char *str2 = "Kentucky";
printf ("TESTS:\nString 1 pre-reversal: %s\n", str1);
reverse (str1);
printf ("String 1 post-reversal: %s\n", str1);
printf ("Constant string 2 pre-reversal: %s\n", str2);
str2 = reverse_const2 ((const char **)&str2);
printf ("Constant string 2 post-reversal: %s\n", str2);
free (str2);
return 0;
}
我正在练习面试。我目前遇到的问题是反转 C 中的常量字符串。我知道由于 str2 是常量,所以我可以修改 str2 指向的位置,但不能修改它的值。我在下面有一个名为 reverse_const 的函数。它将原地反转 const char *str_const 并打印它。但是,当我尝试从 main 方法反转后打印 st2 时,字符串不再反转。就像 reverse_const() 临时改变了 str2 的内存位置。我在这里做错了什么?
#include <stdio.h>
#include <string.h>
void reverse(char *str){
int c_size = strlen(str);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for(i = 0; i < c_size / 2; i++){
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
}
void reverse_const(const char *str_const){
int c_size = strlen(str_const);
char str[c_size];
strcpy(str, str_const);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for(i = 0; i < c_size / 2; i++){
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
str_const = str;
printf("%s\n", str_const);
}
int main(){
char str1[] = "Indiana";
char *str2 = "Kentucky";
printf("TESTS:\nString 1 pre-reversal: %s\n", str1);
reverse(str1);
printf("String 1 post-reversal: %s\n", str1);
printf("Constant string 2 pre-reversal: %s\n", str2);
reverse_const(str2);
printf("Constant string 2 post-reversal: %s\n", str2);
}
这里的问题是您修改了传递给 reverse_const
的参数,但是 C 中的参数是按值传递的,这意味着它们被复制了。你在函数中修改的变量是原指针的副本,改变一个副本当然不会改变原来的
C 没有这里需要的 pass by reference,但是可以使用指针 emulated,在这种情况下你的函数需要传递一个指向指针的指针,然后使用解引用运算符 *
修改指向指针指向的指针,并在调用函数时使用寻址运算符 &
。
当你传递参数时,函数会得到一个副本。 str_const = str;
分配给该副本。您可以将指针传递给指针,以便能够在函数外部更改指针的值,但是您正在堆栈上分配字符串副本,因此一旦离开 [=11= 的范围,字符串副本就会变得无效] 所以这在这里没有意义。
如果您想要一个在 reverse_const
结束后仍然存在的字符串副本,请使用 malloc
分配数组或使用 strdup
进行分配和复制。您必须以某种方式 return malloc'ed
指针(通过指向指针参数的指针的 return 值),然后调用者将有责任 free
malloc
' 完成记忆后。
你需要编写你的函数,这样你就有办法return修改参数。
一个这样的解决方案是传递引用:
void reverse_const(const char **str_const){
const char *in = *str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
*str_const = out;
}
但更好的方法是使用 return 值:
char *reverse_const(const char *str_const){
const char *in = str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
return out;
}
return 类型可以是 const char *
,但这是不必要的限制,因为您知道可以安全地修改 returned 字符串。
请注意,两个示例都使用 malloc
。在 C 中,不能以这种方式传回数组,因为它们存在于堆栈中,并在函数退出时被销毁。
每当长运行 程序使用malloc
时,确实应该在代码中的某处匹配free
,否则会发生内存泄漏。这很痛苦,但是所有 C 程序员都必须掌握的东西。
如果你想在 main()
中返回反转的 str2
,你需要将一个足够大的缓冲区传递给 reverse_const
来保存反转的字符串,或者你需要在 reverse_const
中为其动态分配存储(局部可变长度数组不会这样做):
#include <stdlib.h>
...
void reverse_const (const char **str_const)
{
int c_size = strlen (*str_const);
char *str = calloc (c_size + 1, sizeof *str);
strcpy (str, *str_const);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for (i = 0; i < c_size / 2; i++) {
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
*str_const = str;
printf ("%s\n", *str_const);
}
int main (void) {
char str1[] = "Indiana";
char *str2 = "Kentucky";
printf ("TESTS:\nString 1 pre-reversal: %s\n", str1);
reverse (str1);
printf ("String 1 post-reversal: %s\n", str1);
printf ("Constant string 2 pre-reversal: %s\n", str2);
reverse_const ((const char **)&str2);
printf ("Constant string 2 post-reversal: %s\n", str2);
free (str2);
return 0;
}
输出
$ ./bin/revconststr
TESTS:
String 1 pre-reversal: Indiana
String 1 post-reversal: anaidnI
Constant string 2 pre-reversal: Kentucky
ykcutneK
Constant string 2 post-reversal: ykcutneK
返回指针
您有一个额外的选项,可以 return 将指向 str
的指针分配给 main()
中的 str2
。这是您通常希望看到的更多内容。如果您有任何问题,请告诉我:
char *reverse_const2 (const char **str_const)
{
int c_size = strlen (*str_const);
char *str = calloc (c_size + 1, sizeof *str);
strcpy (str, *str_const);
char *c_begin = str, *c_end = str + (c_size - 1);
int i;
for (i = 0; i < c_size / 2; i++) {
*c_begin ^= *c_end;
*c_end ^= *c_begin;
*c_begin ^= *c_end;
c_begin++;
c_end--;
}
//*str_const = str;
printf ("%s\n", *str_const);
return str;
}
int main (void)
{
char str1[] = "Indiana";
char *str2 = "Kentucky";
printf ("TESTS:\nString 1 pre-reversal: %s\n", str1);
reverse (str1);
printf ("String 1 post-reversal: %s\n", str1);
printf ("Constant string 2 pre-reversal: %s\n", str2);
str2 = reverse_const2 ((const char **)&str2);
printf ("Constant string 2 post-reversal: %s\n", str2);
free (str2);
return 0;
}