拈花小仙 发表于 2014-3-28 18:28:48

一个C语言的小问题

本帖最后由 拈花小仙 于 2014-3-28 20:23 编辑

#include <stdio.h>
int main()
{
    int a = {1,2,3,4,5,6,7,8,9,10};
    printf("%p\n",&a);
    printf("%p\n",a);
    printf("%p\n",a + 1);
    printf("%p\n",&a + 1);
    printf("%d\n",sizeof(a));         //这里a不是代表数组首元素地址吗?,为什么是40
    printf("%d\n",sizeof(&a));      
    return 0;
}
输出结果:

0017FDE4
0017FDE4
0017FDE8
0017FE0C
40
4

这题几个朋友说法不一,请不要看了结果后用个人理解,给个准确的定义来解释一样,谢谢!

青玄 发表于 2014-3-28 18:28:49

嗯............,其实说白了,就是与VC的入栈顺序有关吧!VC的入栈顺序是自右往左的,所以数组的最后一个元素就是栈中的第一个元素,而数组的第一个元素就是栈中的最后一个元素,根据栈的后进先出原理,那么数组的第一个元素的大小,其实就是栈的偏移大小。

牡丹花下死做鬼 发表于 2014-3-28 20:00:12

我用VC++6.0 两个都是 40

oggplay 发表于 2014-3-28 20:19:20

本帖最后由 oggplay 于 2014-3-28 20:21 编辑

sizeof(a)求的是数组大小,我的编译器定义为4*10=40
如果你的系统是32位的,最后一项肯定是4

拈花小仙 发表于 2014-3-28 20:22:40

oggplay 发表于 2014-3-28 20:19 static/image/common/back.gif
sizeof(a)求的是数组大小,我的编译器定义为4*10=40
如果你的系统是32位的,最后一项肯定是4

看结果我也知道是数组大小了,可a+1只移动4个字节,而&a却移动40个字节呢?

青玄 发表于 2014-3-28 20:23:14

我也一样,两个都是40,其实这个40我想是这样的,这些数据都是在栈中的,而VC的入栈顺序是自右往左的,所以当最后一个元素进栈的时候,也就是数组的第一个元素,这样,一个数据时4个字节,那么10个的话,就是40个,而数组名指向的也是数组的第一个元素,而第一个元素在栈中就是第40个元素啊!而且不管是a或&a它都指向的是同一个地址!
下面是反编译的情况,你看一下就明白了:
4:      int a = {1,2,3,4,5,6,7,8,9,10};
00401028   mov         dword ptr ,1
0040102F   mov         dword ptr ,2
00401036   mov         dword ptr ,3
0040103D   mov         dword ptr ,4
00401044   mov         dword ptr ,5
0040104B   mov         dword ptr ,6
00401052   mov         dword ptr ,7
00401059   mov         dword ptr ,8
00401060   mov         dword ptr ,9
00401067   mov         dword ptr ,0Ah
5:      printf("%p\n",&a);
0040106E   lea         eax,
00401071   push      eax
00401072   push      offset string "%p\n" (00422020)
00401077   call      printf (00401120)
0040107C   add         esp,8
6:      printf("%p\n",a);
0040107F   lea         ecx,
00401082   push      ecx
00401083   push      offset string "%p\n" (00422020)
00401088   call      printf (00401120)
0040108D   add         esp,8





拈花小仙 发表于 2014-3-28 20:25:47

青玄 发表于 2014-3-28 20:23 static/image/common/back.gif
我也一样,两个都是40,其实这个40我想是这样的,这些数据都是在栈中的,而VC的入栈顺序是自右往左的,所以 ...

我不懂汇编,能用C的标准或定义解释下吗?{:7_174:}

swsm 发表于 2014-3-28 20:34:13


#include <stdio.h>
int main()
{
    int a = {1,2,3,4,5,6,7,8,9,10};
    int *p = a;
   
    printf("%d (十进制打印a的首地址)\n", &a);               //这是打印a数字的首地址

    printf("%p\n",&a);            //%p一般以十六进制整数方式输出指针的值
    printf("%p\n",*p);            //这条为验证上面的结论

    printf("%p\n",a);               //以十六进制整数方式打印a的首地址
    printf("%p\n",a + 1);         //以十六进制整数方式打印a +4的首地址

    printf("%p\n",&a + 1);          //以十六进制整数方式打印(a +sizeof(a))的首地址   (sizeof(a) = 40 = 4 * 10)

    printf("%d\n",sizeof(a));         //a代表数组首元素地址,为什么是40(上面的语句证明了a中有10个整型数据,所以为40)
    printf("%d\n",sizeof(&a));      //&a ==a都是表示a数组的首地址,呵呵!
    return 0;
}
//我又来了,你看看我的解释怎么样?呵呵!程序已经注释和验证了!!

无名侠 发表于 2014-3-28 20:34:31

sizeof(&a) 不知道可不可以。

拈花小仙 发表于 2014-3-28 20:36:01

无名侠 发表于 2014-3-28 20:34 static/image/common/back.gif
sizeof(&a) 不知道可不可以。

最后一个是&a的输出结果,可a和&a的区别被这题搞乱了,我现在不知哪个代表整个数组,哪个代表数组首元素地址了

拈花小仙 发表于 2014-3-28 20:40:27

青玄 发表于 2014-3-28 20:35 static/image/common/back.gif
嗯............,其实说白了,就是与VC的入栈顺序有关吧!VC的入栈顺序是自右往左的,所以数组的最后一个元 ...

那么a是首元素地址,&a是整个数组的地址吗?这个问题出在sizeof这个关键字上吗?

无名侠 发表于 2014-3-28 20:41:01

拈花小仙 发表于 2014-3-28 20:36 static/image/common/back.gif
最后一个是&a的输出结果,可a和&a的区别被这题搞乱了,我现在不知哪个代表整个数组,哪个代表数组首元素地 ...

不知道该作何解释。

oggplay 发表于 2014-3-28 20:41:07

本帖最后由 oggplay 于 2014-3-28 20:45 编辑

青玄 发表于 2014-3-28 20:23 static/image/common/back.gif
我也一样,两个都是40,其实这个40我想是这样的,这些数据都是在栈中的,而VC的入栈顺序是自右往左的,所以 ...
通过你的反汇编我明白了,你的编译器在调用printf函数时一直在压栈,而我的编译器直接调用了变量地址,从未压过栈,也就是说我的变量并不在堆栈中。哈哈。看来是编译器不同的缘故。

virtual1225 发表于 2014-3-30 10:04:33

都是高手:cry
页: [1]
查看完整版本: 一个C语言的小问题