一、存储类
自动存储、寄存器、具有代码块作用域的静态、具有外部链接的静态、以及具有内部链接的静态。
5种存储类说明符:auto、register、static、extern、typedef。
注意:不可以在一个声明中使用一个以上的存储类说明符;
1、作用域
代码块作用域、函数原型作用域和文件作用域。
2、链接
链接属性一共有3种:external(外部)、internal(内部)和none(无)。
备注:
1.链接属性分为external,internal,none。
2.全局变量默认拥有external链接属性;
static修饰的变量拥有internal链接属性;
函数体中的变量用于none链接属性。
3.拥有external链接属性的变量可被所有文件访问,只需要声明下即可(extern int b;)
拥有internal属性的变量只能在其定义的文件中被访问(static int sta_c;)
拥有none属性的变量只能在其定义开始处到代码块作用域结束处被访问。
4.给已经定义的变量添加任何链接属性声明(如:extern或static)都是无效的,变量原链接属性保持不变。
myfun.c
int b = 123;
int out_c = 315;
static double PI= 3.14159; //myfun.c文件以外的文件是不能访问PI变量的
int Add(const int first, const int second)
{
return first + second;
}
mian.c
int houcus;
int b; //② 等价于extern int b;即定义在myfun.c中的变量b
//最好写成extern int b;易于理解,这种简写模式只适用于全局作用域
//对于函数作用域是不能简写的,否则成了定义函数的局部变量。
int main(void)
{
extern int b; //③ external(外部链接)属性的b,其作用域起于此声明处止于语句④之前
printf("%d\n",b); //输出:123
int b = 456; //④ 函数的局部变量,链接属性为none;④处的变量b会屏蔽掉③处的变量b,
printf("%d\n",b); //④处变量b的作用域起于其定义处,止于函数结束输出: 456
extern int b; //⑤ 编译器将extern int b解析成:在已经定义的int b = 456 (④)基础
//上加了一个extern属性。C规定:在已经定义变量上加任何链接属性都不
//会改变变量的原链接属性。给b上加extern属性并不会使none链接属性变
//成extern链接属性。
printf("%d\n",b); //所以输出: 456
extern int out_c;//绝对不能简写成int out_c;否则是定义函数作用域的变量
printf("%d\n",out_c); //输出:315
<span style="white-space:pre"> </span> printf("%d\n",Add(15,25));
return EXIT_SUCCESS;
}
-----------------------------------------
123
456
456
315
40
2、存储时期
静态存储时期:如果一个变量具有静态存储时期,它在程序执行期将一直存在。
自动存储时期:具有代码块作用域的变量一般情况下具有自动存储时期,在程序进入定义这些变量的代码块时,将为这些变量分配内存,当退出这个代码块时,分配的内存将被释放。
3、自动变量(auto)
自动变量具有自动存储时期、代码块作用域和空链接。
默认情况下载在代码块或函数的头部定义的任意变量都属于自动存储类。
如果在内层代码块定义了一个具有和外层代码块变量同一名字的变量时,当运行离开内层代码块时,外部变量重新恢复作用。
自动变量的初始化:除非显示地初始化变量,否则它不会被初始化。
int main()
{
int x = 30;
printf("x in outer block: %d\n", x);
{
int x = 77;
printf("x in inner block: %d\n", x);
}
printf("x in outer block: %d\n", x);
while (x++ < 33)
{
int x = 100;
x++;
printf("x in while loop: %d\n", x);
}
printf("x in outer block: %d\n", x); // will print 34 not 33
return 0;
}
----------------------------------------------------
x in outer block: 30
x in inner block: 77
x in outer block: 30
x in while loop: 101
x in while loop: 101
x in while loop: 101
x in outer block: 34
4、寄存器变量(register)
因为寄存器变量多是存放在一个寄存器而非内存中,所以无法获得寄存器变量的地址。不能对寄存器变量使用地址运算符&
但是在其他的许多方面,寄存器变量与自动变量是一样的。
但是寄存器变量仅仅是一个请求,而非一条直接的命令,所以该变量不一定存在寄存器里,但是任然不能使用&取地址。
5、具有代码块作用域的静态变量
这些变量和自动变量具有相同的作用域,但包含这些变量的函数完成工作时,它们并不消失。
void trystat(void);
int main()
{
int count;
for (count = 1; count <= 3; ++count) {
printf("Here comes iteration %d:\n",count);
trystat();
}
return 0;
}
void trystat(void)
{
int fade = 1;
static int stay = 1;
printf("fade =%d and stay =%d\n",fade++,stay++);
}
-----------------------
Here comes iteration 1:
fade =1 and stay =1
Here comes iteration 2:
fade =1 and stay =2
Here comes iteration 3:
fade =1 and stay =3
可以产出fade 每次都初始化,而stay只初始化一次,如果不显示的对静态变量进行初始化,它们将被初始化0.
fade是函数的一部分,所以每次执行都会执行,stay不是函数的一部分,因为静态变量和外部变量在程序调入内存时已经就位了。把这个语句放在trystat()函数中是为了告诉编译器只有函数trystat()可以看到该变量
但是对函数参量不能使用static
int wontwork(static int flu) //不允许
6、具有外部链接的静态变量
具有外部链接的静态变量具有文件作用域、外部链接、和静态存储时期
外部变量的初始化
如果不对外部变量进行初始化,它们将自动被赋值0
int tern = 1;
int main(void)
{
external int tern; //不会引起空间分配
}
external int tern = 12; //不允许
7、具有内部链接的静态变量
具有内部链接的静态变量具有文件作用域、内部链接、和静态存储时期
static int svil = 1; // 具有内部链接的静态变量
二、内存分配(malloc( )和free())
函数原型在 stdlib.h
在程序运行时分配更多的内存
malloc( )可以返回 数组指针、结构指针等等。
一般的对应每个malloc( )调用,应该调用一次free( ).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double * ptd;
int max;
int number;
int i = 0;
puts("What is the maximum number of type double entries?");
scanf("%d", &max);
ptd = (double *) malloc(max * sizeof (double));
if (ptd == NULL)
{
puts("Memory allocation failed. Goodbye.");
exit(EXIT_FAILURE);
}
// ptd now points to an array of max elements
puts("Enter the values (q to quit):");
while (i < max && scanf("%lf", &ptd[i]) == 1)
++i;
printf("Here are your %d entries:\n", number = i);
for (i = 0; i < number; i++)
{
printf("%7.2f ", ptd[i]);
if (i % 7 == 6)
putchar('\n');
}
if (i % 7 != 0)
putchar('\n');
puts("Done.");
free(ptd);
return 0;
}