将结构指针传递给函数不起作用
动机:将结构传递给函数,例如我们可以在任何函数中更改它并在任何函数中检索任何值。
我从以下位置获取了此代码: http://cboard.cprogramming.com/c-programming/126381-passing-struct-reference-through-4-functions.html#post942397
我稍微调整一下,它是:
struct_passing.h
typedef struct thing {
char *x;
}thing_t;
struct_passing.c
#include <stdio.h>
#include "struct_passing.h"
void f4(thing_t *bob) {
bob->x = "changed";
}
void f3(thing_t *bob) {
f4(bob);
printf("inside f3 x: %s\n", bob->x);
}
void f2(thing_t *bob) {
f3(bob);
}
void f1(thing_t *bob) {
f2(bob);
}
int main(void) {
thing_t foo;
foo.x = "same";
printf("Before: %s\n", foo.x);
f1(&foo);
printf("After: %s\n", foo.x);
return 0;
}
它在 ubuntu 上的 **gcc 版本 4.4.3 上按预期工作,
$ gcc -o struct struct_passing.c
$ ./struct
Before: same
inside f3 x: changed
After: changed
但在 freebsd 上的 gcc 版本 4.2.1 上,我无法检索“bob->x”的更改值。我没有内部 f3 x: 已更改
。我反而得到垃圾。
为什么?
Motive: Passing struct to functions such as we can change it in any function and retrieve any value in any function.
I picked up this code from: http://cboard.cprogramming.com/c-programming/126381-passing-structure-reference-through-4-functions.html#post942397
I tweaked it a little and here it is:
struct_passing.h
typedef struct thing {
char *x;
}thing_t;
struct_passing.c
#include <stdio.h>
#include "struct_passing.h"
void f4(thing_t *bob) {
bob->x = "changed";
}
void f3(thing_t *bob) {
f4(bob);
printf("inside f3 x: %s\n", bob->x);
}
void f2(thing_t *bob) {
f3(bob);
}
void f1(thing_t *bob) {
f2(bob);
}
int main(void) {
thing_t foo;
foo.x = "same";
printf("Before: %s\n", foo.x);
f1(&foo);
printf("After: %s\n", foo.x);
return 0;
}
It works as expected on **gcc version 4.4.3 on ubuntu
$ gcc -o struct struct_passing.c
$ ./struct
Before: same
inside f3 x: changed
After: changed
But on gcc version 4.2.1 on freebsd, I cannot retrieve the changed value of "bob->x". I do not get inside f3 x: changed
. I get garbage instead.
Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对我来说一切看起来都很好。在调试器中运行这样的小示例程序总是很有启发性的,以查看到底发生了什么。如果您不了解 gdb,现在是开始的好时机。我已经根据您的代码创建了 struct_passing.[ch],让我们看看:
是的,相同的编译器。编译调试:
并运行它:
好的,我们可能想知道从 main() 开始发生了什么,所以...
我们主要使用 (s)tep 来单步执行函数,使用 (n)ext 来单步执行函数我们不想看到它的内部,比如 printf()。我们也可能偶尔(p)打印一些东西。
我们还没有执行这一行,所以如果我们查看 foo,它可能会包含垃圾:
是的,正如预期的那样,x 指向一些垃圾字符串。这是因为 foo 以及扩展后的 foo.x 是在 main() 函数的堆栈上创建的,而堆栈中只有之前留下的随机垃圾。
所以我们进入 f1() 并看到我们已经正确地将 foo 的地址传递到函数中。请注意 gdb (p)rint 函数如何始终知道其打印内容的类型?在这种情况下,查看结构的地址并不是很有用,因此:
哦,很好,结构看起来仍然像它应该的那样。让我们继续下去,直到我们改变它:
记住,我们还没有执行第 5 行,所以“bob”应该仍然是相同的:
是的,所以让我们执行第 5 行并再看一遍:
所以“bob”确实改变了。让我们继续看看 main() 中是否仍然发生了变化:
所以我们得到了我们所期望的结果。此时,我们即将从 main() 返回,最好让调试器继续,这样您就不会一半地浏览 C 运行时启动代码的尾部:
让我们退出调试器并正常运行它确保我们得到相同的输出。如果我们不这样做,那就太奇怪了……
哦,太好了,星星还在闪烁。我不确定你的情况发生了什么,让我们尝试像你一样编译并运行它:
所以现在,让我们改进你的错误报告。向我们提供“uname -a”、“gcc -v”和“ld -v”的输出,以便我们准确找出您正在使用的系统。另请阅读“Joel on Software”文章,了解如何编写错误报告。 :)
Everything looks just fine to me. It's always instructive to run a small sample program like this in the debugger, to see what's really happening. If you don't know gdb, now is a great time to start. I've created struct_passing.[ch] from your code, let's have a look:
Yup, same compiler. Compile for debugging:
And run it:
OK, we probably want to know what's happening from main() on, so...
We'll mostly use (s)tep to step into functions, and (n)ext to step over functions we don't want to see the inside of, like printf(). We may also occasionally (p)rint something.
We haven't yet executed this line, so if we look at foo, it will probably contain garbage:
Yup, as expected, x points to some garbage string. That's because foo, and by extension foo.x, got created on the stack in the main() function, and the stack just has whatever random junk was left around before.
So we step into f1() and see that we have correctly passed the address of foo into the function. Notice how the gdb (p)rint function always knows the type of what it's printing? In this case, seeing the address of the structure isn't very useful, so:
Oh, good, the structure still looks like it should. Let's keep going until we change it:
Remember, we haven't executed line 5 yet, so "bob" should still be the same:
Yup, so let's execute line 5 and look again:
So "bob" did get changed. Let's keep going and see if it's still changed up in main():
So we got what we expected. At this point, we're about to return from main(), it's best to just let the debugger continue so you don't half to walk through the tail end of the C runtime startup code:
Let's exit the debugger and run it normally to make sure we get the same output. It would be really weird if we didn't...
Oh, good, the stars are still shining. I'm not sure what happened in your case, let's try compiling as you did and run it:
So now, let's improve your bug report. Give us the output of 'uname -a', 'gcc -v', and 'ld -v' so we can find out exactly what system you're using. Also read the 'Joel on Software' article(s) about how to write a bug report. :)
在我看来,该代码是完全合法的,并且应该有效......
我怀疑这个问题与 gcc 4.2.1 的优化器如何处理字符串常量有关。
您可以尝试以下编译命令行,以检查这是否属实:
我建议还尝试以下代码变体,看看是否获得更好的结果:
In my opinion the code is perfectly legal and it should work...
I suspect the problem is related to how the optimizer of gcc 4.2.1 handles string constants.
You can try the following compilation command line, to check if this is true:
I suggest also to try the following code variation, to see if you get a better result: