C语言第九回合:作用域和存储类型

C语言第九回合:作用域和存储类型 

【学习目标】

1.        局部变量

2.        全局变量

3.        存储类型

4.        内存

A: 局部变量

局部变量也称为内部变量。局部变量是在函数内定义说明。

作用域:仅在声明的函数或复合语句内内,有效区也在函数或复合语句内。

B: 全局变量

全局变量也称为外部变量,是在函数外定义的变量。

作用域:整个与程序文件

PS: 局部变量和全局变量是按照作用域来划分的。

#include <stdio.h>

int numuber;  //全局变量
              //作用范围为整个本文件

//定义print函数.无参数,也无返回值
void print( void )
{
         float score; //局部变量
                      //作用范围为print函数内

         return ;  //作为print的结束标志
}
int main( void )
{
         //局部变量score可以同名
         float score; //局部变量
                      //作用范围为main函数内
         print();

    return 0;
}

C: auto的使用

在函数或复合语句内部,如不声明变量为static存储类型,则就称该变量为auto变量

PS:C 语言规定,关键字auto可以省略(默认条件下都是auto)。

D: static的使用

(1)修饰变量(存在内存的静态区)

(a)  静态局部变量:是用static修饰的局部变量。

PS:静态局部变量保存在静态数据区,生命周期和程序相同。特别注意,静态局部变量只能在被定义的函数内使用,保存的只一直存在!

(b) 静态全局变量:是用static修饰的全局变量。

PS:静态全局变量只能作用域声明的文件中,不能被其他文件引用。

( 2)修饰函数(静态函数,又称内部函数)

在函数前加上static,就成为静态函数。这里的’static’意思不是指存储方式,而是指对函数的作用仅局限于本文件

 //功能:观察静态局部变量
#include <stdio.h>

//静态函数定义
//定义静态的print函数,作用范围只能在本文本中
//返回值为void,参数也为void
static void print( void )
{
    static intnum= 0;  //静态局部变量的定义

    num++; //num=num+ 1;

   printf("%d\n", num );

                   return; //返回类型为void,所以不返回什么。这样写可以提高可读性
}

int main( void )
{
    //auto变量的定义
                   floatscore= 99.0;  //等同于 autofloat score= 99.0;

                   //第一次调用print函数
                   printf("第一次调用后,num的值: " );
                   print();

                   //第二次调用print函数
                   printf("第二次调用后, num的值: " );
                   print();

    return 0;
}

运行结果:

我们会发现,num的值是在前一次调用后的值基础上自加的。

E: register变量(寄存器变量)

用register修饰的变量,就是register变量。register:这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。(是尽可能,但不是绝对,因为CPU的寄存器个数有限!!)

PS: 虽然寄存器的速度非常快,但是使用register修饰符也有些限制的:register变量必须是能被CPU寄存器所接受的类型。意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度。而且 register变量可能不存放在内存中,所以不能用取址运算符“&”来获取register变量的地址。

F: extern的使用

关键字extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中

【扩展知识】

在看下面程序时,先看看这点知识。这是在自定义头文件中经常使用的

 //(整体作用)防止头文件被重复引用
   #ifndef TEXTC_H
   #define TEXTC_H
   //内容。。。
   #endif

testc.h文件中【注意:这是自定义的头文件】

//textc.h文件
//extern的使用

#ifndef TEXTC_H   //(整体作用)防止头文件被重复引用
#define TEXTC_H

int    number= 100;
float  score= 99.9;
char   ch= 'A';

#endif

main.c文件

#include <stdio.h>
#include "textc.h"  //自定义的头文件。打“”的意思是先在当前文件目录下查找头文件

int main( void )
{

     extern int number;   //声明number已定义。下同。
     extern float score;
     extern char ch;

     printf("number= %d\n", number );
     printf( " score= %.1f\n", score );
     printf( "    ch= %c\n", ch );

         return0;
}    

main.c必须与testc.h一起!

运行结果:

G:内存

内存可以分为三个部分:堆、栈和静态区【堆就是堆,栈就是栈】

  1. 堆:由malloc系列函数分配的内存。其生命周期由free或delete决定。                                                                            特点:使用灵活,空间比较大,但容易出错。
  2. 栈:保存局部变量。栈上的内容只在函数内存在,当函数运行结束,就会自行销毁。                                                                                 特点:效率高,但使用大小有限。
  3. 静态区:保存自动全局变量和static变量。静态区的内容在整个程序的生命周期内都存在。
//堆、栈和静态区的程序解释
#include <stdio.h>
#include <stdlib.h> //for函数malloc()和exit()提供原函数

//定义内存分配函数Malloc,无参数也无返回值
void Malloc( void )
{
         intnum= 100; //局部变量,存储在栈中,函数一结束就销毁内存

         char*str;  //定义一个char类型的指针变量

         //malloc函数的使用,分配100个字节空间
         str=( void* )malloc( num* sizeof( char ) ); //强制类型的转换
         if(str== NULL )
         {
                   printf("内存分配失败\n" );

                   exit(1 );  //程序退出
         }
         //str动态内存分配成功,存储在堆中。

   return ;
}

