《K&R》04-函数与程序结构

作用域

  • 对于在函数开头声明的自动变量,其作用域是声明该变量的函数。
  • 外部变量或函数的作用域从声明它的地方开始,到其所在的(待编译的)文件的末尾。
  • 如果在外部变量声明之前使用该变量,或者外部变量的声明和使用不在同一个文件中,则必须在相应的变量声明中使用关键字extern
#include <stdio.h>

int i; 

int main()
{
    // 先于main声明变量i,在main函数中可直接使用
    printf("%d", i;

    return 0;
}
int main()
{
    // 编译报错
    // error: 'i' undeclared (first use in this function
    printf("%d", i);

    return 0;
}

int i;
int main()
{
    // 通过extern声明来访问一个尚未声明的外部变量
    extern int i;
    printf("%d", i); // 100

    return 0;
}

int i = 100;

静态变量(static关键字)

  • static修饰外部变量(或函数),则该变量仅限当前文件中可以访问。其他文文件不能通过extern关键字来访问。
  • static修饰函数内部变量,则无论函数是否被调用,该变量将一直存在,而不像自动变量那样,随着函数的被调用和退出而存在和消失。

寄存器变量

  • register声明告诉编译器,它所声明的变量在程序中使用频率较高。其思想是,将register变量放在机器的寄存器中,这样可以使程序更小,执行速度更快。但编译器可以忽略此选项。
  • register仅适用于函数的形式参数和自动变量。
f (register unsigned m, register long n)
{
    register int i;
    ...
}

初始化

  • 如果没有显式的初始化,外部变量及静态变量将被初始化为0,自动变量及寄存器变量则不的初值则没有定义(即初值为无用的信息)。
  • 对于外部变量及静态变量来说,初始化表达式必须是常量表达式。

数组初始化

  • 数组作为外部变量或者静态变量,其元素将被自动初始化为0,自动变量则为无效值。
  • 数组的初始化可以在声明的后面紧跟一个初始化表达式列表,初始化表达式列表用花括号括起来,各初始化表达式之间用逗号分隔。如果省略了数组的长度,则数组的长度为花括号中初始化表达式的个数。如果初始化表达式的个数少于指定的数组元素数,则对于外部变量、静态变量和自动变量来说,没有初始化表达式的元素将被初始化为0。
  • 字符数组的初始化比较特殊:可以使用一个字符串来代替初始化表达式列表。
// 未指定数组长度,以表达式的个数作为数组的长度,即12
int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
printf("%d\n", sizeof(days) / sizeof(int)); 

// 表达式的个数少于指定的索引数,没有初始化表达式的元素,初始值为0
// 相当于:{1, 2, 3, 4, 5, 0, 0, 0, 0, 0}
int nums[10] = {1, 2, 3, 4, 5};
for (int i = 0; i < 10; i++) 
{
    printf("%d", nums[i]);
    if (i == 9) {
        printf("\n");
    } else {
        printf(",");
    }
}
// 字符数组的初始化,下面两个语句是等价的
char s1[] = "ould";
char s2[] = {'o', 'u', 'l', 'd'};

作者: 砸缸之神

这是一个饱经沧桑的傻子发出的声音,他其实更愿做个柔弱而孩子气的砸缸人

发表评论

电子邮件地址不会被公开。 必填项已用*标注