C/C++

关键字

volatile

编译时,不进行优化。如一些特殊的变量在中断时会被修改,为了保证每次都从该变量的地址中读取。

volatile int i = 10;

int j = i;

.....

int k = i;

在省略号中,对于i没有改变,但是k=i这一步还是会从i的地址中读取数据。如果没有volatile,则k=i这一步会将上次i的数值放到k中,而不是从i的地址中读取。

const

定义常量,如果一个变量被const修饰,它的值不能改变。

  • 作用:

1、预编译指令#define只是对值进行简单的替换,不能进行类型检查;

2、保护被修饰的东西,防止意外修改,增强程序的健壮性;

3、将const修饰的变量放在符号表中,称为编译期间的常量,没有了存储和读内存的操作,效率高。

  • 用法

1、修饰局部变量


const int i = 5;

int const i = 5;

两种写法相同,需要给变量初始化,之后无法修改。


const char * str = "fasdaddf";

有const修饰,如果后期修改内容,则会报错。如str[4] = ‘x’;

2、常量指针和指针常量


const int * n;

或者

int const * n;

常量指针(在星号左边)说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的;也可以改变指针的值。


int * const n;

指针常量(在星号右边)的指针地址不能改变,但是地址指向的数值可以改变。

其他作用可以上网查阅。

static

修饰函数或者变量。

1、隐藏功能

static修饰的函数和变量,在其他文件中不可见。

也就是说在不同文件中,用static可以定义相同名字的变量,也不能通过extern来调用其他文件中的函数或者变量。

2、保持变量的持久

3、默认初始化为0

全局变量也具有该效果。

static和const变量的存放位置

①static无论是全局变量还是局部变量都存储在全局/静态区域,在编译期就为其分配内存,在程序结束时释放。

②const全局变量存储在只读数据段,编译期最初将其保存在符号表中,第一次使用时为其分配内存,在程序结束时释放;const局部变量存储在栈中,代码块结束时释放。

③全局变量存储在全局/静态区域,在编译期为其分配内存,在程序结束时释放。

④局部变量存储在栈中,代码块结束时释放。

restrict

C99标准引入,只可以用于限定和约束指针,表明该指针释放问一个数据对象的唯一初始的方式。即告诉编译器,所有修改该指针指向内存中内容的操作必须通过该指针来修改,不能通过其他途径(其他变量或者指针)修改

char * strcpy(char *restrict,const char *restrict)

struct

结构体

  • 结构体对齐问题

两条原则:

(1)结构体成员的偏移量必须是成员大小的整数倍

(2)结构体大小必须是所有成员大小的整数倍

计算方法

(1)根据原则(1)进行偏移量和长度计算

(2)根据原则(2)进行长度的补齐,如长度18,补长到20使得是所有成员大小的整数倍

其他注意点:

(1)数组的大小被拆分成数组元素的大小,即char x[5]则为5个char,而不是大小为5bytes的数组

例子

(1)例子1

// 满足两个原则,得到大小为8bytes
struct s1{
    char ch1;//偏移量0
    char ch2;//偏移量1
    int i;//偏移量4,因为int长度为4bytes
}

(2)例子2

// 满足两个原则,得到大小为12bytes
struct s2{
    char ch1;//偏移量0
    int i;//偏移量4
    char ch2;//偏移量8
    //由于偏移量8,长度为9,不是4bytes(int)倍数,则得到12bytes
}

(3)包含数组的结构体例子3

// 满足两个原则,得到大小为20bytes
struct s3{
    char ch1;//偏移量0
    int i;//偏移量4
    char str[10];//偏移量8,且相当于10个char
    //由于偏移量8,长度为18,不是4bytes(int)倍数,则得到20bytes
}

(4)包含结构体的结构体例子4

// 满足两个原则,得到大小为20bytes
struct s4{
    char ch1;//偏移量0
    int i;//偏移量4
    struct s{//结构体被当做两个元素——ch2和j,而不是一个8bytes的整体
        char ch2;//偏移量8
        int j;//偏移量12
    }
    float f;//偏移量16,4bytes长度
    //由于偏移量16,长度为20,则得到20bytes
}

(5)包含联合体的结构体例子5

// 满足两个原则,得到大小为20bytes
struct s5{
    char ch1;//偏移量0
    int i;//偏移量4
    union s{//联合体被当做一个整体
        char ch2;//偏移量8
        int j;//偏移量12
    }
    //由于偏移量16,长度为20,则得到20bytes
}

(6)指定对齐值的结构体例子6

// 满足两个原则,得到大小为20bytes
//如果没有指定对齐值,则结构体大小是24,因为double长度为8bytes,20不是8的倍数
//如果指定了对齐长度4,则结构体大小是20bytes,是4的倍速
//如果成员对齐值和指定对齐值选择小的作为对齐值,例如制定对齐值10,最大成员长度8,则最终和8对齐
#pragma pack(4) //指定向4对齐
struct s6{
    char ch;//偏移量0
    int i;//偏移量4
    float f;//偏移量8
    double d;//偏移量12,长度8bytes
}

欢迎关注我的微信公众号

互联网矿工

funpeefun

Search

    Post Directory