//定义静态全局函数
static int number= 1 ; //存储在静态区,只有当程序结束时才会被销毁

int main( void )
{
         floatscore=  99.9;  //局部变量,存储在栈中

   return 0;
}

H:内存分配函数

【扩展知识】在使用这些函数前必须”科普”一下

1.      size_t就是unsignedint 的别名,因为大小不允许为负数。

2.      void *(空类型指针)可以强制换为任何类型指针,但不允许逆操作!

3.      sizeof()是求字节大小,但不可以求动态分配的内存。

4.      void perror ( const char * str);打印错误信息

( 1 ) malloc的使用

原型:void* malloc (size_t size);

分配size大小的字节内存,并返回指向内存开始的指针

//malloc使用例子
#include <stdio.h>
#include <stdlib.h>  //malloc,free.exit

int main( void )
{
         unsignedint num; //定义无符号int型变量
         char*str;  //定义char类型指针变量str

         num=100;  //赋值语句,把100赋值给num

         //为str分配100个字节
         str=( char* )malloc( num* sizeof( char ) );
         if(str== NULL ) // 检测是否分配成功
         {
             perror( "内存分配失败\n");

             exit( 1 ); //退出程序
         }
         else
         {
                   printf("内存分配成功\n" );
         }

         free(str );//释放分配的内存
         str=NULL; //把NULL赋值给str,防止成为野指针

   return 0;
}  

(2 ) calloc的使用

原型:void* calloc (size_t num, size_t size); //size为类型大小,num为个数

分配num* size大小的内存空间,并初始化为0,再返回指向内存开始的指针

//calloc的使用
#include <stdio.h>
#include <stdlib.h>

int main( void )
{
         unsignedint num;
         inti;
         int*array;  //定义int型指针

         num=10 ;

         //分配num*sizeof( int )大小的内存,并全初始化为0
         array=( int * )calloc( num, sizeof( int ) );
         if(array== NULL )
         {
                   perror("内存分配失败\n" );

                   exit(1 ); //退出程序
         }
         else
         {
                   printf("内存分配成功\n" );

                   for(i= 0; i< num; i++ )
                   {
                            printf("%d ", array[ i ] ); //可以同过数组的访问方式范围元素
                   }
         }

         //释放内存
         free(array );
         array=NULL;

   return 0;
}

运行结果:

内存分配成功

0 0 0 0 0 0 0 0 0 0

(3 ) realloc的使用

原型:void* realloc (void* ptr, size_t size);

改变指针ptr的内存大小

//realloc的使用
#include <stdio.h>
#include <stdlib.h>  // malloc realloc,free,exit

int main( void )
{
         unsignedint num= 5;
         inti= 0;
         int*array= NULL;
         int*more_array= NULL;

         array=( int * )calloc( num, sizeof( int ) );
         if(array== NULL )
         {
                   perror("内存分配失败\n" );

                   exit(1 );
         }

         printf("calloc:内存分配成功\n");

         //给数组array赋值
   for( i= 0; i< num; i++ )
         {
                   array[i ]= i;
         }

         printf("再次分配内存前: " );
         for(i= 0; i< num; i++ )
         {
                   printf("%d ", array[ i ] );
         }

         //realloc从新分配内存
         num=10;
         more_array=realloc( array, num* sizeof( int ) );
         if(array== NULL )
         {
                   perror("内存分配失败\n" );

                   exit(1 );
         }

         printf("\n\nrealloc:内存分配成功\n" );
         //给数组more_array赋值
         for(i= 0; i< num; i++ )
         {
                   array[i ]= i;
         }

         printf("再次分配内存后: " );
         for(i= 0; i< num; i++ )
         {
                   printf("%d ", array[ i ] );
         }

         free(array );
         array=NULL;

         return0;
}

运行结果:

calloc:内存分配成功

再次分配内存前:0 1 2 3 4

realloc:内存分配成功

再次分配内存后:0 1 2 3 4 5 6 7 8 9

(4 ) free的使用

原型: void free (void* ptr);

【指尖的微笑】错误在所难免,希望得到大家的指正^-^

转载时保留原文的链接http://codingit.howbbs.com和http://blog.csdn.net/mirrorsbeyourself

时间: 2024-07-28 15:30:31

C语言第九回合:作用域和存储类型的相关文章

C语言入门(十四)变量的作用域和存储类型

