C中的指针是如何工作的?

C中的指针是如何工作的?,c,pointers,C,Pointers,C语言中有一个程序: void bar(char *str) { str = "ok bye!"; } int main(int argc, char *argv[]) { char *str = "hello world!"; bar(str); printf("%s\n", str); return EXIT_SUCCESS; } 然而,它说main方法中的值str不会受到bar方法的影响,但这是为什么呢?我的理解是,char*str=“你好,世界!”此代

C语言中有一个程序:

void bar(char *str) {
   str = "ok bye!";
}

int main(int argc, char *argv[]) {
   char *str = "hello world!";
   bar(str);
   printf("%s\n", str); 
   return EXIT_SUCCESS;
}
然而,它说main方法中的值
str
不会受到bar方法的影响,但这是为什么呢?我的理解是,
char*str=“你好,世界!”此代码使指针
str
指向字符串“hello world”。然后是
bar(str)
使
str
指针指向字符串“ok bye!”。但为什么结果仍然是“你好世界”


解决方案是将bar方法的参数更改为双指针,为什么要这样做?

函数
bar
中的
str
指针只是一个局部变量。您不能使用此命令更改主代码中的
str
变量。此概念称为按值调用。 但既然你真的想改变它指向的内存,你可以改变它。请注意不要覆盖已分配内存的长度

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void bar(char *str, size_t s) {
   strncpy(str, "ok bye!", s);
   str[s-1] = '\0'; // terminate for the case that the string was cropped
}

int main(int argc, char *argv[]) {
   char str[20] = "hello world!";
   printf("%s\n", str); 
   bar(str, sizeof(str));
   printf("%s\n", str); 
   return EXIT_SUCCESS;
}
#包括
#包括
#包括
空栏(字符*字符,大小){
strncpy(str,“好的,再见!”,s);
str[s-1]='\0';//如果字符串被裁剪,则终止
}
int main(int argc,char*argv[]){
char str[20]=“你好,世界!”;
printf(“%s\n”,str);
棒材(str,sizeof(str));
printf(“%s\n”,str);
返回退出成功;
}

有一个整体可以帮助您解决这个难题。提示:
str=x
*str=x
之间有什么不同?在装配/机器指令级别会发生什么?问自己同样的问题,不要涉及指针。给定
voidbar(intx){x=42;}
,您是否期望
y=0;巴(y)
会改变
y
的值吗?@jamesdlin一个更干净的代码会调用
bar(24)
。现在很明显,那里没有变量可以将
42
带回
main
。代码非常危险,并且具有未定义的行为,因为main中的
str
实际上是一个
const char*
。不允许更改它引用的内存。请注意,首先您应该更改
char*str=“hello world!”
字符str[]=“你好,世界!”
您有两个完全不同的变量,都称为
str
。这让你认为改变一个应该改变另一个。如果你给他们起不同的名字,就会清楚得多。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void bar(char *str, size_t s) {
   strncpy(str, "ok bye!", s);
   str[s-1] = '\0'; // terminate for the case that the string was cropped
}

int main(int argc, char *argv[]) {
   char str[20] = "hello world!";
   printf("%s\n", str); 
   bar(str, sizeof(str));
   printf("%s\n", str); 
   return EXIT_SUCCESS;
}