C 结构体

定义

typedef struct a{
    ...
}b;

(struct a) == b

调用

从类型变量:st_name.member

从指针变量: st_name->member

对齐

GCC默认非紧凑对齐(按最大单元素类型对齐),可以优化访存

用GCC的__attribute__机制来紧凑对齐(按1字节对齐,即取消对齐)

typedef struct t_name{
    ...
}__attribute__((packed));

自定义对齐

typedef struct t_name{
    ...
}__attribute__((aligned(4)));

全局对齐策略

#pragma pack( [show] | [push | pop] [, identifier], n )

通过sizeof(st_name)可获取结构体大小进行对比

__attribute__属性

在函数或数据声明时设置编译属性,GCC特色

  • 函数属性(Function Attribute)

    • __attribute__((noreturn)): 函数永不会返回,优化时去掉不必要的函数返回代码
    extern void exit(int)   __attribute__((noreturn));extern void abort(void) __attribute__((noreturn));
    • __attribute__((weak)): 虚函数,弱符号,引入外部强符号函数后不被调用
  • 变量属性(Variable Attribute)
  • 类型属性(Type Attribute)

    • __attribute__ ((packed)): 取消结构的编译优化对齐
    • __attribute__((aligned(n))): 指定结构的内存对齐

位域

把字节按二进制位拆分,以冒号说明各位域位数,以域名访问

位域是特殊的结构体成员,与非位域结构体成员间依然存在对齐

类型说明符位域名:位域长度

位域可以无位域名,这时它只用来作填充或调整位置

指针类型变量不能指定所占的位数

位域成员不能单独被取sizeof值,且给位域变量成员赋值时,当数值超过变量范围,自动截取不会报错

struct BF1{
char f1 : 3;
char f2 : 4;
char f3 : 5;
};
struct BF2{
char f1 :  3;
short f2 : 4;
char f3 :  5;
};
struct BF3{
char f1 : 3;
char f2;
char f3 : 5;
};

初始化

示例定义

struct InitMember
{
    int first;
    double second;
    char* third;
    float four;
};

{}赋值

struct InitMember test = {-10,3.141590,"method one",0.25};

逐个赋值(乱序)

struct InitMember test;

test.first = -10;
test.second = 3.141590;
test.third = "method two";
test.four = 0.25;

.乱序赋值(c)

Linux Kernel常用

struct InitMember test = {
    .second = 3.141590,
    .third = "method three",
    .first = -10,
    .four = 0.25
};

:乱序赋值(C++)

struct InitMember test = {
    second:3.141590,
    third:"method three",
    first:-10,
    four:0.25
};

*数组初始化

  • {0}
  • memset
  • for

构造/析构函数

c

C没有构造函数,可以写个伪构造malloc一个

student * newStudent(char * name,int age){
    student * stu;
    stu = (student *)malloc(sizeof(student));
    *stu={
        .name=name,
        .age=age
    };
    return stu;
}
void deleteStudent(student **stu){
    free(*stu);
    *stu=NULL;
}
student * stu= newStudent("233",233);
deleteStudent(&stu);

c++

#include <iostream>
#include <string>
using namespace std;
struct node{
    int data;
    string str;
    char x;
    //自己写的初始化函数
    void init(int a, string b, char c){
        this->data = a;
        this->str = b;
        this->x = c;
    }
    node() :x(), str(), data(){}
    node(int a, string b, char c) :x(c), str(b), data(a){}
}N[10];
int main()
{
      N[0] = { 1,"hello",'c' };  
      N[1] = { 2,"c++",'d' };    //无参默认结构体构造体函数
      N[2].init(3, "java", 'e'); //自定义初始化函数的调用
      N[3] = node(4, "python", 'f'); //有参数结构体构造函数
      N[4] = { 5,"python3",'p' };

    //现在我们开始打印观察是否已经存入
    for (int i = 0; i < 5; i++){
        cout << N[i].data << " " << N[i].str << " " << N[i].x << endl;
    }
    system("pause");
    return 0;
}

参考:

https://www.cnblogs.com/silentNight/p/5427600.html

https://blog.csdn.net/ericbar/article/details/79567108

https://www.cnblogs.com/wlw-x/p/11566191.html