鱼C论坛

 找回密码
 立即注册
查看: 2334|回复: 14

这段代码为什么不能改变a 的值

[复制链接]
发表于 2012-2-18 08:19:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

#include <stdio.h>
void change(char *t)
{
t = "ABC";
}
int main(int argc, char *argv[])
{
char a[100] = "abc";
printf("a = %s\n", a);
change(a);
printf("b = %s\n", a);
return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-2-18 09:17:27 | 显示全部楼层
本帖最后由 yipwing 于 2012-2-18 09:17 编辑

{:2_28:}  这个算是测试嘛? 如果是测试,咱就不写答案了...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-2-18 11:11:50 | 显示全部楼层
跟踪一下内存,弄明白了。
发表一下跟大家分享。
t = "ABC";
此时 t 获得 "ABC"的指针。
同时把 t 原来的地址给替换了。
所以 a[]数组的值没被改变。

总结:
对于字符串指针的操作 不能使用 =
而用strcpy函数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-2-18 21:59:03 | 显示全部楼层
改变形参没啥用才是问题所在
就像你写个函数
fun(char *lp)
{
  lp = (char *)malloc(10);
}
实参也不会改变的
因为你改变的是形参副本lp
解决方法形参改指针引用 或二级指针
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-2-19 18:46:13 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-2-19 19:12:40 | 显示全部楼层
#include <stdio.h>
void change(char **t)
{
        *t = "ABC";
}
int main(int argc, char *argv[])
{
        char *a = "abc";
        printf("a = %s\n", a);
        change(&a);
        printf("b = %s\n", a);
        return 0;
        
}
二级指针的例子,我帮他给
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-2-19 19:20:25 | 显示全部楼层
仰望天上的光 发表于 2012-2-19 19:12
二级指针的例子,我帮他给

多谢光哥,我没用过二级指针。
你能做一些文字说明吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-2-19 20:09:03 | 显示全部楼层

#include <stdio.h>
void change(char*& t)
{
    t = "ABC";
}
int main(int argc, char *argv[])
{
char *a = "abc";
printf("a = %s\n", a);
change(a);
printf("b = %s\n", a);
return 0;
}
引用就是别名
就相当于a = "ABC"
你写的改的是实参
strcpy可以是因为
strcpy改的是指针指向的值 非指针值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-2-19 20:24:50 | 显示全部楼层
仰望天上的光 发表于 2012-2-19 19:12
二级指针的例子,我帮他给

大概有点明白了。
之前经常用 void fun(int *a)的测试
我大概是被void change(char *t)这种相似的格式给误导了。
因为传送的参数本身就是个指针。
在子程序中修改原程序的值,就必须用解引用。所以就用到二级指针了。
而跟strcpy的方式修改又有本质不同。
后者是将原地址上的“abc"强制复盖成“ABC”
前者是定义另一段“ABC”的地址赋给原指针。
我这样的理解正确吗。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-2-19 21:02:16 | 显示全部楼层
其实无所谓什么二级指针,这个问题的本质就是函数的值传递机制。
假设C语言里的一个函数调用(如果用C++的话先不考虑引用):
f(a);
我们都不用看f的定义就知道,这个函数调用后不可能改变a的值,充其量只能改变a的副本的值。因为传进函数f的不是a,而是a的副本。

但函数调用g(&a);就有可能改变a的值,因为此时传进函数g的是变量a地址的副本,虽然也是副本,但注意,不是"a的副本",而是“a地址的副本”。根据前面的描述我们可以断定此函数必不能改变"a的地址"
但是却有可能能改变a的值,因为“a地址的副本”指向了变量a

所以得出结论:
1.C语言值传递机制使得传给函数的实参必定不能被改变。
2.而你如果要让函数改变某个变量的值怎么办呢?就只能把该变量的地址传给函数。

所以,这题我写的代码里:
如果是change(a);的话,a的值是不可能被改变的(你现在根本不需要知道a是什么类型)

而如果是change(&a);的话,就很有可能改变a的值

再结合a是个指针,我们这题需要改变它的值使它指向另一个字符串,所以一定要写change(&a);在知道这一点后,函数的原型以及定义就都很清楚了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-2-19 21:02:46 | 显示全部楼层
Mr.C 发表于 2012-2-19 20:24
大概有点明白了。
之前经常用 void fun(int *a)的测试
我大概是被void change(char *t)这种相似的格式给 ...

正确
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-2-19 22:55:50 | 显示全部楼层
仰望天上的光 发表于 2012-2-19 21:02
其实无所谓什么二级指针,这个问题的本质就是函数的值传递机制。
假设C语言里的一个函数调用(如果用C++的话 ...

谢谢,你的说明让我理解更深刻。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2015-8-17 07:54:50 | 显示全部楼层
咱们码农有力量,嘿
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-17 18:47:21 | 显示全部楼层
传过去变量a的地址 然而t是一个形参  指向了变量a首地址
然而t = "ABC" 只是把常量"ABC"的地址 赋给 形参t     形参t指向的不再是变量a 而是字符串"ABC"
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-17 18:51:08 | 显示全部楼层
#include <iostream>

int func(char *a)
{
        a[0] = 'C';
        return 0;
}
int main(void)
{
        char a[] = {"abc"};
        func(a);
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-26 07:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表