C语言:使用指针指向特定的内存地址

37 篇文章 0 订阅

  C语言指针是一个很灵活的东西,使用指针可以提高效率,但同时指针也是很危险的,弄不好就容易使得程序崩溃。下面看下将指针指向特定的内存地址:

#include <stdio.h>

struct Data{
	char length;
	char width;
	short height;
}; 

int main()
{
	char buf[12] = {0};
	
	buf[4] = 0x12;
	buf[5] = 0x34;
	buf[6] = 0xab;
	buf[7] = 0x23;
	
	struct Data *realData = (struct Data *)(buf + 4*sizeof(char));
	printf("realData->length = 0x%x\n", realData->length);
	printf("realData->width = 0x%x\n", realData->width);
	printf("realData->height = 0x%x\n", realData->height);
	
	return 0;	
}

  我们首先定义一个结构体,包含长宽高三个成员,同时也定义了一块buf缓存,并且将数据填充进去。然后我们定义一个结构体指针,这个指针指向以buf为首地址的后面第4个内存地址处,这时结构体的成员就可以对应起来了,所以printf打印的数据就是结构体指针指向的buf数组对应成员数据。可以想象一下内存中的对应关系(我们测试的机器环境是小端模式,字节序的大小端模式可以参考《C语言:字节序的大小端模式》):

在这里插入图片描述

运行程序可以看到结果与我们的内存对应关系是一致的:

realData->length = 0x12
realData->width = 0x34
realData->height = 0x23ab

  还没结束哦,必须注意的一点就是使用结构体的时候,需要了解结构体内部的成员在内存中的分布关系,否则得到的数据就不一定是正确的了,比如我们修改一下程序,将结构体成员的顺序调换一下并且相应调整buf的元素:

#include <stdio.h>


struct Data{
	char length;
	short height;
	char width;
}; 


int main()
{
	char buf[10] = {0};
	
	buf[4] = 0x12;
	buf[5] = 0xab;
	buf[6] = 0x23;
	buf[7] = 0x34; 
	
	struct Data *realData = (struct Data *)(buf + 4*sizeof(char));
	printf("buf start in RAM addr: %p\n", &buf[0]);
	printf("realData->length addr: %p, val: 0x%x\n", &realData->length, realData->length);
	printf("realData->height addr: %p, val: 0x%x\n", &realData->height, realData->height);
	printf("realData->width  addr: %p, val: 0x%x\n", &realData->width, realData->width);

	return 0;	
}

先看答案再解释:

buf start in RAM addr: 0xbea84d52
realData->length addr: 0xbea84d56, val: 0x12
realData->height addr: 0xbea84d58, val: 0x3423
realData->width  addr: 0xbea84d5a, val: 0x0

  输出的结果和我们设定的数据是不一样的了,不可否认的一点是,我们的数据存放到buf中的位置是正确的,但是结构体内部成员的关系可就不是连续的4个地址空间了,不信可以看一下上面打印的地址数一下。还是把内存图画出来会比较容易对上号:

在这里插入图片描述
  由于结构体成员存在内存对齐问题(本程序在32位机器上运行),结构体本身占用的内存就发生了变化,至于为什么会这样可以参考文章:《C语言:结构体大小及其成员分布探究(结构体内存对齐问题)》,里面讲解了结构体内存分布的好几种情况。所以看到以上内存分布对应关系,知道程序应该怎么改了吧?只需要将buf的下标调整一下配合结构体成员分布即可输出正确结果:

buf[4] = 0x12;
buf[6] = 0xab;
buf[7] = 0x23;
buf[8] = 0x34; 
  • 1
    点赞
  • 0
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 博客之星2020 设计师:CY__ 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值