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://www.bangedushuren.cn/)的技术部LearnCoding(http://it.bangedushuren.cn/)原创,转载请注明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值