变量的作用域和存储类型 一.作用域和生存期 C程序的标识符作用域有三种:局部.全局.文件.标识符的作用域决定了程序中的哪些语句可以使用它,换句话说,就是标识符在程序其他部分的可见性.通常,标识符的作用域都是通过它在程序中的位置隐式说明的. 1.局部作用域 前面各个例子中的变量都是局部作用域,他们都是声明在函数内部,无法被其他函数的代码所访问.函数的形式参数的作用域也是局部的,它们的作用范围仅限于函数内部所用的语句块. void add(int); main() { int num=5; add(

C和指针 3.9作用域、存储类型示例

1 int a = 5; 2 extern int b; 3 static int c; 4 5 int d( int e ) 6 { 7 int f = 15; 8 register int b; 9 static int g = 20; 10 extern int a; 11 ... 12 { 13 int e; 14 int a; 15 extern int h; 16 ... 17 } 18 ... 19 { 20 int x; 21 int e; 22 ... 23 } 24 ...

C语言:链接属性与存储类型

一. 链接属性 C语言中链接属性决定如何处理在不同文件中出现的标示符.标示符的作用域与它的链接属性有关,但这两个属性并不相同. 链接属性有3种: external(外部),internal(内部) 和 none(无). 1. none: 没有链接的标示符,总是被当做单独的个体,也就是说改标示符的多个声明被当做不同的实体. 2. internal: 在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同的实体. 3. external: 标示符不论声明多少次,位于几个文件

C/C++中变量的作用域和存储类型简介

写在开头 对于很多C/C++的初学者来说,很容易理不清变量的作用域和存储类型这一块的一些概念,也容易将其中的一些概念搞混淆.作为一个C/C++的初学者,笔者希望在这里能够尝试着去理一理这些较为繁杂的概念,主要当作自己备忘之用.当然,由于笔者水平有限,经验不足,在这里也只能罗列一些常用概念和使用方法,且可能会有些许不专业之处,望君理解并指正. 一定要把变量的作用域和存储类型分开来看 很多人很容易把变量的作用于和存储类型搞混,但其实只要我们从它们定义出发来看,这个问题是很容易解决的.作用域是一个变量

【转】作用域、链接属性、存储类型总结--转载学习,很清晰,很详细

标识符: 首先,在讨论这三种东西之前,详细说明一下C语言中的标识符. 标识符是用户编程为变量.常量.函数.语句等指定的名字,就好比人名一样的东西. 标识符的命名规则如下: 1.只能由字母.数字.下划线组成,并且首字符不能是数字: 2.不能把C语言的关键字作为标识符: 3.对大小写敏感: 其次,需要明确,作用域和链接属性是在标识符范畴内讨论的,存储类型是在标识符中的变量范畴内讨论的. 作用域: 标识符的作用域就是程序中该标识符可以被使用的区域,由它的声明位置决定. 分为以下四类: 1.文件作用域

作用域 属性链接 存储类型

一:作用域: 4中不同类型的作用域:代码块作用域,函数作用域,文件作用域和原型作用域 1:代码块作用域: 一对花括弧的代码称作一个代码块,任何在花括弧开始声明的标识符都具有代码块作用域 形参隐藏的问题: K&RC中,形参在函数体外的声明中开始变生效,如果在函数体内有同名的表示服,他们就会将形参隐藏. ANSIC中避免了这种情况,他把形参的作用域定义在函数最外层的那个函数体,也就是整个函数体,这样,声明与函数最外的局部变量无法和形参同名,因为他们的作用域相同2:文件作用域: 任何在所有代码块之外声

【转】C语言中标识符的作用域、命名空间、链接属性、生命周期、存储类型

Technorati 标签: C,标识符,作用域,命名空间,链接属性,生命周期,存储类型,scope,name space,linkage,storage durations,lifetime 无论学习哪一种语言,都免不了要讨论这些问题.而且这些问题,深究起来有时也让我们很迷惑. 标识符的定义无需多讲,只需注意不仅仅是指变量,还有函数,标签等. 1. 标识符的作用域 作用域是指允许对标识符进行访问的位置范围.按照C99(章节6.2.1),C语言的作用域共有 4 种类型:文件作用域.代码块作用域.

嵌入式 Linux C语言(八)——存储类型、作用域、生命周期、链接属性

嵌入式 Linux C语言(八)--存储类型.作用域.生命周期.链接属性 一.存储类型 C语言中,每个变量和函数都有两个属性:数据类型和数据的存储类型. 变量的存储类型是指存储变量值的内存类型.变量的存储类型决定变量何时创建.何时销毁以及它的值将保持多久.计算机中有三个地方可以用于存储变量:普通内存,运行时堆和栈,硬件寄存器.变量的存储类型取决于声明变量的位置. C语言存储类别说明符: 说明符 用    法 auto 只在代码块内变量声明中被允许, 表示变量具有本地生存期 extern 出现在顶

C语言中的作用域,链接属性和存储类型

作用域 当变量在程序的某个部分被声明的时候,他只有在程序的一定渔区才能被访问,编译器可以确认4种不同类型的作用域:文件作用域,函数作用域,代码块作用域和原型作用域 1.代码块作用域:位于一对花括号之间的所有语句称为一个代码块.任何在代码块的开始位置声明的标识符都具有代码块作用域,表示他可以被这个代码块中的所有语句访问.(例子中:f,g函数,i) 2.文件作用域:任何在所有代码块之外声明的标识符都具有文件作用域,他表示这些标识符从他们的声明之处直到他所在的源文件结尾处都是可以访问的.(例子中:a,