[英]Modify const char * in C
我正在练习面试。 Im当前遇到的问题是反转C中的常量字符串。我知道由于str2是const,因此我可以修改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);
}
当您传递参数时,该函数将获得一个副本。 str_const = str;
分配给该副本。 您可以将指针传递给指针,以能够在函数之外更改指针的值,但是您正在将字符串副本分配在堆栈上,因此一旦离开了reverse_const
的范围,字符串副本将变为无效,因此这里没有道理。
如果您想让字符串副本在reverse_const
的末尾reverse_const
下来,请使用malloc
分配数组,或者使用strdup
进行分配和复制。 您必须以某种方式返回通过malloc
malloc'ed
指针(通过指向指针参数的指针的返回值),然后调用者将有责任在完成malloc
分配的内存后free
它。
您需要编写函数,以便有某种方式返回修改后的参数。
一种这样的解决方案是通过引用传递 :
void reverse_const(const char **str_const){
const char *in = *str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
*str_const = out;
}
但是更好的方法是使用返回值:
char *reverse_const(const char *str_const){
const char *in = str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
return out;
}
返回类型可以是const char *
,但这是不必要的限制,因为您知道可以安全地修改返回的字符串。
注意,两个示例都使用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
返回指针
您还有其他选择,可以将指向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;
}
这里的问题是您修改了传递给reverse_const
的参数,但是C中的参数是按值传递的,这意味着它们已被复制。 你在功能修改该变量是原始指针的副本 ,改变副本当然不会改变原来的。
C没有此处需要的按引用传递 ,但是可以通过使用指针进行模拟 ,对于函数,您需要将指针传递给指针,然后使用解引用运算符*
修改指向的指针指针指向该函数,并在调用该函数时使用地址运算符&
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.