【总结】C++与C#中的struct结构体

C++结构体

支持继承,甚至可以多继承,虚继承,多态,重载运算符,模板,定义友元函数,友元类等。

 
C++ 结构体和类区别
  • 和C不一样,C++结构体可以有成员函数、构造函数、继承和多态,相比C增加了很多功能
  • 默认public,无论是继承还是修饰变量(本质区别),这点和class,C#都不同
struct B : A。继承默认是public的,而class默认是private的
  • struct可以继承class,同样class也可以继承struct,那么默认的继承访问权限是看子类到底是用的struct还是class
你可以将程序里所有的class全部替换成struct,它依旧可以很正常的运行
  • 关键字“struct”不能用于定义模板参数,而class可以
  • 结构体没有默认构造函数,所以没有定义构造函数时可以使用 ={ } 初始化列表赋值public变量
  • 思想: struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。
 
结构体对象所占的空间大小
字节对齐:每个成员前面的字节数(即成员地址)需要是自身大小的倍数 。即当前成员的偏移量(起始位置)必须是成员变量大小的整数倍,不是的话在后面填充字节。
字节对齐的目的是让计算机快速读写,是一个以空间换取时间的方式。
 
内存补齐:结构体大小必须是最大成员的倍数。不是的话还要填充。
  1. 32位机中,如果成员大于4字节则以4字节整数倍为基准对齐;64位机中则以8字节作为基数上限。
  2. 补齐是为了让这个结构体定义的数组变量时候,数组内部,也同样满足内存对齐的要求。
#pragma pack(n) 表示默认以n字节对齐(上限),若某变量(如int)的字节大于n,则以n的倍数对齐,内存补齐同理
 
例题1:
sizeof (64位机)
struct st_t {
    int status;
    short *pdata;
    char errstr[32];
};
注意64位机指针占8个字节,而且要补齐4个字节,所以4+8+32+4=48
 
例题2:
64位机上,一个结构体有三个成员,分别是char、int、short类型,三个成员位于结构体中不同位置时整个结构体的大小可能是哪些值?
三个数据,一共6种排列:
int 4B   char 1B   short 2B
根据内存对齐原则:
1. char int short   char1 + 空3 + int4 + short2 + 空2 = 12
2. char short int   char1 + 空1 + short2 + int4 = 8
3. int short char   int4 + short2 + char1 + 空1 = 8
4. int char short   int4 + char1 + 空1 + short2 = 8
5. short int char   short2 + 空2 + int4 + char1 + 空3 = 12
6. short char int   short2 + char1 + 空1 + int4 = 8
 
 

C#结构体

与C++结构体区别
默认访问权限为 private
struct是值类型,其实例在栈上分配内存
class是引用类型,其实例在堆上分配内存
 
比如 int 是结构体int32的关键字,所以是值类型。 是从System.ValueType继承的,但是只有他们装箱(boxing)的引用类型是从这里继承的,他们的值类型不是从任何地方继承的,就是.net的内部类型。
System.ValueType是从System.Object继承的。你用了struct关键字,就表明了System.ValueType的继承关系,无需指明。
 
所有结构体都继承ValueType父类,结构体不能被其它类继承。
结构体可以实现接口,却不能继承其他的class
因为值类型不能继承类类型
 
结构体定义
关于C++中结构体的定义声明,我用一段代码来演示吧。

       // 类型别名:为现有类型创建别名
       typedef int in;
       // 这里是定义结构体的同时用typedef取了个叫Stu的别名
       typedef struct Student
       {
              string name;
       }Stu;
       // 还可以用using声明别名
       using init = int;
       in i = 0;
       // 结构体对象的几种构造方式
       Stu s1{ "xx" };
       Student s2{ "ss" };          // 在C语言中你不能使用这种构造方式。。
       struct Student s3();  // 在C语言中,Stu视为struct Student
       init j = 0;
       // decltype可以获得对象或函数返回值的类型,从而进行一些操作。但是这不是反射,这是编译时获取的类型
       decltype(s1) type = s2;

 

以上代码表明了C++和C中定义结构体变量的区别

C语言通常用typedef或struct Student的方式定义

C++中你可以用using别名,Student直接定义

C#中,和类差不多

 

共用体

定义:union name { };
共用体的作用就是不同的类型的变量共享同一个地址,好处是节省开销,缺点是同一时刻仅仅能存储一个成员。
 
共用体的大小是所有成员中占内存最大的那个,初始化时只能有一个常量。
  • 共用体不能同时引用几个成员,他只能用上一次赋值过的那个成员,其他成员都被覆盖掉了
  • 共用体变量不能初始化
  • 共用体变量不能作为函数参数(指针可以)
  • 大小端模式(这个有兴趣可以了解)
 
例题:
下列代码的输出结果有可能是哪些
#include<stdint.h>
#include<stdio.h>
union X
{
    int32_t a;
    struct
    {
        int16_t b;
        int16_t c;
    };
};
int main(){
    X x;
    x.a=0x20150810;
    printf("%x,%x\n",x.b,x.c);
    return 0;
}
答:2015,810 或 810,2015
 
0x20150810 如果按照大端模式存储(和阅读习惯一致):从低地址到高地址:20 15 08 10
                                  输出从低地址到高地址:20 15 08 10
如果按照小端模式存储:从低地址到高地址:10 08 15 20 
                                  输出从高地址到低地址:08 10 20 15
 
 
 
 
 
 
posted @ 2018-04-12 14:03  sols  阅读(2217)  评论(0编辑  收藏  举报