C语言小白深入理解指针1---char篇

        献给初学指针一头雾水难以理解的朋友们.....

        拿到一款RAM只有1KB的51单片机,首先想到的这款MCU的内存1KB=1024个字节,相当于可以存储1024个8bit的数据,假使在未烧入程序的情况,内部1024个字节存储的都是0:

内存编号012345。。。。1020102110221023
存的数据00000000000

        现在打开了keil软件,写下第一段代码:

        char i=0x08;

        编译以后,MCU会自动分配一个内存标号(比如是3,&i=3),表示定义了一个char型变量i,给它赋值0x08,这个0x08存储在内存标号3的小房间里:

内存编号012345。。。。1020102110221023
存的数据0000x080000000

        接着写下第2行代码:

        char *p=&i;

        编译以后,MCU会自动分配一个内存标号(比如是1020,&p=1020),表示定义了一个指向char型变量的指针变量p,这个指针变量p存储的是i的地址3(内存编号),同时它自己的内存编号是1020,即

内存编号012345。。。。1020102110221023
存的数据0000x080000x03000

        重点来了!上面的表是错误的!!!!初学者最难理解地方也在这里。

        首先要理解这个MCU内存有1024个字节,用十六进制表示从0-1023(0x03 FF),所以每个内存编号(指针)需要2个字节来表示。整型变量i的地址不是简单的3,而是0x00 03,必须用16位来表示,虽然从数值上来说,3和0x0003是相等的,但是地址是16位,不能简单的用十进制数字来表示,而且无论其他32位或64位MCU,每个内存块只能存储一个字节,即8bit的数据,超过8bit的数据,比如long型变量,就需要4个内存块来存储量,这也是初学者最容易忽视的地方@!

        p!=0x03,p=0x0003(8051单片机采用大端编码方式,高8位数据0x00在前,低8位数据0x03在后)。所以正确的表格应该是:

内存编号0x00000x00010x00020x00030x00040x0005.....0x03FC0x03FD0x03FE0x03FF
存的数据0000x080000x000x0300

        这里使用Code_Blocks工具在PC平台上测试一下char型的数据具体是如何存储的,它的指针到底是多少。注意PC平台为小端存储方式,高8位数据在后 。      

#include <stdio.h>

typedef unsigned char   uint8;
unsigned char test_i=0x08;
unsigned char *test_p=&test_i;

int main()
{
    printf("test_i = 0x%x\r\n",test_i);
    printf("&test_i = 0x%x\r\n",&test_i);
    printf("test_p = 0x%x\r\n",test_p);
    printf("test_p+1 = 0x%x\r\n",test_p+1);
    printf("*test_p = 0x%x\r\n",*test_p);
    printf("&test_p = 0x%x\r\n",&test_p);
    printf("&test_p+1 = 0x%x\r\n",&test_p+1);
    printf("*(test_p-5 )= 0x%x\r\n",*(test_p-5));
    //printf("*(uint8*)0x60fecd= 0x%x\r\n",*(uint8*)0x0060fecd);
    printf("*(test_p-4 )= 0x%x\r\n",*(test_p-4));
    printf("*(test_p-3 )= 0x%x\r\n",*(test_p-3));
    printf("*(test_p-2 )= 0x%x\r\n",*(test_p-2));
    printf("*(test_p-1 )= 0x%x\r\n",*(test_p-1));
    printf("*(test_p+1 )= 0x%x\r\n",*(test_p+1));
    printf("*(test_p+2 )= 0x%x\r\n",*(test_p+2));
    printf("*(&test_p+1)= 0x%x\r\n",*(&test_p+1));
}

运行结果:

test_i = 0x08         //test_i的赋值
&test_i = 0x60fed1    //test_i的内存地址,占4个字节
test_p = 0x60fed1     //指针变量test_p存储的值,即test_i的地址
test_p+1 = 0x60fed2   //指针变量test_p存储的test_i地址,因为test_i是char型,一个地址就够了
*test_p = 0x08        //指针变量test_p所指向的地址存储的值,即test_i的赋值
&test_p = 0x60fecc    //指针变量test_p自己所存的内存地址,占4个字节
&test_p+1 = 0x60fed0  //指针变量test_p自己所存的内存地址,占4个字节,加1后地址编号+4
*(test_p-5 )= 0xd1    //内存块0x60fecc存储的数据
//*(uint8*)0x60fecd= 0xfe //0x60fece强制转换为uint8型指针,查看内部存的数据
*(test_p-4 )= 0xfe    //内存块0x60fecd存储的数据
*(test_p-3 )= 0x60    //内存块0x60fece存储的数据
*(test_p-2 )= 0x00    //内存块0x60fecf存储的数据    
*(test_p-1 )= 0x50    //内存块0x60fed0存储的数据
*(test_p+1 )= 0x34    //内存块0x60fed2存储的数据
*(test_p+2 )= 0x12    //内存块0x60fed3存储的数据
*(&test_p+1)= 0x12340850  //指向地址0x60fed0的指针变量存储的数据
内存编号0x60fecb

0x60fecc

&test_p

test_p-5

0x60fecd

test_p-4

0x60fece

test_p-3

0x60fecf

test_p-2

0x60fed0

&test_p+1

test_p-1

0x60fed1

&test_i

test_p

0x60fed2

test_p+1

0x60fed3
存的数据00xd10xfe0x600x000x50

0x08

test_i 

*test_p

0x340x12

0x0060fed1  test_p 

0x12340850  *(&test_p+1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值