首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

问一个二级指针和二维数组有关问题

2012-12-14 
问一个二级指针和二维数组问题C语言#includestdio.hint main(){int i[3][3] {{1,2,3},{4,5,6},{7,8,9}

问一个二级指针和二维数组问题
C语言


#include<stdio.h>
int main()
{
    int i[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    int **pi = i;
    printf("%d\r\n",*(i[0]));
    printf("%d\r\n",*(i[0]+1));
    printf("%d\r\n",pi[0]);
    printf("%d\r\n",pi[1]);
    printf("%d\r\n",pi[0]+1);
    return 0;
}


为什么结果是:





5

int **pi = i;


这次赋值在内存中是怎么样的呢?

最好图解!!谢谢各位大神。
[最优解释]
我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2

[其他解释]
引用:
引用:我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2为什么C/C++ code?1pi[0]+1 = 5呢?


pi[0]是一个int型的指针,pi[0]+1=pi[4]
[其他解释]



引用:
引用:引用:我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2为什么C/C++ code?1pi[0]+1 = 5呢?

pi[0]是一个int型的指针,pi[0]+1=pi[4]

pi[0] + 1 = pi[4] 这个应该不对, 这个应该跟int值和int型指针在内存中的存储有关系,请高手解释
[其他解释]
刚刚自己测试了一下, 楼主应该编译的是64位的,在64位里面,int型是4个字节,但是int型指针是8个字节。 
 int i[3][3] = {{1,2,3},{4,5,6},{7,8,9}};中每个数据都只占4个字节
pi[0]是一个int型的指针,其宽度实际上为8个字节,pi的各个部分的值:

pi[0]占据了数字1,2的位置,其值为0x20000001,
pi[1]占据了数字3,4的位置,其值为0x40000003 
pi[2]占据了数字5,6的位置,其值为0x60000005,
pi[3]占据了数字7,8的位置,其值为0x80000007
pi[4]占据了数字9的位置,其值为0x9

楼主可以自己打印一下 sizeof(int), sizeof(int*)验证一下
[其他解释]
首先我的vs这句编译不通过
 int **pi = i;
改为int **pi = (int **)i;后方可
显示结果为:
1
2
1
2
5

然后int **pi 指向的内存布局为:{(int*)1,(int*)2,(int*)3,(int*)4......};
pi[0],pi[1]分别取索引0,和1,所以结果即为:(int*)1和(int*)2
然后pi[0]+1,相当于 pi[0]+sizeof(int*)*1;
[其他解释]
引用:
首先我的vs这句编译不通过
 int **pi = i;
改为int **pi = (int **)i;后方可
显示结果为:
1
2
1
2
5

然后int **pi 指向的内存布局为:{(int*)1,(int*)2,(int*)3,(int*)4......};
pi[0],pi[1]分别取索引0,和1,所以结果即为:(int*)1和(int*……


正解,lz要分清指针类型,指针所指的类型,指针指向了哪里,特别是最后一点指针指向了哪里
[其他解释]
引用:
引用:引用:我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2为什么C/C++ code?1pi[0]+1 = 5呢?

pi[0]是一个int型的指针,pi[0]+1=pi[4]


sorry,pi[0]+1=pi[4]错了,应该是pi[0]+1=pi[0]+4. 6楼的解释是对的。
printf("%d\r\n",pi[0]);
    printf("%d\r\n",pi[1]);
    printf("%d\r\n",pi[0]+1);

上面这个代码在GCC编译的时候有警告需要加-w选项,因为pi[0]是int型的指针,而你打印格式是%d类型,里边会有一个隐式的运算:将pi[0]转换为*pi[0]。即打印指针时是打印指针所指向的值,如果这个值跟%d不相符则会隐式提升为%d格式。
------其他解决方案--------------------


6L 正解....

LZ你一开始 就错了....

int **p = i;  这句话错误...!!!
i是一个数组..被编译器解释为: (*i)[3];  也就是说i是一个指向含有3个元素的数组的指针...

int **p;  声明p是一个指向int型指针的指针....指针的指针和数组的指针 自然不一样..LZ你的编译器不大符合ANSI C标准啊....

[其他解释]

引用:
看了各位的解释,顺便看了一下《C primer Plus》第十章。那我是不是可以这样理解呢?

在32位系统下这样理解是对的。


引用:
那为什么64系统下,pi[1] = 3了呢?

在64位系统下指针占8个字节,pi[1]是int*类型,存储的是a[0][2]和a[1][0]的地址,各占4字节共8字节,在printf的时候发生了截断,只打印了低4位的值,所以输出的是3. 楼主可以继续打印p[2]看看就会输出5.
[其他解释]
6L正解,最后一个+1应该是+sizeof(int *) * 1

学习了
[其他解释]
引用:
引用:
引用:引用:我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2为什么C/C++ code?1pi[0]+1 = 5呢?

pi[0]是一个int型的指针,pi[0]+1=pi[4]

sorry,pi[0]+1=pi[4]错了,应该是pi[0]+1=pi[0]……


如果改为 printf("%d\r\n",*pi[0]+1); 
运行时错误,这是为什么?求解
[其他解释]
还是不懂!这个6楼说的我也不懂
[其他解释]
引用:
如果改为 printf("%d\r\n",*pi[0]+1); 
运行时错误,这是为什么?求解

可以从汇编角度去看看。俺对汇编不灵。
[其他解释]
引用:
引用:引用:
引用:引用:我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2为什么C/C++ code?1pi[0]+1 = 5呢?

如果改为 printf("%d\r\n",*pi[0]+1); 
运行时错误,这是为什么?求解


也许是编译器不识别了吧。本来pi都是从一个指针常量赋值而来的,这样的转换编程中莫要用。
[其他解释]
//在堆中开辟一个4×5的二维int数组
#include <stdio.h>
#include <malloc.h>
int **p;
int i,j;
void main() {
    p=(int **)malloc(4*sizeof(int *));
    if (NULL==p) return;
    for (i=0;i<4;i++) {
        p[i]=(int *)malloc(5*sizeof(int));
        if (NULL==p[i]) return;
    }
    for (i=0;i<4;i++) {
        for (j=0;j<5;j++) {
            p[i][j]=i*5+j;
        }
    }
    for (i=0;i<4;i++) {
        for (j=0;j<5;j++) {
            printf(" %2d",p[i][j]);
        }
        printf("\n");
    }
    for (i=0;i<4;i++) {
        free(p[i]);
    }
    free(p);
}
//  0  1  2  3  4
//  5  6  7  8  9


// 10 11 12 13 14
// 15 16 17 18 19


//在堆中开辟一个3×4×5的3维int数组
#include <stdio.h>
#include <malloc.h>
int ***p;
int i,j,k;
void main() {
    p=(int ***)malloc(3*sizeof(int **));
    if (NULL==p) return;
    for (i=0;i<3;i++) {
        p[i]=(int **)malloc(4*sizeof(int *));
        if (NULL==p[i]) return;
        for (j=0;j<4;j++) {
            p[i][j]=(int *)malloc(5*sizeof(int));
            if (NULL==p[i][j]) return;
        }
    }
    for (i=0;i<3;i++) {
        for (j=0;j<4;j++) {
            for (k=0;k<5;k++) {
                p[i][j][k]=i*20+j*5+k;
            }
        }
    }
    for (i=0;i<3;i++) {
        for (j=0;j<4;j++) {
            for (k=0;k<5;k++) {
                printf(" %2d",p[i][j][k]);
            }
            printf("\n");
        }
        printf("---------------\n");
    }
    for (i=0;i<3;i++) {
        for (j=0;j<4;j++) {
            free(p[i][j]);
        }
        free(p[i]);
    }
    free(p);
}
//  0  1  2  3  4
//  5  6  7  8  9
// 10 11 12 13 14
// 15 16 17 18 19
//---------------
// 20 21 22 23 24
// 25 26 27 28 29
// 30 31 32 33 34
// 35 36 37 38 39
//---------------
// 40 41 42 43 44
// 45 46 47 48 49
// 50 51 52 53 54
// 55 56 57 58 59
//---------------

[其他解释]
VC调试时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

这辈子不看内存地址和内存值;只画链表、指针示意图,画堆栈示意图,画各种示意图,甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗?本人深表怀疑!


这辈子不种麦不收麦不将麦粒拿去磨面;只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头,压面条,烤面包,……能从本质上理解面粉、理解面食吗?本人深表怀疑!!

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

有人说一套做一套,你相信他说的还是相信他做的?
其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗?

不要写连自己也预测不了结果的代码!

电脑内存只是一个一维二进制字节数组及其对应的二进制地址;
人脑才将电脑内存中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是很多数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、……

[其他解释]

引用:
我的输出和你不一样,我用的是Ubuntu 11.04 及 GCC 4.5.2
为什么
pi[0]+1 = 5
呢?
[其他解释]
看了各位的解释,顺便看了一下《C primer Plus》第十章。那我是不是可以这样理解呢?


[其他解释]
那为什么64系统下,pi[1] = 3了呢?
[其他解释]
引用:
引用:看了各位的解释,顺便看了一下《C primer Plus》第十章。那我是不是可以这样理解呢?
在32位系统下这样理解是对的。


引用:那为什么64系统下,pi[1] = 3了呢?
在64位系统下指针占8个字节,pi[1]是int*类型,存储的是a[0][2]和a[1][0]……
谢谢!!

热点排行