| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 868 人关注过本帖
标题:指针数组的内存结构
只看楼主 加入收藏
dorainm
Rank: 1
等 级:新手上路
帖 子:17
专家分:0
注 册:2007-7-31
收藏
 问题点数:0 回复次数:3 
指针数组的内存结构

1、指针数组

2、赋值




1、指针数组


const char *g_sHelpCommSet[][2]={{"1","2323"},{"3","4dfdsfd"}};

对于这个数组来看看系统给它分配的内存空间是什么样子的?!


写个address.c

#include <stdio.h>


const char *g_sHelpCommSet[][2]={{"1","2323"},{"3","4dfdsfd"}};


int main( void )

{

return 0;

};


编译,带-g参数,方便在gdb中调试

$ gcc -g -o test test.c


然后调试,查看内存,系统是怎么给g_sHelpCommSet安排内存的

$ gdb address

GNU gdb 6.6-debian

Copyright (C) 2006 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type "show warranty" for details.

This GDB was configured as "i486-linux-gnu"...

Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".

/* 在程序入口处设制断点 */

(gdb) break main

Breakpoint 1 at 0x8048352: file address.c, line 7.

/* 运行程序 */

(gdb) run

Starting program: /home/guaicat/workroom/memory/address


Breakpoint 1, main () at address.c:7

7 return 0;

(gdb)

/* g_sHelpCommSet 数组在内存中的模样 */

(gdb) x/12x g_sHelpCommSet

0x804954c <g_sHelpCommSet>: 0x0804842c 0x0804842e 0x08048433 0x08048435

0x804955c <completed.5758>: 0x00000000 0x00000000 0x00000000 0x00000000

0x804956c: 0x00000000 0x00000000 0x00000000 0x00000000

/* 注意:g_sHelpCommSet0x804954c0x0804842c是数组里面的值 */

/* 继续看,g_sHelpCommSet 指向的内存单元 */

(gdb) x/24b 0x0804842c

0x804842c: 0x31 0x00 0x32 0x33 0x32 0x33 0x00 0x33

0x8048434: 0x00 0x34 0x64 0x66 0x64 0x73 0x66 0x64

0x804843c: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00


对于系统或者程序来说,因为char *指针类型,所以它认识的g_sHelpCommSet 仅仅是一个指针, 0x804954c;记住了,g_sHelpCommSet就是 0x804954c,而且仅仅是 0x804954c!!!


指针数组,对于系统或者程序来说,依然是一个指针,但是因为数组的下标,程序会为这个指针数组设制偏移量来解释,比如申明的g_sHelpCommSet[][2]中,g_sHelpCommSet[i][j]就被解释为 g_sHelpCommSet + (sizeof(char*)*2)*i + (sizeof(char*))*j 的地址,因为sizeof(char *)==4,所以


g_sHelpCommSet[0][0] = 0x804954c + (4*2)*0 + (4)*0 = 0x804954c

g_sHelpCommSet[0][1] = 0x804954c + (4*2)*0 + (4)*1 = 0x8049550

g_sHelpCommSet[1][0] = 0x804954c + (4*2)*1 + (4)*0 = 0x8049554

g_sHelpCommSet[1][1] = 0x804954c + (4*2)*1 + (4)*1 = 0x8049558

因为数组记录的是首地址,靠下标来算偏移量来决定某个数组成员的实际内存地址,这跟指针里面的地址操作是一样的,所以,表达一个数组char array[7]的成员,可以用array[3]这种方式,也可以用(array+3)来表达,它们都是array的地址+sizeof(char)*3的那个内存单元:)


我们知道这个指针数组了,再看看指针数组每个指向的内存单元内容

(gdb) x/12x g_sHelpCommSet

0x804954c <g_sHelpCommSet>: 0x0804842c 0x0804842e 0x08048433 0x08048435

0x804955c <completed.5758>: 0x00000000 0x00000000 0x00000000 0x00000000

0x804956c: 0x00000000 0x00000000 0x00000000 0x00000000


可以看出来:

g_sHelpCommSet[0][0],即0x804954c里面存着 0x0804842c

g_sHelpCommSet[0][1],即0x8049550里面存着 0x0804842e

g_sHelpCommSet[1][0],即0x8049554里面存着 0x08048433

g_sHelpCommSet[1][1],即0x8049558里面存着 0x08048435


这些又是什么呢?这些就是g_sHelpCommSet成员所表达的字符串的首地址

(gdb) x/24b 0x0804842c

0x804842c: 0x31 0x00 0x32 0x33 0x32 0x33 0x00 0x33

/* '1' '\0' '2' '3' '2' '3' '\0' '3' */

0x8048434: 0x00 0x34 0x64 0x66 0x64 0x73 0x66 0x64

/* '\0' '4' 'd' 'f' 'd' 's' 'f' 'd' */

0x804843c: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

/* '\0' */


