子函数修改参数问题

hougl1982 2010-01-18 05:48:40
问题描述:
子函数修改参数方法
int main(void)
{
char *p;
test(&p);
printf("p =%s\n",p);
int test(char **pt)
{
*pt = "hello world\n";
printf("p =%s\n",*pt);
}
这样的打印信息为:
p =hello world

p =hello world

但是如果修改为下面的方式,程序就无法运行:
int main(void)
{
char **p;
test(p);
printf("p =%s\n",*p);
}

int test(char **pt)
{
*pt = "hello world\n";
printf("p =%s\n",*pt);

}
没有打印信息

上面的程序是运行在x86上的(用gcc编译),如果将它重新编译在ARM上运行(),两个程序都能正常的打印信息:
p =hello world

p =hello world

这是为什么呢。

...全文
260 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
hougl1982 2010-01-19
  • 打赏
  • 举报
回复
谢谢楼上的各位,根据大家的解答,初始化指针后可以正常的运行程序。

但是在arm上运行,没有初始化指针的情况下也是OK的,不知道是什么原因。
arm运行在linux系统下,编译工具是arm-soft_uclibc-linux-gnu-cc
versaariel 2010-01-19
  • 打赏
  • 举报
回复
LZ怎么不给分。。。。MS大家回答的和你要的不一样。。。。
traceless 2010-01-18
  • 打赏
  • 举报
回复
void test(char ***pt);
int main(void)
{
char *arr[] = {"123555555555555", "12222222222222222"};
char **p = arr;
*p = NULL;
test(&p);
printf("main: p =%s\n",*p);
return 0;
}

void test(char ***pt)
{
char arr[] = "hello world\n"; //这样才不行
**pt = arr;
printf("test: p =%s\n",**pt);
}


Faint。。。更正17L打印地址作为佐证不成立啊
mostmark 2010-01-18
  • 打赏
  • 举报
回复
int main(void)
{
char *p;
test(&p);
printf("p =%s\n",p);
int test(char **pt)
{
*pt = "hello world\n";
printf("p =%s\n",*pt);
}
这段代码没有问题。常量字符串生存期为整个程序,不会有问题!

int main(void)
{
char **p;
test(p);
printf("p =%s\n",*p);
}
int test(char **pt)
{
*pt = "hello world\n";
printf("p =%s\n",*pt);
}
lz的这段代码明显是野指针,定义二级指针变量p,没有初始化,此时p的内容随机,可能为不可访问的内存地址,大多数是这样,当调用子函数test时,把常量字符串的地址付给*p,很明显这是在更该p(里面存的随机地址)所指向的内存地址的值,肯定会段错误!!!windonws安全机制差些,arm ads下有可能会通过,linux基本肯定报段错误!
第一段代码没错的原因是因为在子函数内部始终是修改的p的值,并没有修改*P, 修改*p肯定是野指针断错误!
常量 字符串是没有问题的,不要胡说, 为此赋上调试信息
(gdb) s
test (pt=0x8b22d0) at parament_func.c:12
12 *pt = "hello world\n";
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x08048397 in test (pt=0x8b22d0) at parament_func.c:12
12 *pt = "hello world\n";
断错误的产生并不是在print,所以常量字符串肯定是没有问题!显而是*P
的问题!
说的很多了。不知道lz明白了么?
traceless 2010-01-18
  • 打赏
  • 举报
回复
疏忽 疏忽。。不好意思

traceless 2010-01-18
  • 打赏
  • 举报
回复
恩 对 对 16说对了,正像那个情况,非法写入,9L和17L的代码都经过初始话了,没有像2L的情况了
traceless 2010-01-18
  • 打赏
  • 举报
回复
嘿嘿。。。

我知道了 原先没有注意到这个。

ls 的说程序错误了对的,但是说错了原因
主要是二级指针没有初始化,给它如9L那样的初始话就好了,错误原因不像你说的那样,呵呵

只要获得常量区/堆的地址不会随着函数而没了,就像在一个函数里new,在另一个函数里delete

错误因为没对二级指针初始化,而对**pt赋值,非法写入

void test(char ***pt);
int main(void)
{
char *arr[] = {"123555555555555", "12222222222222222"};
char **p = arr;
*p = NULL;
test(&p);
printf("main: p =%s addr of *p: %p\n",*p, (unsigned int)*p); //
return 0;
}

void test(char ***pt)
{
**pt = "hello world\n";
printf("test: p =%s and addr of **pt: %p\n",**pt, (unsigned int)**pt); //打印地址值
}

打印地址值就知道了
如9L那样初始化就可以test了

  • 打赏
  • 举报
回复
我似乎又看到同样的问题了 举个例子:

char *a="fdsaf"; //对的

char *a;
a="fdsafdsa"; //错的

因为:

char* a="fdsafsda"; 它等于 const char *a="fdsafdsa";

所以!
xboy 2010-01-18
  • 打赏
  • 举报
回复
to:traceless
你编译后运行一下看看,vs2008下运行报错“test.exe 中的 0x00411c43 处未处理的异常: 0xC0000005: 写入位置 0xcccccccc 时发生访问冲突”;
cygwin下运行没报错,但是这样做是错误的!
void test(char ***pt);
int main(void)
{
char **p;
test(&p);
printf("p =%s\n",*p);//0000
}

void test(char ***pt)
{
**pt = "hello world\n";//11111
printf("p =%s\n",**pt);
}

在“//11111”处,你是定义了"hello world\n";这个常量,
但是在test(...)调用结束后,"hello world\n";就不存在了,他的作用域只是在test内;
等程序执行到“//0000”处,p实际上指向的是一个已经不被承认的区域了,运气好的话这个区域没有被覆盖,可以编译执行通过,看编译器的了。
在cygwin下没报错应该是其下的编译器没有做严格的校验。



jernymy 2010-01-18
  • 打赏
  • 举报
回复
二级指针
traceless 2010-01-18
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 xboy 的回复:]
to traceless:
你的代码编译是没有问题,但是test()返回之后**p= "hello world\n";的生命周期已经结束,
p变成了野指针,此时再调用p是不对的吧
[/Quote]
你说的是这个呀

void test(char ***pt)
{
**pt = "hello world\n";
printf("p =%s\n",**pt);
}
没有成为野指针呀,你可以缩个短如果参数是这样就清楚些了吧MyCharP *pt; **pt就等于了MyCharP,
"hello world\n"是个常量 MyCharP = "hello world\n",它的地址不会随着函数的退出而没了,这样
相当于往MyCharP 地址里写入这个常量字符串开始处的地址。
xboy 2010-01-18
  • 打赏
  • 举报
回复
to traceless:
你的代码编译是没有问题,但是test()返回之后**p= "hello world\n";的生命周期已经结束,
p变成了野指针,此时再调用p是不对的吧
mymtom 2010-01-18
  • 打赏
  • 举报
回复
char **p;
test(p);
指针未分配空间也敢用?
versaariel 2010-01-18
  • 打赏
  • 举报
回复
LZ问的不是X86和ARM的区别吗=.=!
traceless 2010-01-18
  • 打赏
  • 举报
回复
不能老抠这些,LZ是笔误也不定

LZ,要知道指针也是变量,对于第二种情况,我帮你修改一下

void test(char **pt);
int main(void)
{
char *arr[] = {"123555555555555", "12222222222222222"};
char **p = arr;
*p = NULL;
test(p); //就像int a = 10; test(a);想在test修改a的值,然后反映到main函数里一样的错误
if (NULL == *p)
{
printf("main: p =%s\n",*p);
}
else
{
printf("*p is NULL\n");
}

}

void test(char **pt)
{
*pt = "hello world\n";
printf("test: p =%s\n",*pt);
}


你再结合2L的代码和你自己写的,好好理解一下指针和多级指针
swl82560397pq 2010-01-18
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hairetz 的回复:]
指针不申请内存,函数作用域都不对称。

楼主这代码,我真不知你想干嘛。
[/Quote]
是啊,LZ的大括号都不匹配,先把这个解决先了吧!
versaariel 2010-01-18
  • 打赏
  • 举报
回复
回5楼,有必要的,因为,不用的话是传值,但是MS,LZ问的不是这个问题
  • 打赏
  • 举报
回复
指针不申请内存,函数作用域都不对称。

楼主这代码,我真不知你想干嘛。
swl82560397pq 2010-01-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 traceless 的回复:]
LZ理解多级指针的引用和概念吗

C/C++ codevoid test(char***pt);int main(void)
{char**p;
test(&p);
printf("p =%s\n",*p);
}void test(char***pt)
{**pt="hello world\n";
printf("p =%s\n",**pt);
}
[/Quote]
敢问有用三级指针的必要吗?
versaariel 2010-01-18
  • 打赏
  • 举报
回复
错了,是2楼。。。。。
加载更多回复(3)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