Bootstrap

结构体 写入文件 C++ 深入理解

fwrite等写文件的函数都是void*的输入,直接填入结构体的指针即可,前提是结构体中不能有指针类型,有的话那些东西写不进去.

可以这样理解,结构体内全部存储的是成员变量,结构体首地址存储的是第一个变量的首地址,结束位置存储的是最后一个变量的位置。

如果用同一种编译器,对变量的地址分布采取的策略的相同的,包括内存对齐,包括大端小端等问题。故而这样操作是没有问题的。

但是C++类不可以,有函数,有虚函数表。

结构体写入文件后打开有乱码,是因为内存对齐的原因,增加的那部分内存。

例如如下的结构体:

struct st
{
    char a; //内存偏移量0 内存中byte[0]存储 A
    char b;//内存偏移量 1 内存byte[1] 存储  B
    char e;//内存偏移量 2 内存byte[2] 存储  C
    int d; //这个就有点问题了,他有内存对齐了,偏移量回事 4 故而中间一个byte填充 0 打印没打印出来。
    char* p;//注意是个32为地址偏移量应该是8 内存对齐。 中间打印的是0 最后打印的是地址,故而乱码
};    总体占用12个字节
int main()
{
    
    st s;
    s.a = 'A';
    s.b = 'B';
    s.d = 'C';
    s.e = 'D';
    s.p = "hello,word";
    FILE* pFile = fopen("G:\\st.txt","wb");
    if(pFile == NULL) cout<<"error"<<endl;
    fwrite(&s,sizeof(s),1,pFile);
    
    fclose(pFile);
    system("pause");
    return 0;
}        

打印的应该是 ABD C   ?@ 



下面是CLass 类型的

#include<iostream>
#include<stdio.h>
using namespace std;
class Cst
{
    private:
    int a;
    int b;
    public:
        Cst(int a,int b):a(a),b(b) { }
        Cst() { }
      virtual void Print() {cout<<"first virual"<<endl;}
      virtual void print() { cout<<a<<b<<endl;} 
      char* name;
};
int main()
{
    
  
    FILE* pFile;
    pFile = fopen("G:\\st.txt","r");
    Cst ss(100,200);
    fread(&ss,sizeof(ss),1,pFile);
    fclose(pFile);
    ss.print();
    cout<<ss.name<<endl;
    system("pause");
    return 0;
}         
除了 name 无法读取,之外。因为name 没有存储到文件中,类定义中也没有,因此不可能知道。指针找不到地方。

其他的都没问题。

回忆下对象在内存中的分布情况

1 虚表 指针 ---------->指向的是类中具体函数的地址。

下来是继承变量

自己变量

                 注意函数指针并没有存在对象中,而是对象在调研函数时候会在类中代码,也就是代码区寻找。

深入理解下,你会问到函数也是指针,虚表也有指针,为什么这些指针能找到想要的地址。

我的回答是,非虚函数首先没有在对象中存储指针信息,运行时候,对象会找到相应的类。然后根据函数名(也就是地址,偏移量)找到函数入口

虚函数的虚表不就是对象的首地址,偏移量不就是0嘛。 因此可以找得到虚表。

一定要理解,函数虚表,和函数列表在代码区的类中存储。不能修改。对于虚函数,多了一个指向他的指针罢了


综上所诉,利用类或者结构体直接写入文件存储,持续化,效果很差,移植性,兼容性很差,受到编译器,运行环境的影响。 而切两边定义的类型要完全一致

;