iOS开发系列--详细讲解C语言之存储方式和作用域

2020-01-18 17:27:22于海丽

概述

基本上每种语言都要讨论这个话题,C语言也不例外,因为只有你完全了解每个变量或函数存储方式、作用范围和销毁时间才可能正确的使用这门语言。今天将着重介绍C语言中变量作用范围、存储方式、生命周期、作用域和可访问性。

变量作用范围 存储方式 可访问性

变量作用范围

在C语言中变量从作用范围包括全局变量和局部变量。全局变量在定义之后所有的函数中均可以使用,只要前面的代码修改了,那么后面的代码中再使用就是修改后的值;局部变量的作用范围一般在一个函数内部(通常在一对大括号{}内),外面的程序无法访问它,它却可以访问外面的变量。


//
// main.c
// ScopeAndLifeCycle
//
// Created by Kenshin Cui on 14-7-12.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#include <stdio.h>

int a=1;
void changeValue(){
 a=2;
 printf("a=%dn",a);
}
int main(int argc, const char * argv[]) {
 int b=1;
 changeValue(); //结果:a=2
 printf("a=%d,b=%dn",a,b); //结果:a=2,b=1 ,因为changeValue修改了这个全局变量
 return 0;
}

变量存储方式

C语言的强大之处在于它能直接操作内存(指针),但是要完全熟悉它的操作方式我们必须要弄清它的存储方式。存储变量的位置分为:普通内存(静态存储区)、运行时堆栈(动态存储区)、硬件寄存器(动态存储区),当然这几种存储的效率是从低到高的。而根据存储位置的不同在C语言中又可以将变量依次分为:静态变量、自动变量、寄存器变量。

静态变量

首先说一下存储在普通内存中的静态变量,全局变量和使用static声明的局部变量都是静态变量,在系统运行过程中只初始化一次(在下面的例子中虽然变量b是局部变量,在外部无法访问,但是他的生命周期一直延续到程序结束,而变量c则在第一次执行完就释放,第二次执行时重新创建)。


//
// 2.1.c
// ScopeAndLifeCycle
//
// Created by Kenshin Cui on 14-7-12.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#include <stdio.h>

int a=1; //全局变量存储在静态内存中,只初始化一次

void showMessage(){
 static int b=1; //静态变量存储在静态内存中,第二次调用不会再进行初始化
 int c=1;
 ++b;
 a+=2;
 printf("a=%d,b=%d,c=%dn",a,b,c);
}

int main(int argc, const char * argv[]) {
 showMessage(); //结果:a=3,b=2,c=1
 showMessage(); //结果:a=5,b=3,c=1
 return 0;
}

自动变量

被关键字auto修饰的局部变量是自动变量,但是auto关键字可以省略,因此可以得出结论:所有没有被static修饰的局部变量都是自动变量。


//
// 1.3.c
// ScopeAndLifeCycle
//
// Created by Kenshin Cui on 14-7-12.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char * argv[]) {
 int a=1;
 auto int b=2;
 printf("a=%d,b=%dn",a,b); //结果:a=1,b=2 ,a和b都是自动变量,auto可以省略
 
 //需要注意的是,上面的自动变量是存储在栈中,其实还可以存储到堆中
 char c[]="hello,world!";
 long len=strlen(c)*sizeof(char)+1;//之所以加1是因为字符串后面默认有一个空操作符不计算在长度内
 char *p=NULL;//可以直接写成:char *p;
 p=(char *)malloc(len);//分配指定的字节存放c中字符串,注意由于malloc默认返回“void *”需要转化
 memset(p,0,len);//清空指向内存中的存储内容,因为分配的内存是随机的,如果不清空可能会因为垃圾数据产生不必要的麻烦
 strcpy(p,c);
 printf("p=%sn",p);//结果:p=hello,world!
 free(p);//释放分配的空间
 p=NULL;//注意让p指向空,否则p将会是一个存储一个无用地址的野指针
 
 
 return 0;
}