0x0804842c指向的字符串是 0x31 0x00,即 “1”

0x0804842e指向的字符串是 0x32 0x33 0x32 0x33 0x00,即 ”2323”

0x08048433指向的字符串是 0x33 0x00,即 ”3”

0x08048435指向的字符串是 0x34 0x64 0x66 0x64 0x73 0x66 0x64 0 x00,即 ”4dfdsdf”


由此,我们可以总结出下图:

500)this.width=500;" border="0" width="500">





搜索更多相关主题的帖子: 内存 指针 结构 
2007-07-31 02:55
dorainm
Rank: 1
等 级:新手上路
帖 子:17
专家分:0
注 册:2007-7-31
收藏
得分:0 
回复:(dorainm)指针数组的内存结构


2、赋值


如果有一个新的 char **info,我们想把g_sHelpCommSet[0],即{“1”,”2323”}赋值给它,怎么做?!


由上图,我们可以看出,{“1”,”2323”},即g_sHelpCommSet[0]在内存里面是占用8个内存单元的,0x0804954c0x08049533,即g_sHelpCommSet[0][0]4个和g_sHelpCommSet[0][1];

char **info,它被系统认为只是一个地址!即使它使出浑身解数,也只能指向一个内存单元,所以,我们只要给info申请8个内存空间,用来存储它两个成员指针


info = (char**)malloc( sizeof(char*)*2 );

info[0] = g_sHelpCommSet[0][0];

info[1] = g_sHelpCommSet[0][1];


现在,info2个成员指针,跟g_sHelpCommSet[0][0]g_sHelpCommSet[0][1]一样,分别指向0x0804842c0x0804842e,就指向 {“1”,”2323”} 了,其内存结构与图中表达的一样,看下面的内存状态图:

500)this.width=500;" border="0" width="500">


看程序例子

$ more address.1.c

#include <stdio.h>

#include <malloc.h>


const char *g_sHelpCommSet[][2]={{"1","2323"},{"3","4dfdsfd"}};

char **info;


int main( void )

{

info = (char**)malloc( sizeof(char*)*2 );


info[0] = (char*)g_sHelpCommSet[0][0];

info[1] = (char*)g_sHelpCommSet[0][1];


printf( "info[0] = %s\n", info[0] );

printf( "info[1] = %s\n", info[1] );


free( info );

return 0;

};

$ gcc -o address.1 address.1.c

$ ./address.1

info[0] = 1

info[1] = 2323

$



这可能不是你当初希望的,我们只是让info指向g_sHelpCommSet[0],这么多赋值运算不说,没有想到还有mallocfree来麻烦; dorainm,能不能帮忙想一个新的办法,让info直接借用g_sHelpCommSet[0]2个成员变量的内存空间,而这2个内存空间已经直接指向好了{“1”,”2323”}

回答是,当然可以!


char **info = g_sHelpCommSet[0];

这种写法,编译时候会给予警告的,因为info只是一个点,当它用info[1],就是访问info+sizeof(char*)*1的内存单元的时候,其实那个单元不是它的地盘,因为C语言没有对下标越界进行强制保护,只要不理那个警告,程序还是可以正常工作的!


内存状态:


500)this.width=500;" border="0" width="500">



程序例子:


$ more address.2.c

#include <stdio.h>


const char *g_sHelpCommSet[][2]={{"1","2323"},{"3","4dfdsfd"}};

char **info = g_sHelpCommSet[0];


int main( void )

{

printf( "info[0] = %s\n", info[0] );

printf( "info[1] = %s\n", info[1] );


return 0;

};

$ gcc -o address.2 address.2.c

address.2.c:4: warning: initialization from incompatible pointer type

$ ./address.2

info[0] = 1

info[1] = 2323

$


2007-07-31 02:56
crazyboy216
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2007-6-28
收藏
得分:0 
我还没看懂,先顶下.等下回去好好研究
2007-07-31 08:36
aoaoaoao
Rank: 1
等 级:新手上路
帖 子:81
专家分:0
注 册:2007-5-14
收藏
得分:0 

没用过gnu.

只不过看到了类型限定符const:

const char *g_sHelpCommSet[][2]={{"1","2323"},{"3","4dfdsfd"}};
char **info =g_sHelpCommSet[0];


这个是最后1个程序的例子中的2句定义,对于这种用法我不知道gnu会怎么做,
只不过ANSI中说明了这是非法的,在win-tc中会给你警告,在c-free和vc中会编译不过去.
因为g_sHelpCommSet[0]是被const char*修饰的 而info是被 char** 修饰的的,

他们不是同一类指针类型.

const char *g_sHelpCommSet[][2]={{"1","2323"},{"3","4dfdsfd"}};
const char **info =g_sHelpCommSet[0];
这样是不是更合适一点?



2007-07-31 09:59
快速回复:指针数组的内存结构
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020913 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved