斯坦福编程范式中对于C的理解

今天在看斯坦福中的编程范式课程的时候看到了一个有趣的关于C/C++中的地址内存的理解问题,我觉得把这个弄明白了,对于C中的内存模型应该是有很好的提升了:

首先第一个例子:

int arr[5];
arr[3] = 128;
((short*)arr)[6] = 2;
std::cout << "arr[6] = " << arr[3] << std::endl;

如上所示:视频中没有标出前提(int为2个字节,且为大端模式),先分析到c的时候,这个整个数组的内存模型是这样的,用语言描述就是,就是之前数组的每一个int型的格子现在变为两个short(一个字节)的格子,并且第六个格子值为2,然后输出的时候值应该为512+128;自己计算机上是2(小端模式,且int为4个字节);

((short*)(((char*)&arr[1]) + 8))[3] = 100;

上面的分析,如果最上面的代码理解了,那么下面的代码也就不难了,主要是首先取arr[1]的地址,然后将其相应的步长变为char移动8个相应的char的格子,然后在将格子转化为short*的格子,从现在的这个位置,移动3个格子给其赋值100;

  1. 首先课中的swap函数,说的是如何实现一个通用的数据交换函数,如都是int类型的a = 4, b = 5;实现数据交换,这里的所谓的通用是数据类型可以使int,也可以是float,double类型的都可以;函数的实现如下:

以上的实现是真理对于C中的内存理解是非常的透彻了,老师似乎是自己编写了一个编译器,大牛啊;膜拜;好了其实上面的代码都能看懂,但是想出来的话,会有点难,在普通的数据交换中,首先我们是绝对需要知道数据的类型,然后交换内存中的值,但是这里使用了void类型的指针,也就和数据类型无关了,我们只需要知道这个数据在内存中所占用的字节数就可以了,然后交换内存中的存储的数据;或许也只有C才有如此优雅的实现了吧;

第二个例子是一个关于在数组中,查找我们所需要数据相应的下标,在知道数据类型的前提下,我们可以很简单的实现这个需求,但是如果把这个作为一个通用的函数去实现,也就是我们不知道数组猴子那个存储的是什么数据类型,这个时候比较久会比较难了,这其中设计到两个比较难的地方,一是指针关于数组下标的移动,而是如何比较内存中的数据;具体的实现如下,看了这个代码或许是能恍然大悟;

首先关于数组中相应的元素的地址移动,也就是下面这句代码:

void *elementAddr = (char *)base + i * elementSize;

Ps:这里的elementSize代表的是数据元素的字节大小,这里是int那么就是4,首先将base的地址转为char*型的,这里转为char*是有两个考虑的,首先void*的地址是不能进行加减的,因为编译器(GNU编译器认为void* ++每次移动一个字节)是不知道每次加减移动的步长的,这与编译器的理解和定义有关系;另一个考虑就是char*类型的每次加减运算,移动的步长都是一个字节,便于我们后面指针的精确移动;

后面还有一个难点就是关于如何比较两个内存中数据是否相同呢?这里的C提供了一个函数,我之前也是一直没有接触过;

int memcmp(const void *str1, const void *str2, size_t n)

C 库函数 int memcmp(const void *str1, const void *str2, size_t n)) 把存储区 str1 和存储区 str2 的前 n 个字节进行比较。

有了这里利器就可以很好的比较内存中数据的异同性了,然后我们返回相应符合条件的数据的下标;

 

 

同步互斥:

同步(synchronized):如果两个线程A与B之间有着同步关系的话,那么在A完成某个人物之后,B线程才能开始运行;

互斥(mutex):多个线程操作同一个资源的时候,而且同一时间只能有一个线程能操作这个共享资源,那么这些线程间的关系就是互斥的关系(竞争)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值