har*_*ari 1 c gcc struct pointers freebsd
动机:将结构传递给函数,例如我们可以在任何函数中更改它并检索任何函数中的任何值.
我从以下网站获取了这些代码:http://cboard.cprogramming.com/c-programming/126381-passing-structure-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;
}
Run Code Online (Sandbox Code Playgroud)
它在ubuntu上的**gcc版本4.4.3上按预期工作
$ gcc -o struct struct_passing.c
$ ./struct
Before: same
inside f3 x: changed
After: changed
Run Code Online (Sandbox Code Playgroud)
但是在freebsd上的gcc版本4.2.1上,我无法检索"bob-> x"的更改值.我没有inside f3 x: changed.我得到了垃圾.
为什么?
一切看起来都很好.在调试器中运行这样的小样本程序总是有益的,看看到底发生了什么.如果您不了解gdb,现在是开始的好时机.我已经从你的代码中创建了struct_passing.[ch],让我们来看看:
[wes@eeegor ~]$ gcc -v
Using built-in specs.
Target: i386-undermydesk-freebsd
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 4.2.1 20070719 [FreeBSD]
Run Code Online (Sandbox Code Playgroud)
是的,同样的编译器.编译进行调试:
[wes@eeegor ~/src]$ cc -g -o struct struct_passing.c
Run Code Online (Sandbox Code Playgroud)
并运行它:
[wes@eeegor ~/src]$ gdb struct
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...
Run Code Online (Sandbox Code Playgroud)
好吧,我们可能想知道main()上发生了什么,所以......
(gdb) b main
Breakpoint 1 at 0x80484c0: file struct_passing.c, line 21.
(gdb) run
Starting program: /usr/home/wes/src/struct
Breakpoint 1, main () at struct_passing.c:21
21 int main(void) {
Run Code Online (Sandbox Code Playgroud)
我们主要使用tep来进入函数,并且(n)ext来跳过我们不希望看到内部的函数,比如printf().我们偶尔也会发现一些东西.
(gdb) n
main () at struct_passing.c:23
23 foo.x = "same";
Run Code Online (Sandbox Code Playgroud)
我们还没有执行这一行,所以如果我们看一下foo,它可能会包含垃圾:
(gdb) p foo
$1 = {x = 0x80482c5 "\203Ä\fÃ"}
Run Code Online (Sandbox Code Playgroud)
是的,正如预期的那样,x指向一些垃圾字符串.那是因为foo和扩展foo.x在main()函数的堆栈上创建了,并且堆栈只包含之前留下的任何随机垃圾.
(gdb) n
24 printf("Before: %s\n", foo.x);
(gdb) n
Before: same
25 f1(&foo);
(gdb) s
f1 (bob=0xbfbfec40) at struct_passing.c:18
18 f2(bob);
(gdb) p bob
$2 = (thing_t *) 0xbfbfec40
Run Code Online (Sandbox Code Playgroud)
所以我们进入f1()并看到我们已经正确地将foo的地址传递给了函数.请注意gdb(p)rint函数如何始终知道它打印的类型?在这种情况下,查看结构的地址不是很有用,所以:
(gdb) p *bob
$3 = {x = 0x804857c "same"}
Run Code Online (Sandbox Code Playgroud)
哦,好的,结构看起来应该是这样的.让我们继续,直到我们改变它:
(gdb) s
f2 (bob=0xbfbfec40) at struct_passing.c:14
14 f3(bob);
(gdb) p *bob
$4 = {x = 0x804857c "same"}
(gdb) s
f3 (bob=0xbfbfec40) at struct_passing.c:9
9 f4(bob);
(gdb) p *bob
$5 = {x = 0x804857c "same"}
(gdb) s
f4 (bob=0xbfbfec40) at struct_passing.c:5
5 bob->x = "changed";
Run Code Online (Sandbox Code Playgroud)
记住,我们还没有执行第5行,所以"bob"应该仍然是相同的:
(gdb) p *bob
$6 = {x = 0x804857c "same"}
Run Code Online (Sandbox Code Playgroud)
是的,让我们执行第5行再看一遍:
(gdb) n
6 }
(gdb) p *bob
$7 = {x = 0x8048563 "changed"}
Run Code Online (Sandbox Code Playgroud)
所以"bob"确实发生了变化.让我们继续前进,看看它是否仍然在main()中更改:
(gdb) n
f3 (bob=0xbfbfec40) at struct_passing.c:10
10 printf("inside f3 x: %s\n", bob->x);
(gdb) n
inside f3 x: changed
11 }
(gdb) n
f2 (bob=0xbfbfec40) at struct_passing.c:15
15 }
(gdb) n
f1 (bob=0xbfbfec40) at struct_passing.c:19
19 }
(gdb) n
main () at struct_passing.c:26
26 printf("After: %s\n", foo.x);
(gdb) n
After: changed
27 return 0;
Run Code Online (Sandbox Code Playgroud)
所以我们得到了我们的期望.此时,我们即将从main()返回,最好让调试器继续运行,这样你就不用一半来完成C运行时启动代码的尾端了:
(gdb) c
Continuing.
Program exited normally.
(gdb) Quit
(gdb)
Run Code Online (Sandbox Code Playgroud)
让我们退出调试器并正常运行它以确保我们得到相同的输出.如果我们不......那真是奇怪
(gdb) q
[wes@eeegor ~/src]$ ./struct
Before: same
inside f3 x: changed
After: changed
Run Code Online (Sandbox Code Playgroud)
哦,好,星星依然闪耀.我不确定你的情况发生了什么,让我们尝试编译并运行它:
[wes@eeegor ~/src]$ gcc -o struct struct_passing.c
[wes@eeegor ~/src]$ ./struct
Before: same
inside f3 x: changed
After: changed
Run Code Online (Sandbox Code Playgroud)
现在,让我们改进您的错误报告.给我们输出'uname -a','gcc -v'和'ld -v',这样我们就可以确切地找到你正在使用的系统.另请阅读关于如何编写错误报告的"Joel on Software"文章.:)