C语言变量的类型和作用域

发布于 2021-08-02  0 次阅读


自动变量类型 auto

auto int i = 1 等同于 int iauto 是变量的类型(int 是数据的类型),表示该变量自动利用内存创建和销毁,不需要人为设定。

作用域范围是函数作用域、块作用域,随着函数和块的退出而销毁。

块作用域范围内的变量只在块内生效,举例如下:

    auto int value = 0;
{
        auto int a = 0;
        printf("%dn",a);    // suuccess
}
    printf("%dn",a);        // error

静态变量类型 static

static 变量类型与 auto 变量类型相对应,为静态类型变量,其所占内存不会因函数退出而销毁。且不赋初值的情况下,系统默认值为 0。

其定义的变量,作用域会变为全局,即文件作用域。举例如下:

void LocalStaticVar(void) {
  // 静态变量
  // 1. 作用域全局,内存不会因函数退出而销毁
  // 2. int 初值默认为 0
  static int static_var;

  // 自动变量
  // 1. 函数、块作用域,随着函数和块退出而销毁
  // 2. 没有默认初值
  int non_static_var;

  printf("static var: %dn", static_var++);
  printf("non static var: %dn", non_static_var++);
}

int main(){

  int a[5] = {1,2,3,4,5};

  // TestScope(5, a);

  // TestStatic();

  LocalStaticVar();
  LocalStaticVar();
  LocalStaticVar();

  return 0;
}

static 类型的变量在定义后,一直将值保留,不在因函数退出而销毁。此外,-858993460 就是 0xcccccccc,烫的GBK编码是 cccc,烫烫烫此梗来源于此。

寄存器变量类型 register

寄存器变量(register int a)和其他类型变量(int a)的区别在于速度,汇编代码中有所体现。具体区别如下:内存变量传参时必须要把存入寄存器的变量值复制到内存的另一块空间中,再把那块空间的值复制到另一个寄存器,如下所示:edi 寄存器要先将变量值放入 PTR[rbp-4],再将值从 PTR[rbp-4] 放入 eax

void PassByMemory(int parameter)
{
  printf("%dn", parameter);
}
push    rbp
mov     rbp, rsp
sub     rsp, 16
mov     DWORD PTR [rbp-4], edi
mov     eax, DWORD PTR [rbp-4]
mov     esi, eax
mov     edi, OFFSET FLAT:.LC0
mov     eax, 0
call    printf
nop
leave
ret

相比之下,寄存器变量可以直接将一个寄存器中存入的变量值直接复制到另外一个寄存器中,无需额外操作。下文中,edi 寄存器的值直接复制到了 eax 中。

void PassByRegister(register int parameter)
{
  printf("%dn", parameter);
}
push    rbp
mov     rbp, rsp
mov     esi, edi
mov     edi, OFFSET FLAT:.LC0
mov     eax, 0
call    printf
nop
pop     rbp
ret

但在实际使用中无需考虑上述情况,编译器会自动选择最优解,将变量设置为寄存器变量还是内存变量。


大变に气分がいい