数据类型(对数据的操作)——奇葩关键字

一、乱世枭雄:static和extern:改变数据类型在内存中的位置或者改变作用域,作用在数据类型上

1、解释:
在C的世界里,不同代码“国度”以.c文件为国界分隔开来,在单个国家里有不同函数占山为王,每个C程序世界里只有一个君主(MAIN),main通过下传指令(参数),调用各种军阀(函数),来掌控。某军阀(函数)心怀叵测,不想单纯听从于main的指挥调度,树立了自己的政权旗帜static。static不同听从于main的调度,自己做主,私藏金库(空间)。不同的国家(不同的.c文件)之间通过extern相互私通,传递消息。

2、static:1)、修饰局部变量:局部变量存放在栈区,staic修饰的话,放在静态数据区,生命周期从该语句块执行结束变到了直到持续整个程序执行为止,生命周期存储空间变 化,作用域没有变化。
                    2)、修饰全局变量,对于一个修饰的全局变量,它既可以在本源文件中被访问,也可以在同一个工程的其他源文件被访问。如果对其中某个源程序文件中的全局变量  前加 static,则更改作用域,由原来的整个工程可见变为本源文件存在。
                    3)、修饰函数:与修饰全局变量类似,更改作用域。
3、extern:指当前变量或函数不是在本源文件内声明的,它是外部变量外部函数,试图引用一个外部声明的全局变量或函数时,可以在其前面加上extern。
                    1)、extern变量名
                     2)、extern函数:函数默认是外部的(在函数体内或函数体外声明一个外部函数,extern关键字可以省略),如果不想让其他源文件链接到,在函数前面加static。

*static:继承中静态属性、静态函数,存在在整个类里而非单个对象


二、铁布衫:const:改变数据类型的只读属性,作用在数据类型上

1、修饰对象:readonly,不仅仅可以用来修辞基本类型,还可以修辞一些结构类型及其参合体,如数组、指针、指针数组、结构体数组、结构体指针数组等。

2、使用方法:将类型去掉,看const修辞谁,谁就拥有了铁布衫谁就是readonly。(不包含指针常量和常量指针的辨析)

const int n=5;
int const m=10;
上述两个变量n和m是同一个类型,都是const int(整型恒量),C++规定:const关键字放在类型或变量名之前等价的。

3、const的位置(指针):常量指针和指针常量

扫描二维码关注公众号,回复: 2368325 查看本文章

const int *p;
int const *b;
int* const c=p;

第一个和第二个是:常量指针:指向的内容是常量,指针本身可以修改,const int 类型指针(const直接修饰int)

第三个是:指针常量:指针本身是个常量,指针只向的内容可以修改,int类型的const指针

当const在*之前是常量指针,在*之后是指针常量

char ** p1;                               //指向char类型的指针的指针
const char **p2;                          //指向const char类型的指针的指针
char *const *p3;                          //指向char类型的const指针
const char *const * p4;                   //指向const char类型的const指针
char ** const p5;                         //指向char类型的指针的const指针
const char ** const p6;                   //指向const char类型的指针的const指针
char * const * const p7;                  //指向char类型const指针的const指针
const char * const * const p8;            //指向const char类型的const指针的const指针
一些声明是不能编译通过的,因为需要在声明的同时进行初始化。


*变量常量const、预处理指令#define


三、隐形刺客auto:局部变量前特有的关键字,作用在变量上

解释:C程序是面向过程的,在C代码中会出现大量的函数模块,每个函数都有其生命周期(也称作用域),在函数生命周期中声明的变量通常叫做局部变量,也叫作自动变量。会在内存栈上进行分配。

        

               

四、闪电飞刀:register:改变变量从内存到寄存器上,作用在变量上

1、作用:意味着该变量会作为一个寄存器变量,让该变量的访问速度达到最快。例如,一个程序逻辑中有一个很大的循环,循环中有几个变量要频繁进行操作,这些变量可以声明为register类型。

2、寄存器变量:寄存器变量是指一个变量直接引用寄存器,也就是对变量名的操作的结果是直接对寄存器进行访问。

3、 寄存器:是CPU的亲信,CPU操作的每个操作数和操作结果,都用寄存器来暂时保存,最后才写入到内存或从内存中读出。变量的值通常保存在内存中,CPU对变量进行读取先是将变量的值从内存中读取到寄存器中,然后进行运算,运算完将结果写回内存中。

4、使用寄存器变量请注意:

1)待声明为寄存器变量类型应该时CPU寄存器所能接收的类型,意味着寄存器变量是单个变量,变量长度应该小于等于寄存器长度

2)不能对寄存器变量使用取地址符“&”,因为该变量没有地址

3)尽量在大量频繁操作时使用寄存器变量,且声明的变量个数应该尽量少。


五、专一王子:volatile:每次都是从内存读取,作用在变量上

解释:不管它的值有没有变化,每次对其值进行访问,都会从内存里,寄存器里读取,从而保证数据一致,做到表里如一。




六、typedef:

1、作用:是为一种数据类型定义一个新名字,
2、目的:一给变量一个易记且意义明确的新名字,二简化一些比较复杂的类型声明。
3、typeof与define比较:define是简单的字符串替换,而typedef则是为一个类型起新名字。

4、typedef与结构体的使用

struct tag_node
{
    char *p_item;
    struct tag_node *p_next;
};
typedef struct tag_node *p_node;

5、typedef与复杂变量声明

int *(*a[5])(int,char*);
typedef int *(*p_fun)(int,char*);                      //pFun是我们建立的一个类型别名
p_fun a [5];                                           //使用定义的新类型来声明对象,等价于int* (*a[5])(int,char*);


void (*b[10]) (void(*)());
typedef void (*p_fun_param)();
typedef void (*p_fun)(p_fun_param);                    //整体声明为一个新变量
p_fun b[10];                                           //使用定义的新类型来声明对象,等价于void (*b[10]) (void(*)());

double (*)() (*pa)[9];
typedef double (*p_fun)();
typedef pFun (*p_fun_param)[9];                        //整体声明一个新类型
P_fun_param pa;                                        //使用定义胡新类型来声明对象,等价于double(*)()(*pa)[9];


*给结构取别名


 七、右左法则

1、解释:从最内部的括号(第一次开始阅读声明时,必须从变量名开始)开始阅读声明,向右看,然后向左看。当碰到一个括号时就调转阅读的方向。括号内的所有内容都分析完毕就跳出括号的范围。

int * (*(*fp1) (int) )[10];

从变量名开始——fp1

往右看,什么也没有,碰到了),因此往左看,碰到一个*——一个指针。

跳出括号,碰到了(int)—— 一个带一个int参数的函数

向左看,发现一个*——(函数)返回一个指针

跳出括号,向右看碰到【10】—— 一个10元素的数组

向左看,发现一个*——指针

向左看,发现int——int类型

总结:fp1被声明为一个函数的指针,该函数返回指向指针数组的指针


int *(*(*arr[5]) ()) ();
从变量名开始——arr

往右看,发现是一个数组—— 一个5元素的数组

向左看,发现一个*——指针

跳出括号,向右看,发现()——不带参数函数

向左看,碰到*——(函数)返回一个指针

继续向左,发现int——int类型

总结:arr被声明为一个函数的数组指针,该函数返回指向函数指针的指针








猜你喜欢

转载自blog.csdn.net/qq_27397357/article/details/53765133