static变量的作用
1,改变变量的生命期
对于static全局变量而言,生命期没有改变,在整个程序执行过程中该变量一直存在。但其作用域反而减小,只有本文件的函数可以引用该全局变量。
对于static局部变量,其作用于没有改变,只有定义该局部变量的函数可以引用该变量。但其生命期发生了改变,在整个程序执行期间,该变量都存在。
下面程序演示static局部变量,该程序打开若干个文件并将文件的内容输出到屏幕中,每输出5行就会输出1个换行:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 1024
int output(char *file_name)
{
FILE *fp;
char buf[Max];
static int count = 0; /*静态变量,保存输出的行数*/
fp = fopen(file_name, "r"); /*打开文件*/
if(NULL == fp)
{
perror("faul to open the file.");
return -1;
}
//此处注意fgets函数的使用方法
while(fgets(buf, Max, fp) != NULL) /*每次读入文件的一行*/
{
int n = strlen(buf);
buf[n-1] = '\0';
printf("%s\n", buf); /*输出读入的一行*/
if(count++ % 5 == 0) /*累加count,能够被5整除,换行*/
{
printf("\n");
}
}
fclose(fp); /*关闭文件*/
return 0;
}
int main(void)
{
char file_name[][10] = {"test.txt",
"test1.txt",
"test2.txt"
};
int i;
i = 0;
while(i < 3)
{
if(output(file_name[i]) == -1)
{
exit(1);
}
i ++;
}
return 0;
}
注意:如果将局部变量count的存储类型设置为非static,每个文件的输出行数的累加就不会被保存了。
当然,也可以使用全局变量来代替静态局部变量,但不能保证程序中其他函数对全局变量造成干扰。
2,实现封装和模块化设计
Static存储类型的特性决定了使用static关键字声明的全局变量只有本文件内的函数可以引用,因此在C语言中一个源程序文件就是一个模块。当用户在一个文件中定义了一个static全局变量后,其他文件(模块)只能通过该模块提供的接口函数来访问这个static全局变量,而不能直接对其进行操作。
下面程序演示一个链表模块的实现。
程序1,list.c:
#include <stdio.h>
typedef node* Node; /*自定义结点指针类型*/
static Node head; /*链表头*/
/*链表结点结构
*val: 结点的值
*next: 下一个节点的指针
*/
struct node
{
int val;
Node next;
};
/*插入结点函数*/
int insert_node(int value)
{
Node p, q;
p = head;
if(NULL != p) /*链表非空*/
{
while(NULL != p->next)
p = p->next;
}
q = (Node)malloc(sizeof(struct node)); /*创建一个新的结点*/
if(NULL == q)
{
return -1;
}
q->next = NULL; /*对结点赋值*/
q->val = value;
if(NULL == p) /*空链表*/
{
head = q;
return 1;
}
p->next = q; /* 结点插入链表 */
return 1;
}
/* 遍历链表,打印每个结点的值 */
void print()
{
Node p = head;
while(NULL != p) /* 打印每个结点的值 */
{
printf("%d\n", p->val);
p = p->next;
}
}
/* 遍历链表,释放每一个结点 */
void destroy()
{
Node p = head;
while(NULL != p) /* 遍历链表 */
{
Node q;
q = p;
p = p->next; /* 到下一个结点 */
free(q); /* 释放该节点 */
}
head = NULL; /* 清空链表的头指针 */
}
程序2,list.h:
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
extern int insert_node(int val); /*插入节点函数*/
extern void print(); /*遍历链表,打印每个链表的值*/
extern void destroy(); /*遍历链表,释放每一个节点*/
#endif // LIST_H_INCLUDED
程序3,main.c:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
int main(void)
{
int i;
for(i = 0; i < 5; i ++) /* 使用insert函数插入5个结点 */
if(insert_node(i) == -1)
exit(1);
print(); /* 输出链表的所有结点 */
destroy(); /* 销毁链表 */
return 0;
}