这是我的测验问题(警告,冗长):
给定以下程序,重新排序printf行,以便对打印的值进行排序 如果在Sun SPARC体系结构上编译和运行,则从最小到最大。这些行打印出的十六进制地址 使用printf()格式说明符%p(指针)的程序的不同部分(不是赋值)。
#include <stdio.h>
#include <stdlib.h>
int a = 420;
void foo() {
int b;
/* 1 */ printf( "b --> %p\n", &b );
}
int
main( int argc, char *argv[] ) {
int c;
int d = 42;
static int e;
/* 2 */ (void) printf( "foo() --> %p\n", foo );
/* 3 */ (void) printf( "e --> %p\n", &e );
/* 4 */ (void) printf( "malloc --> %p\n", malloc(420) );
foo();
/* 5 */ (void) printf( "d --> %p\n", &d );
/* 6 */ (void) printf( "argv --> %p\n", &argv );
/* 7 */ (void) printf( "a --> %p\n", &a );
/* 8 */ (void) printf( "c --> %p\n", &c );
/* 9 */ (void) printf( "argc --> %p\n", &argc );
return 0;
}
我在C中运行了这个程序并获得了这些打印值:
2 foo() --> 10594
3 e --> 2099c
4 malloc --> 209a8
1 b --> ffbff1b4
5 d --> ffbff228
6 argv --> ffbff288
7 a --> 20974
8 c --> ffbff22c
9 argc --> ffbff284
我的问题很好....为什么?我试图手工完成这个,记住每个变量保存的位置(堆栈,BSS,数据等),并试图命令它们说这是变量的顺序,从低内存到高内存:
这应该是从最小到最小的组织方式吗?
LOW MEMORY - text (labels, function names):
2 - foo
data (initialized global/static vars):
7 - a
BSS ( initialized global/static vars:
3 - e
stack (local vars):
9 - argc
6 - argv[]
8 - c
5 - d
1 - b
4 - ptr returned by malloc
HIGH MEMORY
如果它与打印的内存值发生冲突,我不知道为什么,有人会介意解释原因吗?谢谢:)!
答案 0 :(得分:2)
唯一的冲突是在堆栈区域。
如果堆栈从较高地址变为较低地址(通常情况下)或其他方式,则取决于系统。
在堆栈的底部有argc
和argv
,然后是c
和d
,然后是b
。
当参数以“错误的方式”推送到堆栈时,首先推送argv
,然后推送argc
,为argc
提供一个较小的地址。显然,c
和d
也是如此;但我认为编译器可以自由选择放置局部变量的位置。
b
的地址最小,因为它被推迟了。
此外,malloc()
返回的ptr不在堆栈上,而是在堆上,它在BSS
区域之后立即启动。
这就是解决方案
LOW MEMORY
text (labels, function names):
2 - foo
data (initialized global/static vars):
7 - a
BSS (initialized global/static vars):
3 - e
heap:
4 - ptr returned by malloc
stack (local vars):
1 - b
5 - d
8 - c
9 - argc
6 - argv[]
HIGH MEMORY
这种不直观的参数传递顺序的原因是因为有一个变量llength参数的选项。您可能知道函数printf()
,其中所有这些调用都是有效的:
printf("Hello\n");
printf("Hello %s\n", name);
printf("Hello User #%d (%s)\n", nr, name);
只有调用者才知道变量的数量。被调用的函数知道堆栈的顶部,并希望对第一个参数有一个已定义的偏移量。所以唯一的选择是将第一个参数放在堆栈的顶部,从而开始从最后一个推到第一个。 通常情况下,数据实际上没有被推送,但是堆栈指针会手动减少,并且以这种方式保留的内存随后会被填充。