二维数组和二级指针

时间:2022-09-06 08:46:29

void output(char **buffer){
printf(“%s\n”,buffer[0]);
}
void main(){
char buffer[100][1024] = {0};
int len = sprintf(buffer[0],"i am a bastard...");
buffer[0][len] = '\0';
output(buffer);
}

程序出现段错误” 

最后在各位大神,特别是skyliuxu的帮助下解决了。

http://bbs.csdn.net/topics/390692578?page=1#post-396630596这是提问页的地址

我总结一下:

GDB显示的结果如下(64位系统):

buffer=0x7ffffffe5180
&buffer[0][0]=0x7ffffffe5180
output (buffer=0x7ffffffe5480) at b.c:22

如上三条说明了两个问题:


1.二维数组地址即第一个数组中第一个元素的地址,而非第一个数组的地址。即buffer=&buffer[0][0]
2.强制类型转换确实不会改变指针的值,尽管函数外bufferchar(*)[1024]类型、函数参数char**类型,buffer还是将buffer[0][0]地址传给了参数char**


此时问题来了,函数内buffer为二级指针,可以看成指针的数组,那么buffer[0]为数组首元素,64位系统指针8字节,则buffer[0]指针的值为buffer所指内存单元向下取8个内存单元内容组成的值。是不是很绕,这8个内存单元内容是什么呢,此时函数内buffer值就是函数外buffer[0][0]即字符'i'的地址,则从i开始依次取八个字节得到的是'i am a b',将其转化为数值即为0x6d612069,故buffer[0]的值为0x6d612069printf%s\n,buffer[0],故发生地址越界。


2014.8.1 9:24数组元素在内存连续存储,多维数组按行连续存储,所以buffer所指内存单元存储的值依次为【i am a bastard...】【...】..........【...】,而buffer的值即为i的地址。将其赋予二级指针void** temp,求temp[0]的值为多少?

解题:temp为二级指针,即指针的数组,也就是地址的数组,最后就是int的数组,temp[0]就是第一个int值。32位系统int 4字节,从temp所指内存单元向下取四字节的内容转成int即为temp[0]的结果。temp与buffer值相同,即从buffer开始取4字节内容如下“i am ”,64位系统则为"i am a b"


总结一下:

1.二维数组地址即第一个数组中第一个元素的地址,而非第一个数组的地址。即buffer=&buffer[0][0]

2.gdb调试结果显示:buffer==&buffer==&buffer[0] == buffer[0] == &buffer[0][0]

3.强制类型转换确实不会改变指针的值,尽管函数外bufferchar(*)[1024]类型、函数参数char**类型,buffer还是将buffer[0][0]地址传给了参数char**

4.二级指针可以看做指针的数组,数组中每个元素皆为指针。


标准的写法是:

void output(char (*buffer)[1024])

char buffer[100][1024] = {0};
char (*temp)[1024];
temp = buffer;
temp[4][2] = '\0';


32位下int/long占用4字节,指针也站4字节,在64位下int占用4字节,long占用8字节,指针占用8字节


查看系统位数:

uname -a

64位的显示

Linux ps4 2.6.16.46-0.12-smp #1 SMP Thu May 17 14:00:09 UTC 2007 x86_64 x86_64 x86_64 GNU/Linux
后面显示有 x86_64

32位的显示:

Linux fc6 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:54:20 EDT 2006 i686 i686 i386 GNU/Linux