BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #53293同步于 2011/6/7
CPP机器人发帖

[合集] 栈的地址是向低地址方向延伸的吧?

shenlei
2011/6/7镜像同步0 回复
☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 22:25:43 2011) 提到: $ cat stack.c #include <stdio.h> int main(void) { int a[10] = {1, 2, 3, 4, 5, 6, 7, 8}; printf("%x, %x, %d\n", (int)a, (int)&a[5], a[7]); return 0; } $ ./stack bfb00618, bfb0062c, 8 为什么后面的a[5]比前面的地址还高呢? ☆─────────────────────────────────────☆ taps (Awesome) 于 (Wed May 25 22:51:48 2011) 提到: google下栈帧吧,往下增长和数组内元素从低到高不冲突... 【 在 Thinker 的大作中提到: 】 : $ cat stack.c : #include <stdio.h> : int main(void) : ................... ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 23:21:34 2011) 提到: $ cat stack.s .file "stack.c" .section .rodata .LC0: .string "%x, %x, %d\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp pushl %edi pushl %ebx subl $72, %esp leal 24(%esp), %ebx movl $0, %eax movl $10, %edx movl %ebx, %edi movl %edx, %ecx rep stosl movl $1, 24(%esp) movl $2, 28(%esp) movl $3, 32(%esp) movl $4, 36(%esp) movl $5, 40(%esp) movl $6, 44(%esp) movl $7, 48(%esp) movl $8, 52(%esp) movl 52(%esp), %ecx leal 24(%esp), %eax leal 20(%eax), %ebx leal 24(%esp), %edx movl $.LC0, %eax movl %ecx, 12(%esp) movl %ebx, 8(%esp) movl %edx, 4(%esp) movl %eax, (%esp) call printf movl $0, %eax addl $72, %esp popl %ebx popl %edi movl %ebp, %esp popl %ebp ret .size main, .-main .ident "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1" .section .note.GNU-stack,"",@progbits 【 在 taps (Awesome) 的大作中提到: 】 : google下栈帧吧,往下增长和数组内元素从低到高不冲突... ☆─────────────────────────────────────☆ crazyhadoop (crazyhadoop) 于 (Wed May 25 23:40:51 2011) 提到: printf 入栈是 从右到左吧。 右面的在高地址,左边的在低地址。 ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 23:45:22 2011) 提到: 听说过这种说法,不知道是否一直都是这样? 不过这里,好像跟它关系不大吧,看这个呢 $ cat stack2.c #include <stdio.h> int main(void) { int a, b; a = 1; b = 2; printf("%x, %x\n", (int)&a, (int)&b); return 0; } $ ./stack2 bf89a45c, bf89a458 这回a的地址又比b的高了 【 在 crazyhadoop (crazyhadoop) 的大作中提到: 】 : printf 入栈是 从右到左吧。 右面的在高地址,左边的在低地址。 ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 23:46:26 2011) 提到: 而且这次,汇编代码中相应的地址也能看出是这样的了 $ cat stack2.s .file "stack2.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $16, %esp movl $1, -4(%ebp) movl $2, -8(%ebp) movl $0, %eax leave ret .size main, .-main .ident "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1" .section .note.GNU-stack,"",@progbits 【 在 Thinker (思想者) 的大作中提到: 】 : 听说过这种说法,不知道是否一直都是这样? : 不过这里,好像跟它关系不大吧,看这个呢 : $ cat stack2.c : ................... ☆─────────────────────────────────────☆ txmm (你被tx啦!) 于 (Wed May 25 23:48:26 2011) 提到: 和调用约定没关系 我觉得是由于数组吧,第一个元素地址最低? ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 23:49:54 2011) 提到: 数组确实比较特别,和普通的变量不同,不知道为什么 【 在 txmm (你被tx啦!) 的大作中提到: 】 : 和调用约定没关系 : 我觉得是由于数组吧,第一个元素地址最低? ☆─────────────────────────────────────☆ zenith (Dbrg77) 于 (Wed May 25 23:52:03 2011) 提到: 【 在 Thinker 的大作中提到: 】 : 数组确实比较特别,和普通的变量不同,不知道为什么 : 【 在 txmm (你被tx啦!) 的大作中提到: 】 : : 和调用约定没关系 : ................... 因为有指针?要不咋往后移啊。。。赫赫 ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 23:52:58 2011) 提到: 换个堆试试: $ cat heap.c #include <stdio.h> #include <stdlib.h> int main(void) { int *pa = (int *)malloc(3 * sizeof(int)); int *pb = (int *)malloc(1 * sizeof(int)); printf("%x, %x, %x\n", (int)pa, (int)&pa[1], (int)pb); return 0; } $ ./heap 8313008, 831300c, 8313018 地址一直在增长 似乎符合预期 【 在 Thinker (思想者) 的大作中提到: 】 : 数组确实比较特别,和普通的变量不同,不知道为什么 ☆─────────────────────────────────────☆ fentoyal (长风长歌) 于 (Wed May 25 23:55:12 2011) 提到: sf说的很对,可惜被无视了。。 “栈往下增长和数组内元素从低到高不冲突” ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Wed May 25 23:57:50 2011) 提到: 没无视,我明白他那句话,他说的很对,确实是这么回事 只是看看不同情况,会出现什么样子的结果 结果就是数组比较特别 【 在 fentoyal (长风长歌) 的大作中提到: 】 : sf说的很对,可惜被无视了。。 : “栈往下增长和数组内元素从低到高不冲突” ☆─────────────────────────────────────☆ rolan (迷途知返的羊) 于 (Thu May 26 06:43:32 2011) 提到: Linux是往低地址吧,windows是往高地址。 ☆─────────────────────────────────────☆ rebirthatsix (茫犭者-算法盲) 于 (Thu May 26 09:41:47 2011) 提到: 这。。。栈都是往低地址,windows没那么神 【 在 rolan 的大作中提到: 】 : Linux是往低地址吧,windows是往高地址。 : -- ☆─────────────────────────────────────☆ jkice (Bamboo) 于 (Thu May 26 14:00:35 2011) 提到: 【 在 Thinker 的大作中提到: 】 : 没无视,我明白他那句话,他说的很对,确实是这么回事 : 只是看看不同情况,会出现什么样子的结果 : 结果就是数组比较特别 : ................... 没明白,是说数组入栈的时候直接栈帧到达最后一个数组元素的地方,然后再往回走吗?就是整体上是栈往低地址走了,而在入栈的过程中栈帧往高地址走的,最后在指回最低的地方吗? ☆─────────────────────────────────────☆ jmpesp (心爱走天涯 ) 于 (Thu May 26 18:12:22 2011) 提到: 这个跟栈往低还是往高增长没啥关系。 数组每个元素的地址安排呢,纯粹是编译器按照自己的喜好去做的。 一般情况下的编译器都是喜欢后面元素比前面逻辑上的地址高。 这个其实要画图比较清晰,现在没时间,哪天有时间再补上。 一般情况下,编译器编译数组的时候,指令大概是类似这样: mov edx, ebp sub edx, 数组大小 这样处理后 edx就是数组首地址啦,以后的元素就往下面逻辑增长啦 ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Thu May 26 19:58:45 2011) 提到: 沙发说的很正确=。= 另外,不论printf或者什么函数,参数均是从右至左入栈,嗯。 ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Thu May 26 23:21:49 2011) 提到: 说的很对 判断栈的增长方向也不应该通过这个来判断 编译器相关 不具备可移植性 甚至不同版本的gcc策略都不同 【 在 jmpesp (心爱走天涯 ) 的大作中提到: 】 : 这个跟栈往低还是往高增长没啥关系。 : 数组每个元素的地址安排呢,纯粹是编译器按照自己的喜好去做的。 : 一般情况下的编译器都是喜欢后面元素比前面逻辑上的地址高。 : ................... ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Thu May 26 23:25:28 2011) 提到: 参数从右边还是从左边入栈,是和 调用约定(calling conventions) 相关的吧 __stdcall or __cdecl 【 在 zxsword (小绝) 的大作中提到: 】 : 沙发说的很正确=。= : 另外,不论printf或者什么函数,参数均是从右至左入栈,嗯。 ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Thu May 26 23:50:08 2011) 提到: 恰好给同学说过这个,以下是我的理解,不保证正确,仅供参考。 首先,栈是向下生长的。 例如printf,是变长的参数,对吧。如果从右至左入栈的话,那么char * fmt最后一个入栈,fmt恰好在栈顶。 凭借fmt,可以继续读出其余参数。 但是,如果从左至右的话,栈顶的元素是什么呢?是个double,是个int? 【 在 Thinker 的大作中提到: 】 : 参数从右边还是从左边入栈,是和 调用约定(calling conventions) 相关的吧 : __stdcall or __cdecl : 【 在 zxsword (小绝) 的大作中提到: 】 : ................... ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 00:03:28 2011) 提到: 这么说 好像也很有道理 不知道是不是因为printf比较特殊 【 在 zxsword (小绝) 的大作中提到: 】 : 恰好给同学说过这个,以下是我的理解,不保证正确,仅供参考。 : 首先,栈是向下生长的。 : 例如printf,是变长的参数,对吧。如果从右至左入栈的话,那么char * fmt最后一个入栈,fmt恰好在栈顶。 : ................... ☆─────────────────────────────────────☆ datou06415 (大头先生) 于 (Fri May 27 00:14:54 2011) 提到: 推荐你看看这个 http://www.tenouk.com/Bufferoverflowc/Bufferoverflow2a.html ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 00:28:53 2011) 提到: 好文章! 【 在 datou06415 (大头先生) 的大作中提到: 】 : 推荐你看看这个 : http://www.tenouk.com/Bufferoverflowc/Bufferoverflow2a.html ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 00:35:29 2011) 提到: 他这里说到意思是 在windows/intel平台,典型情况,是从右向左 As an example in Windows/Intel, typically, when the function call takes place, data elements are stored on the stack in the following way: The function parameters are pushed on the stack before the function is called. The parameters are pushed from right to left. 【 在 datou06415 (大头先生) 的大作中提到: 】 : 推荐你看看这个 : http://www.tenouk.com/Bufferoverflowc/Bufferoverflow2a.html ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 01:06:41 2011) 提到: Why are function arguments pushed on the stack in right to left order? To enable the existence of functions with a variable number of arguments, like printf. The function can extract the first one or two arguments and then use their values to deduce the total number of arguments on the stack. Order of evaluation of function arguments is unspecified, from C99 §6.5.2.2 paragraph 10: The only reason is for variadic functions: the first arguments popped from the stack are the "known" ones for the function, and it can determine from them how many other arguments it should read from the stack. Notice that, for this to work fine, in such calling conventions the stack cleanup is left to the caller, that knows how many arguments it pushed on the stack. This is slightly less efficient than callee-cleanup, because the cleanup code has to be written after each function call, while in calling conventions that do not allow variadic functions it can be embedded at the end of each function. Other than this, there's no particular reason, in facts there are several calling conventions (e.g. Pascal, Borland Fastcall) that do not admit variadic functions and push parameters left to right. The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call. Similar wording exists in C89. Just because the arguments are PUSHED in that order doesn't mean they must be EVALUATED in that order. You can't assume anything about the order of evaluation. With the different calling conventions, there are multiple ways of passing variables around. This is just the standard one with C/C++. The cdecl calling convention is used by many C systems for the x86 architecture.[1] In cdecl, function parameters are pushed on the stack in a right-to-left order. The cdecl calling convention is usually the default calling convention for x86 C compilers, although many compilers provide options to automatically change the calling conventions used. "Try this: int i=1; printf("%d %d %d", i++, i++, i); I get 2 1 3 with VS2003 " from: http://cboard.cprogramming.com/cplusplus-programming/92214-stack-push-order-function-arguments.html http://stackoverflow.com/questions/4031488/function-arguments-push-order http://stackoverflow.com/questions/376278/parameter-evaluation-order-before-a-function-calling-in-c http://en.wikipedia.org/wiki/X86_calling_conventions 结论: 1. 函数参数入栈顺序与调用约定有关,绝大多数情况都是从右向左依次入栈,但不能依赖这个特性;像printf这种变长参数的函数,肯定要从右向左,不过存在一些调用约定不允许 使用变长参数函数 2. 求值顺序与入栈顺序未必相同,求值顺序是未定义的,与实现有关,这是标准规定的 【 在 zxsword (小绝) 的大作中提到: 】 : 恰好给同学说过这个,以下是我的理解,不保证正确,仅供参考。 : 首先,栈是向下生长的。 : 例如printf,是变长的参数,对吧。如果从右至左入栈的话,那么char * fmt最后一个入栈,fmt恰好在栈顶。 : ................... ☆─────────────────────────────────────☆ uusad (god) 于 (Fri May 27 10:10:42 2011) 提到: 从高到低是说你申请数组的空间是从栈的高地址向低地址延伸得到的, 申请后得到的固定空间中a[0]就是最低地址,后面数组元素向高地址延伸,即数组中就跟栈分配空间没关系了 个人理解。。 ☆─────────────────────────────────────☆ a206206 (右将军府副手) 于 (Fri May 27 12:54:32 2011) 提到: 我很纳闷。。这个和调用约定有什么关系。。你打印的是数组元素的地址。和printf的活动记录的局部参数地址顺序有关系么。。 ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 15:26:50 2011) 提到: 你纳闷原因在于你没有看完所有楼 从而断章取义 后面有讨论到入栈顺序的问题 【 在 a206206 (右将军府副手) 的大作中提到: 】 : 我很纳闷。。这个和调用约定有什么关系。。你打印的是数组元素的地址。和printf的活动记录的局部参数地址顺序有关系么。。 ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Fri May 27 15:48:03 2011) 提到: Bingo!LZ自己没理解罢了,栈往低地址生长指的是 int a = 1; int b = 2; b的地址比a小 数组的话也像单个变量被当成一个整体,所以 int a = 1; int b[5]; 数组b的地址比a的地址小,但b内各元素的的地址一般是编译器确定,这部分和栈的生长方向没关系。 【 在 a206206 的大作中提到: 】 : 我很纳闷。。这个和调用约定有什么关系。。你打印的是数组元素的地址。和printf的活动记录的局部参数地址顺序有关系么。。 : -- ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Fri May 27 15:54:16 2011) 提到: 有没有搞错呀,这个例子哪里体现了printf()函数的参数入栈顺序了?只是把调用函数中的a,b地址打印出来罢了,并没有打印出被调用函数(printf)中的a,b地址。。。 【 在 Thinker 的大作中提到: 】 : 听说过这种说法,不知道是否一直都是这样? : 不过这里,好像跟它关系不大吧,看这个呢 : $ cat stack2.c #include <stdio.h> int main(void) { int a, b; a = 1; b = 2; printf("%x, %x\n", (int)&a, (int)&b); return 0; } $ ./stack2 bf89a45c, bf89a458 这回a的地址又比b的高了 【 在 crazyhadoop (crazyhadoop) 的大作中提到: 】 : printf 入栈是 从右到左吧。 右面的在高地址,左边的在低地址。 ☆─────────────────────────────────────☆ smilefufu (不水的FuFu) 于 (Fri May 27 18:01:48 2011) 提到: 同意“因为有指针”的说法。用指针引用数组的时候,pointer++一般是指取后一个元素。如果数组成员不是按序号从低地址向高地址排的话,编译器就得把所有的++当作--理解,我想应该没哪个编译器这么蛋疼吧。。。 至于其他独立的局部变量(如楼主第二个例子中的a和b),是由小到大还是由大到小应该是取决于编译器的,他乐意怎么排就怎么排呗。不过一般比较常见的好像还是由高往低排吧。 【 在 zenith 的大作中提到: 】 : : 数组确实比较特别,和普通的变量不同,不知道为什么 : : 【 在 txmm (你被tx啦!) 的大作中提到: 】 : : : 和调用约定没关系 : ................... ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 18:20:40 2011) 提到: 你看完所有楼再看看你自己的帖子 不要脸红就好 中国科学院的人 得严谨才对 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : 有没有搞错呀,这个例子哪里体现了printf()函数的参数入栈顺序了?只是把调用函数中的a,b地址打印出来罢了,并没有打印出被调用函数(printf)中的a,b地址。。。 : #include <stdio.h> : int main(void) : ................... ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Fri May 27 20:45:23 2011) 提到: 不好意思,我都看了。 那你到底看懂我两个回帖没有,看得出你对底层根本没入门(既然你先喷了)。请不要乱喷,特别是涉及到人身。 不过没明白意思当然觉得我说你的例子用错了这事也是错的。 【 在 Thinker 的大作中提到: 】 : 你看完所有楼再看看你自己的帖子 不要脸红就好 : 中国科学院的人 得严谨才对 : 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : ................... ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Fri May 27 20:49:18 2011) 提到: 我是菜b 求问主贴和printf的参数入栈顺序有任何关系吗? 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : 不好意思,我都看了。 : 那你到底看懂我两个回帖没有,看得出你对底层根本没入门(既然你先喷了)。请不要乱喷,特别是涉及到人身。 : 不过没明白意思当然觉得我说你的例子用错了这事也是错的。 : ................... ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Fri May 27 21:05:27 2011) 提到: 中途楼歪了一下,有人谈到函数调用入栈顺序,确实这个和主帖没关系。 __cdecl也就是标准C的入栈方式是参数从右到左入栈,但LZ给的例子也同样不能体现出参数入栈顺序,我看到这里就小吐槽了一下。 【 在 renne 的大作中提到: 】 : 我是菜b : 求问主贴和printf的参数入栈顺序有任何关系吗? : 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : ................... ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Fri May 27 21:07:38 2011) 提到: lz也从来没说到过他的例子能体现这点吧? 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : 中途楼歪了一下,有人谈到函数调用入栈顺序,确实这个和主帖没关系。 : __cdecl也就是标准C的入栈方式是参数从右到左入栈,但LZ给的例子也同样不能体现出参数入栈顺序,我看到这里就小吐槽了一下。 ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Fri May 27 21:10:45 2011) 提到: 我只是觉得他给的例子啥都不能说明干嘛还给出来 【 在 renne 的大作中提到: 】 : lz也从来没说到过他的例子能体现这点吧? : 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : : 中途楼歪了一下,有人谈到函数调用入栈顺序,确实这个和主帖没关系。 : ................... ☆─────────────────────────────────────☆ renne (歼灭天使 玲) 于 (Fri May 27 21:11:37 2011) 提到: 所以他这是求助楼 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : 我只是觉得他给的例子啥都不能说明干嘛还给出来 ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Fri May 27 21:13:10 2011) 提到: 那干嘛还搞个似是而非的教学帖出来,我第一帖就是回答帖呀,被LZ选择性的无视罢了。 【 在 renne 的大作中提到: 】 : 所以他这是求助楼 : 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : : 我只是觉得他给的例子啥都不能说明干嘛还给出来 : ................... ☆─────────────────────────────────────☆ zxsword (小绝) 于 (Fri May 27 21:29:58 2011) 提到: 是我不对,是我歪楼了=。= ☆─────────────────────────────────────☆ a206206 (右将军府副手) 于 (Fri May 27 21:31:53 2011) 提到: 【 在 Lennon 的大作中提到: 】 : 有没有搞错呀,这个例子哪里体现了printf()函数的参数入栈顺序了?只是把调用函数中的a,b地址打印出来罢了,并没有打印出被调用函数(printf)中的a,b地址。。。 : 【 在 Thinker 的大作中提到: 】 : : 听说过这种说法,不知道是否一直都是这样? : ................... 同意。 打印main的局部变量的地址。和printf的活动记录中的局部变量两码事。。。跟入栈顺序没关系 ☆─────────────────────────────────────☆ a206206 (右将军府副手) 于 (Fri May 27 21:34:20 2011) 提到: 【 在 zxsword 的大作中提到: 】 : 是我不对,是我歪楼了=。= : -- 软开版bm大驾光临。。 ☆─────────────────────────────────────☆ IETF (windancer) 于 (Fri May 27 23:13:16 2011) 提到: 和谐,和谐,讨论问题,讨论问题。 ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Fri May 27 23:21:03 2011) 提到: 后面有好几个帖自都在讨论入栈顺序的问题 和主贴的问题不同 主贴问题在19058号文章 就已经结束了 看看后面的逻辑 很明显是这样的 后面说的就都是函数参数入栈顺序的问题 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : 不好意思,我都看了。 : 那你到底看懂我两个回帖没有,看得出你对底层根本没入门(既然你先喷了)。请不要乱喷,特别是涉及到人身。 : 不过没明白意思当然觉得我说你的例子用错了这事也是错的。 : ................... ☆─────────────────────────────────────☆ Thinker (思想者) 于 (Sat May 28 00:54:29 2011) 提到: auto变量和数组都在一个栈桢内,顺序同编译器相关, 武断地认为谁先声明谁就先入栈,也无非是自作多情而已 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : 标 题: Re: 栈的地址是向低地址方向延伸的吧? : 发信站: 北邮人论坛 (Fri May 27 15:48:03 2011), 站内 : : Bingo!LZ自己没理解罢了,栈往低地址生长指的是 : int a = 1; : int b = 2; : b的地址比a小 b的地址未必要比a小,都在一个栈桢内,同样与栈的增长方向无关 : : 数组的话也像单个变量被当成一个整体,所以 : int a = 1; : int b[5]; : 数组b的地址比a的地址小,但b内各元素的的地址一般是编译器确定,这部分和栈的生长方向没关系。 : 数组b的地址也未必就比a小 ,原因同上 : : 【 在 a206206 的大作中提到: 】 : : 我很纳闷。。这个和调用约定有什么关系。。你打印的是数组元素的地址。和printf的活动记录的局部参数地址顺序有关系么。。 : : -- : -- : : ※ 来源:·北邮人论坛 http://bbs.byr.cn·[FROM: 124.16.137.*] ☆─────────────────────────────────────☆ txmm (你被tx啦!) 于 (Sat May 28 10:49:54 2011) 提到: 刚才看了下关于连接的书,虽然是同一个活动记录,但是也必然有先后之分,就如同经典的操作系统的栈都是从高向低,经典的编译器应该也是先声明则先入栈吧。如果不是。请举出反例 ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Sat May 28 16:03:19 2011) 提到: 呵呵,好歹态度还好了不少,那就继续专注问题说吧。 首先,我举的例子是在编译器无任何优化下,一般来说(呵呵,一般),b地址是比a地址小的。但其实不小也没关系,这里重点是谈论b[5]内部的元素地址嘛。我要表达的意思是b[5]是作为一个整体入栈的,所以它内部元素的顺序是和变量入栈顺序无关的。这就是我对LZ原帖的回答。 至于编译器优化的情况下,LZ的说法是对的,但我觉得讨论这个有点伪命题的感觉。毕竟有可能你的程序写的很烂,声明了很多无用的或可以被转换掉的变量,最后优化出来有一大堆变量都没影了,更别提什么入栈顺序了。所以我谈论的不是这种情况。 ps,auto变量和数组都在一个栈桢内,顺序同编译器相关?那叫与优化相关,在编译器认为不能提高性能的时候,入栈顺序会尽量按照声明顺序,因为那更符合原程序的语义。 【 在 Thinker 的大作中提到: 】 : auto变量和数组都在一个栈桢内,顺序同编译器相关, : 武断地认为谁先声明谁就先入栈,也无非是自作多情而已 : 【 在 Lennon (卡瓦伊) 的大作中提到: 】 : ................... ☆─────────────────────────────────────☆ Lennon (卡瓦伊) 于 (Sat May 28 16:13:15 2011) 提到: link的话都是涉及全局变量吧,全局变量不在栈里,所以应该和这个帖关系不大。 经典的编译器确实如你所说,但你说的还没有涉及优化方面的问题,优化后确实可能出现LZ说的情况。但我觉得他拿那个来反驳有点。。。见上帖 【 在 txmm 的大作中提到: 】 : 刚才看了下关于连接的书,虽然是同一个活动记录,但是也必然有先后之分,就如同经典的操作系统的栈都是从高向低,经典的编译器应该也是先声明则先入栈吧。如果不是。请举出反例 : -- ☆─────────────────────────────────────☆ txmm (你被tx啦!) 于 (Sat May 28 17:11:30 2011) 提到: 刚问了下大牛。对于同一组局部变量。地址顺序没有任何保证。 唯一肯定的是数组元素一定是连续存储且第一个元素地址最低
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。