数据类型是变量的模子,理解为固定内存大小的别名;而变量是一段连续存储空间的别名。
1. auto
l 默认属性,只能修饰局部变量,存放在栈中;
l auto变量在内存中的地址并不是一成不变的,每次调用函数时都可能不同,所以并不初始化。
2. register
l 请求为寄存器变量(不一定成功)。因为其不存在内存地址,故不能用“&”获得register变量地址;
l 只能修饰局部变量,不允许修饰外部变量和静态变量,必须是寄存器可接受的值,受硬件寄存器长度的限制,寄存器变量只能是int、char或指针型。
3. static
l 静态是指地址固定。既可修饰局部变量又可修饰全局变量;
l 数据存储在全局数据区,虽然作用域仅在函数内部,但生命周期是全局的;
l static变量只被初始化一次,但可以多次赋值;
l static修饰的变量或函数只是声明的文件中,具有文件作用域限定的意义。
eg:
int add1(int a,int b)
{
static int result = a + b; //定义并初始化
return result;
}
int add2(int a,int b)
{
static int result = 0;
result = a + b;
return result;
}
int main()
{
int a = add1(2,1); // int a = add2(2,1);
int b = add1(3,4); // int b = add2(2,1);
if(a == b)
cout << 1 << endl;
return 0;
}
调用add1时,输出1;调用add2时,输出无。原因在于static变量只初始化一次,第二次初始化直接跳过。静态变量在全局开辟的空间result其空间上方有一个标志域0,程序若检查到标志域为0则赋值,否则不执行。
4. extern
l 用于声明外部定义的变量和函数;
l 用于告诉编译器用C方式编译;
eg:
#ifdef _cplusplus //_cplusplus是cpp中自定义的宏
extern “C”{
#endif
//C代码
#ifdef _cplusplus
}
#endif
5. volatile
禁止编译器优化(频繁取同一个内存中的值时,值会存放在缓存中),每次必须从内存中取变量值。
eg:
int obj = 10;
int a = 0, b = 0;
a = obj;
sleep(100);
b = obj;
编译阶段发现obj没有被当做左值使用,因此将obj替换成10,而把a和b都赋值为10。隐患,在sleep期间产生硬件中断,将obj值改为100,此时b = 10达不到预期效果。
使用volatile变量的例子:
l 并行设备的硬件寄存器(如:状态寄存器);
l 一个中断服务子程序中会访问到的非自动变量或中断服务程序中修改的供其他程序检测的变量;
l 多线程应用中被几个任务共享的变量。
6. const
变量由const修饰,但本质仍是变量,所以存储在堆栈和静态存储区,这些区域从进程角度讲是可读可写的,但是为什么const修饰后就不可写了?
原因:C语言编译主要分为编译和链接两个部分,如果人为修改只读变量,在编译器编译阶段检查语法错误时将报错,这是C语言规定的语法,而不是const修饰的内存空间属性变成了只读,所以我们可以修改这个空间的值,只不过我们需要获取这个空间的地址。
eg:const变量
#include <stdio.h>
int main(void)
{
const int i = 100;
//int *p = &i; //实体和模子应当匹配,实体:int*实体;模子:const int*类型
int *p = (int *)(&i);
*p = 200;
printf("now the value of i is %d\n",i);
return 0;
}
输出:
windows:the value of i is 200
eg:常量
#include <stdio.h>
int main(void)
{
char *p = "hello world";
*p = 'w';//编译通过,不报warning
return 0;
}
这段代码可以通过编译的第二步:编译过程,生成汇编代码,但是运行时程序崩溃。常量放在内存中的静态区的常量区,这块空间由系统管理,编译器无权管理,所以编译时不报警告,运行时崩溃。
左数右指:
const int *p; //p可变,p指向的内容不可变
int const *p; // p可变,p指向的内容不可变
int * const p; //p不可变,p指向的内容可变
const int * const p; //p不可变,p指向的内容不可变
C++标准规定const关键字放在类型或变量名前等价,如:const int n = 5; int const n = 5;
7. void
l 如果函数没有返回值,应声明为void,否则默认为返回int;
l C语言中,可以向无参的函数传送任意类型的参数(不支持函数重载),C++不行;
l 不存在void变量,C语言中没有规定void究竟是多大内存的别名;
l void *指针作左值用于接受任意类型的指针;作右值时,需要强制类型转换;
ANSI标准规定不能对void指针进行算法操作,因为不知道其指向数据类型大小。
0.0分
0 人评分