[英]Modify const char * in C
I am practicing for interviews. 我正在练习面试。 The problem Im currently stuck on is reversing a constant string in C. I know that since str2 is const, I can modify the location str2 points to, but not its value. Im当前遇到的问题是反转C中的常量字符串。我知道由于str2是const,因此我可以修改str2指向的位置,但不能修改其值。 I have a function below called reverse_const. 我下面有一个称为reverse_const的函数。 It will reverse the const char *str_const in place and print it. 它将const char * str_const反转到位并打印。 However, when I try to print st2 after reversal from the main method, the string isn't reversed anymore. 但是,当我尝试从main方法反转后打印st2时,字符串不再反转了。 Its like reverse_const() is temporarily changing the memory location of str2. 就像reverse_const()一样,它暂时更改了str2的存储位置。 What am I doing wrong here? 我在这里做错了什么?
#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);
}
When you pass by arguments, the function gets a copy. 当您传递参数时,该函数将获得一个副本。 str_const = str;
assigns to that copy. 分配给该副本。 You could pass a pointer to pointer to be able change the value of a pointer outside of your function, however you're allocating the string copy on the stack, and therefore the string copy becomes invalid once you leave the scope of reverse_const
so this wouldn't make sense here. 您可以将指针传递给指针,以能够在函数之外更改指针的值,但是您正在将字符串副本分配在堆栈上,因此一旦离开了reverse_const
的范围,字符串副本将变为无效,因此这里没有道理。
If you want a string copy that survives the end of the reverse_const
, allocate the array with malloc
or do both the allocation and the copying with strdup
. 如果您想让字符串副本在reverse_const
的末尾reverse_const
下来,请使用malloc
分配数组,或者使用strdup
进行分配和复制。 That you have to return the malloc'ed
pointer somehow (by a return value of via a pointer to pointer argument) and the caller will then have the responsibility to free
that malloc
'ed memory once it's done with it. 您必须以某种方式返回通过malloc
malloc'ed
指针(通过指向指针参数的指针的返回值),然后调用者将有责任在完成malloc
分配的内存后free
它。
You need to write your function so that you have some way to return the argument modified. 您需要编写函数,以便有某种方式返回修改后的参数。
One such solution is pass-by-reference : 一种这样的解决方案是通过引用传递 :
void reverse_const(const char **str_const){
const char *in = *str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
*str_const = out;
}
But a better way would be to use the return value: 但是更好的方法是使用返回值:
char *reverse_const(const char *str_const){
const char *in = str_const;
char *out = malloc(strlen(in)+1);
/* write to out */
return out;
}
The return type could be const char *
, but that's an unnecessary restriction since you know the returned string may be safely modified. 返回类型可以是const char *
,但这是不必要的限制,因为您知道可以安全地修改返回的字符串。
Note that both examples use malloc
. 注意,两个示例都使用malloc
。 Arrays cannot be passed back, in this manner, in C, as they exist on the stack and are destroyed when the function exits. 数组无法以这种方式在C语言中传回,因为它们存在于堆栈中,并在函数退出时销毁。
Whenever a long-running program uses malloc
, there really ought to be a matching free
somewhere in the code, or else you'll have a memory leak. 每当长时间运行的程序使用malloc
,在代码中的某处确实应该有一个匹配的free
,否则您将发生内存泄漏。 It's a pain, but something all C programmers must master. 这很痛苦,但是所有C程序员都必须掌握一些东西。
If you want the reversed str2
back in main()
, you will either need to pass an adequately sized buffer to reverse_const
to hold the reversed string, or you will need to dynamically allocate storage for it in reverse_const
(a local variable length array won't do): 如果要在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;
}
Output 输出量
$ ./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
Returning The Pointer 返回指针
You have an additional option to return the pointer to str
to assign to str2
in main()
. 您还有其他选择,可以将指向str
的指针返回给main()
str2
。 This is more what you would normally expect to see. 这通常是您期望看到的。 Let me know if you have any questions: 如果您有任何疑问,请告诉我:
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;
}
The problem here is that you modify the argument passed to reverse_const
, but arguments in C are passed by value meaning that they are copied. 这里的问题是您修改了传递给reverse_const
的参数,但是C中的参数是按值传递的,这意味着它们已被复制。 The variable you modify in the function is a copy of the original pointer, changing a copy will of course not change the original. 你在功能修改该变量是原始指针的副本 ,改变副本当然不会改变原来的。
C doesn't have pass by reference which is needed here, but it can be emulated by using pointers, in the case of your function you need to pass a pointer to the pointer, then use the dereference operator *
to modify what the pointer to pointer points to, and use the address-of operator &
when calling the function. C没有此处需要的按引用传递 ,但是可以通过使用指针进行模拟 ,对于函数,您需要将指针传递给指针,然后使用解引用运算符*
修改指向的指针指针指向该函数,并在调用该函数时使用地址运算符&
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.