07-STM32MP1对结构体、地址、内存的最新理解

今天在拷贝数据的时候遇到一个问题:将一个结构体里面的值放到一个数组里面。

结构体:struct memory_manage{

uint16_t head;

uint16_t tail;

uint16_t len;

}mem_page_manage{0x1234,0x5678,0xabcd};

数组:uint8_t net_send_buf[6] = {0};

即,想把结构体mem_page_manage的值放到数组net_send_buf中。

想到直接地址赋值:

测试 one:

先打印出地址,看看地址的关系

printf("%08lx\n", &mem_page_manage);

printf("%08lx\n", &mem_page_manage.head);

printf("%08lx\n", &mem_page_manage.tail);

printf("%08lx\n", &mem_page_manage.len);

打印出的地址为:

bf017000

bf017000

bf017002

bf017004

【首先,必须要知道内存地址只是一个编号,代表一个内存空间。那么这个空间是多大呢?原来在计算机中存储器的容量是以字节为基本单位的。也就是说一个内存地址代表一个字节(8bit)的存储空间。例如经常说32位的操作系统最多支持4GB的内存空间,也就是说CPU只能寻址2的32次方(4GB),注意这里的4GB是以Byte为单位的,不是bit。也就是说4G=4*1024M(Byte)=4*1024*1024Kb(Byte)=4*1024*1024*1024Byte(8bit),即2的32次方个8bit单位。】

测试 two:

打印出地址中的数据:

printf("%08lx\n", *(&mem_page_manage));

printf("%08lx\n", *(&mem_page_manage.head));

printf("%08lx\n", *(&mem_page_manage.tail));

printf("%08lx\n", *(&mem_page_manage.len));

打印出的数据为:

56781234

00001234

00005678

0000abcd

【这里有个疑问:前两个地址是一样的,都为:bf017000,但是打印出来的数据却不一样:56781234     00001234】

测试three:

打印地址中的数据:

for(i=0;i<6;i++)

{

printf("%08lx\n", (*((&mem_page_manage)+i)));

}

printf("%12lx\n", *(&mem_page_manage));

printf("%16lx\n", *(&mem_page_manage));

打印出的数据为:

56781234
34120000
bf02b26c
c0c0c0e7
00000000
00000000
    56781234

        56781234

【测试到这里有个猜测:从地址取数据,最多可取出32位的数据。那么你从这个地址取出的数据应该是多少位的,应该是什么类型的,是由这个地址的类型决定的,即:地址应该也是有类型的。如上测试中,第一个地址打印出的值为56781234,但是为什么这个地址+1后打印出来的值就变成了34120000,再+1后变的更乱了。因为第一个地址是由类型的,即结构体类型的,但是这个地址被+1或+2之后就没有类型了,那么要想把+1之后的地址里面的数据取出来就需要先把这个地址给它赋予一个类型,然后再取

测试four:

for(i=0;i<6;i++)

{

printf("%08lx\n", *(uint32_t *)((&mem_page_manage)+i));

}

for(i=0;i<6;i++)

{

printf("%08lx\n", *(uint8_t *)((&mem_page_manage)+i));

}

输出结果:

mem_page_manage [0]: 56781234
mem_page_manage [1]: 34120000
mem_page_manage [2]: bf070254
mem_page_manage [3]: 10c0c0e7
mem_page_manage [4]: 00000000
mem_page_manage [5]: 00000000
[mem_page_manage [0]: 34
mem_page_manage [1]: 00
mem_page_manage [2]: 54
mem_page_manage [3]: e7
mem_page_manage [4]: 00
mem_page_manage [5]: 00

【看到这个数据有点蒙,怎么会这样呢,和想的不一样啊!但是细看这个语句:*(uint8_t *)((&mem_page_manage)+i)  它是先把结构体的地址+1以后再强转为uint8_t *指针类型的。恍然大悟,是不是应该先把结构体地址强转为uint8_t *类型之后再+1】

测试five:

for(i=0;i<6;i++)

{

//先+1再强转

printf("%08lx\n", *(uint32_t *)((&mem_page_manage)+i));

}

for(i=0;i<6;i++)

{

//强转之后再+1

printf("%08lx\n", *((uint8_t *)(&mem_page_manage)+i));

}

输出结果(前面的打印信息懒得删了,忽略即可):

[203298.684097] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [0]: 56781234
[203298.696369] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [1]: 34120000
[203298.703722] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [2]: bf078254
[203298.715597] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [3]: 90c0c0e7
[203298.724669] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [4]: 00000000
[203298.733848] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [5]: 00000000
[203298.742980] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [0]: 34
[203298.751602] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [1]: 12
[203298.760184] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [2]: 78
[203298.768754] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [3]: 56
[203298.775584] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [4]: cd
[203298.787227] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [5]: ab

【从结果看8位输出的已经正常了,0x1234,0x5678,0xabcd分别是以uint16_t存储的,大端模式:低字节在前。下面把32位输出的也修改一下】

测试six:

for(i=0;i<6;i++)

{

//强转之后再+1

printf("%08lx\n", *((uint32_t *)(&mem_page_manage)+i));

}

for(i=0;i<6;i++)

{

//强转之后再+1

printf("%08lx\n", *((uint8_t *)(&mem_page_manage)+i));

}

[204947.451802] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [0]: 56781234
[204947.460563] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [1]: 0000abcd
[204947.469410] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [2]: 78563412
[204947.478192] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [3]: bf098254
[204947.486987] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [4]: c0e7dcd0
[204947.495697] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [5]: bf0990c0
[204947.504611] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [0]: 34
[204947.514118] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [1]: 12
[204947.522617] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [2]: 78
[204947.530811] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [3]: 56
[204947.538961] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [4]: cd
 [204947.548334] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.0: mem_page_manage [5]: ab

【至此,结构体存储分析完成。接下来,通过地址给数组赋值】

测试seven:

uint8_t net_send_buf[6];

编译时报错:

测试eight:

然后,将net_send_buf的类型改为指针类型:int8_t *net_send_buf;

OK,这样编译通过了打印出

【值已经放到这个指针变量里面了,但是注意是高字节在前的

完结!20200108-21:43

猜你喜欢

转载自blog.csdn.net/fang_yang_wa/article/details/103896988
今日推荐