Chinaunix首页 | 论坛 | 博客
  • 博客访问: 150861
  • 博文数量: 28
  • 博客积分: 1476
  • 博客等级: 上尉
  • 技术积分: 356
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-11 11:39
文章分类
文章存档

2011年(1)

2010年(18)

2009年(9)

我的朋友

分类: 嵌入式

2009-11-20 18:44:10

    前不久就说要弄指针,一直瞎忙,也没什么时间,以前对指针的理解总是很模糊,对指针做为参数是怎么被函数调用的不理解。今天终于有点时间了可以弄了,所以特地将实践过程也出来。
    首先,如果学过汇编的话,按我的理解,指针就是一个地址,只不过这个地址里的内容里又含有地址,要是在来个指向指针的地址,那就是地址中的地址的地址,指针还是分级的,比如:声明一个指针char *name,这就是一个一级指针,而如果是**name,那就是二级指针,其中“*”越多,级数就越高,也就越复杂。一般我们只我们只用到二级指针,即是指向指针的指针,在往上就很难理解了。
    其次,这里我举个例子用文字简单的描述一下,这里要涉及到一点内存的知识,没学过汇编理解就可能需要点时间,不过我用的是日常生活中的例子,应该不难理解。假设我们有10个箱子,这10个箱子就可以看成是一段内存,大家都知道内存是有地址的,而我们将箱子从1号到10号分别排上号,要打开这10个箱子就必须要有钥匙,而钥匙也是有号码的,是与箱子的号码是一一对应的。假设我们有2号箱子的钥匙,而我们要打开8号箱子拿100元,但是8号箱子的钥匙在2号箱子里,于是我们就先要用2号箱子的钥匙先打开2号箱子取得8号箱子的钥匙,然后在用8号箱子的钥匙打开8号箱子拿走其中的money。现在我们来重新回顾下这个过程,我们手上有2号箱子的钥匙,它是属于第2个箱子的,我们称它的地址为2号箱子,类似的8号箱子的钥匙的地址为8号箱子。好了,我们用一句C语言来描述下,我们定义了一个指针char *key=“100”,假设这个指针的地址在内存为0x2000,而0x2000存储了100这个字符串的地址为0x8000。
    0x2000-->0x8000--->“100”。其中要注意的是指针的地址是不可以改变的,而指针所指向的内容却是可以改变的,我们可以使用一条语句改变指针指向的内容,key=0x3000,这样我们就把指针所指向的内容改为了0x3000。如果对指针进行自加,它就指向了0x3001。而对于指向指针的指针,由于表达能力有限,在最后的时候,我会画一张图方便理解。
    接下来的时候我们就看看实践的过程,有如下一段代码:
//hello.c
#include
 
int main()
{
    char *name = "Lu xi";
    return 0;
}
代码很简单,主要是为了方便调试的过程中方便理解指针的概念。编译代码gcc -g hello.c会在目录下生成a.out文件,然后gdb ./a.out,我的代码会有所不同,主要是为了以后方便,不影响我们的调试过程。
>>> gdb ./a.out
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i586-suse-linux"...
(gdb) b 18
//其中b 18是main函数所在的行数
Breakpoint 1 at 0x80483d7: file hello.c, line 18.
(gdb) r
Starting program: /home/lcw/embedded/test_code/pointer_test/a.out
Breakpoint 1, main () at hello.c:19
19 {
(gdb) s
main () at hello.c:20
20     char *name = "Lu xi";
(gdb) p &name
$1 = (char **) 0xbff4e520
(gdb) s
23     return 0;
(gdb) p &name
$2 = (char **) 0xbff4e520
(gdb) p name
$3 = 0x80484d5 "Lu xi"
(gdb) p *name
$4 = 76 'L'
(gdb) x/4w 0xbff4e520
0xbff4e520: 0x080484d5 0xbff4e540 0xbff4e598 0xb7eec5f5
//请注意看红色部分
(gdb) x/4w 0x080484d5
0x80484d5: 0x7820754c 0x00000069 0x00000000 0x00000000
(gdb) x/6b 0x080484d5
0x80484d5: 0x4c 0x75 0x20 0x78 0x69 0x00
//这里可能会有人看不懂,0x4c是大写字符L的ASCII码,后面的以此类推,而
//0x7820754c,又是什么意呢,请看后面还有个0x00000069,这又是什么意思
//呢?如果学过大端格式的知识应该不难理解。不错,通常我们的内存中的内容都
//是以大端格式的形式存储信息的,不懂的可以去看看大端格式的相关知识,不里
//就不做介绍了。如果还不理解,我们在换种形式来观察。
(gdb) x/s 0x080484d5
0x80484d5:  "Lu xi"
//由此就可以知道了,指针name的地址为0xbff4e520,其中保存了字符串字符
//串“Lu xi”的首地址为0x80484d5。好了,现在都明白了,更复杂如指针是
//怎么调用的,指向指针的指针在内存中是如何分配的留到下一次在说。
 
阅读(1232) | 评论(0) | 转发(0) |
0

上一篇:09.11.19日

下一篇:指针的理解2

给主人留下些什么吧!~~