c 和 c++ 最大的特点就是对内存的自由操作,数据类型,其实都是对内存的一种解释方式。C语言中常用的一个技巧就是尾随数据,网络编程中经常会用到这个特性,

特别是以前写完成端口的时候,这个特性肯定是会用到,跟IOCP的API特性相关。c++中也有类似的new也可以使用。

e1:尾随内存与指针解释

// c++ std
#include <iostream> // c std
#include <cstdlib>
#include <cstring> struct TestData {
int data_size_;
char data_[];
}; void foo1() {
std::cout << "sizeof(TestData) = " << sizeof(TestData)<<std::endl;
int len = sizeof(TestData) + *sizeof(int);
char *buffer = "hello world";
TestData * data_ptr = reinterpret_cast<TestData*>(new char[len]);
if (nullptr != data_ptr) {
data_ptr->data_size_ = ;
memcpy(data_ptr->data_, buffer, strlen(buffer) + );
std::cout << data_ptr->data_ << std::endl;
std::cout << reinterpret_cast<char *>(data_ptr+) << std::endl;
std::cout << "sizeof(TestData) = " << sizeof(TestData)<<std::endl;
} }
int main(int argc, char* argv[]){
foo1();
getchar();
return ;
}

输出结果:

sizeof(TestData) = 4

hello world

hello world

说面:动态分配的内存比TestData本身的数据大小4要大,而TestData的成员data_是不计内存的,只是其地址依然是在data_size_的内存地址之后。给data_的赋值其实利用的是其后的数据内存,而不是TestData本身的内存,不过,实际使用时最好还是将data_声明为char data_[1]。

e2:C++中的定位new

通常我们用new来动态分配一个对象或者一个对象数组,上面的代码中分配内存时,分配了相对足够大的内存,然后在其上面构建字符串。new操作符其实也可以在已有内存上构建对象,继续在刚才的代码上改进一下。

void foo2() {
char * buffer = new char [];
// 利用new在已有内存上构建对象
TestData *data1 = new (buffer) TestData;
if (nullptr == data1) {
return;
}
// 再次利用new在data1后构建第二个TestData对象
// 此时new是没有分配内存的
TestData *data2 = new (data1 + ) TestData;
if (nullptr == data2){
return;
}
data1->data_size_ = ;
memcpy(data1->data_, &data1->data_size_, sizeof(data1->data_size_));
// 这个时候, 由于data2的内存仅随data1之后,data2->data_size_的值为4
std::cout << "data1:" << data1 << std::endl;
std::cout << "data2:" << data2 << std::endl;
std::cout << "data2->data_size_:" << data2->data_size_ << std::endl;
} int main(int argc, char* argv[]){
foo2();
getchar();
return ;
}

输出结果:

data1:001EFBE0

data2:001EFBE4

data2->data_size_:4

最新文章

  1. opengl es中不同的绘制方式
  2. easyui的datagrid实例实现
  3. jquery ajax跨域的完美解决方法(jsonp方式)
  4. NSURLConnection 网络超时的那些事(转别人整理的)
  5. 由tomcat启动想到的
  6. springcloud(八):配置中心服务化和高可用
  7. Cinnamon桌面是怎么回事儿
  8. 基于Lua脚本解决实时数据处理流程中的关键问题
  9. oracle03
  10. PHP正则表达式二分法实现mysql盲注脚本
  11. 网络基础 外网IP,内网IP,虚拟机的网络设置
  12. 20165223 结对编程之四则运算week1-阶段性总结
  13. Ajax和Json实现自动补全
  14. html干货部分
  15. Number of Islands I &amp; II
  16. 任务失败,因为未找到“AxImpexe”,或未安装正确的 Microsoft Windows SDK
  17. SQLServer2008 全文检索摘记
  18. Ubuntu18.04 修改DNS
  19. NodeJS 难点(网络,文件)的 核心 stream 四: writable
  20. 【POJ】1835:宇航员【模拟】【三维行走】

热门文章

  1. JS保留两位小数 四舍五入函数
  2. Codeforces Round #324 (Div. 2) E. Anton and Ira 贪心
  3. C# 网络编程之豆瓣OAuth2.0认证具体解释和遇到的各种问题及解决
  4. Java对数组的操作(二)——集合与数组的切换
  5. perl指针引用
  6. linux高级命令组合
  7. MySQL(16):Select-union(联合查询)
  8. swift和oc区别----属性部分(参考官方swift2.1文档)
  9. RESTful HTTP实践
  10. 详细讲解Android对自己的应用代码进行混淆加密防止反编译