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;
}
posted @ 2020-05-17 14:17  guardwhy  阅读(279)  评论(0编辑  收藏  举报