C语言-变量属性
变量属性
C语言中的变量可以有自己的属性,在定义变量的时候可以加上"属性"关键字。
属性关键字指明变量的特殊意义。
auto关键字
- auto是C语言中局部变量的默认属性。
- auto表明将被修饰的变量存储于栈上。
- 编译器默认所有的局部变量都是auto的。
代码示例
void f()
{
int i; // 局部变量默认属性为auto
auto int j; // 显示声明auto属性
}
register关键字
- register关键字指明将局部变量存储于寄存器中。
- register只是请求寄存器变量,但是不一定请求成功。
- register变量必须是CPU寄存器可以接受的值。
- 不能用&运算符获取register变量的地址。
代码示例
#include <stdio.h>
register int g_v; // error
int main()
{
register char var;
print("8x%88x", &var) // error
return 0;
}
static关键字
1、static关键字指明变量的静态属性。
static修饰的局部变量存储在程序静态区。
2、static关键字同时具有作用域限定符的意义。
static修饰的全局变量作用域只是声明的文件中。
static修饰的函数作用域只是声明的文件中。
代码示例
#include <stdio.h>
int g_v; // 全局变量,程序的任意地方均能访问
static int g_vs; // 静态全局变量,只有当前文件中可以访问。
int main()
{
int var; // 局部变量,在栈上分配空间。
static int var; // 静态局部变量,在静态数据区分配空间。
return 0;
}
实例分析
#include <stdio.h>
// 定义f1函数
int f1()
{
int r = 0;
r++;
return r;
}
// 定义f2函数
int f2()
{
static int r = 0;
r++;
return r;
}
int main()
{
auto int i = 0; // 显示声明 auto 属性,i 为栈变量
static int k = 0; // 局部变量 k 的存储区位于静态区,作用域位于 main 中
register int j = 0; // 向编译器申请将 j 存储于寄存器中
printf("%p\n", &i);
printf("%p\n", &k);
printf("%p\n", &j); // error
for(i=0; i<5; i++)
{
printf("%d\n", f1());
}
for(i=0; i<5; i++)
{
printf("%d\n", f2());
}
return 0;
}
图示:
extern关键字
extern用于声明“外部”定义的变量和函数。
- extern变量在文件的其他地方分配空间。
- extern函数在文件的其他地方定义。
代码示例
#include <stdio.h>
extern int getI();
int main()
{
printf("%d\n", getI());
return 0;
}
static int g_i;
int getI()
{
return g_i;
}
const关键字
const只读变量
- const修饰变量是只读的,本质上还是变量。
- const修饰的局部变量在栈上分配空间。
- const修饰的全局变量在全局数据区分配空间。
- const只是在编译期有用,在运行其无效果。
注意:
const修饰的变量不是真正的常量,他只是告诉编译器该变量不能出现在赋值符号的左边。
const全局变量的分歧
1、在现代C语言编译器中,修改const全局变量将导致程序崩溃。
2、标准C语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变。
代码示例
#include <stdio.h>
// 定义全局变量
const int g_cc = 2;
int main()
{
const int cc = 1;
printf("cc = %d\n", cc);
// 通过指针修改内存空间的地址
int* p = (int*)&cc;
*p = 3;
printf("cc = %d\n", cc);
p = (int*)&g_cc;
printf("g_cc = %d\n", g_cc);
// 修改内存空间
*p = 4;
printf("g_cc = %d\n", g_cc);
return 0;
}
const的本质
- C语言中的const使得变量具有只读属性。
- 现代C编译器中的const将具有全局生命周期的变量存储于只读存储区。
- const不能定义真正意义上的常量。
代码示例
#include <stdio.h>
// 定义一个const类型的全局数组
const int g_array[5] = {0};
// 定义modify函数
void modify(int* p, int v)
{
*p = v;
}
int main()
{
int const i = 0;
const static int j = 0;
int const array[5] = {0};
modify((int*)&i, 1); // ok
modify((int*)&j, 2); // error
modify((int*)&array[0], 3); // ok
modify((int*)&g_array[0], 4); // error
printf("i = %d\n", i);
printf("j = %d\n", j);
printf("array[0] = %d\n", array[0]);
printf("g_array[0] = %d\n", g_array[0]);
return 0;
}