《匠人手记》推荐网上购书渠道:
互动出版网(china-pub)购书入口   >>>
当当网(dangdang)购书入口   >>>
卓越亚马逊网 购书入口   >>>
淘宝网(taobao)购书入口   >>>
更多购书渠道……   >>> 

设为首页加入收藏联系匠人管理入口21IC首页21IC博客21IC社区侃单片机回复的贴参与的贴

天气预报
百宝日历
载入中...

百宝专栏

载入中...
最新货色

载入中...

粉丝评论

载入中...

载入中...



百宝信息

载入中...

百宝流量

(2006-07-01开始)


匠人手记

 匠人观点: 好记性不如烂笔头  
 黑色幽默:三鹿门——后世畅想

学C51的基础4 《 变 量 》
程序匠人 发表于 2005-9-30 11:19:00  阅读全文 | 回复(0) | 引用通告 | 编辑

学C51的基础4 《 变 量 》 作者[cmh]

            --- 摘自《C51BBS离线版光盘》---

    4. 变量

    4.1  变量说明
    Turbo C2.0规定所有变量在使用前都必须中以说明。一条变量说明语句由数据类型和其后的一个或多个变量名组成。变量说明
的形式如下:
    类型 <变量表>;
    这里类型是指Turbo C2.0的有效数据类型。变量表是一个或多个标识符名,每个标识符之间用 "," 分隔。
    例如:
          int i, j, k;   unsigned char c, str[5], *p;

    4.2 变量种类
    变量可以在程序中三个地方说明: 函数内部、函数的参数定义中或所有的函数外部。根据所定义位置的不同, 变量可分为局部
变量、形式参数和全程变量。
    一、局部变量
    局部变量是指在函数内部说明的变量(有时也称为自动变量)。用关键字auto进行说明, 当auto省略时, 所有的非全程变量都被
认为是局部变量, 所以auto实际上从来不用。
    局部变量在函数调用时自动产生,但不会自动初始化,随函数调用的结束,这个变量也就自动消失了, 下次调用此函数时再自动产
生, 还要再赋值, 退出时又自动消失。

    二、形式参数
    形式参数是指在函数名后面的小括号里定义的变量, 用于接受来自调用函数的参数。形式参数在函数内部可以象其它局部变量
那样来作用。
    例如:
     puthz(int x, int y, int color, char *p)
     {
          int i, j, k;   /*定义局部变量*/
          <程序体>
     }
    其中x, y, color, *p为函数的形式参数, 不需要再进行说明就可在该函数内直接使用。

    三、全程变量
    全程变量是指在所有函数之外说明的变量,它在整个程序内部者是"可见的", 可以被任何一个函数使用, 并且在整个程序的运行
中都保留其值。全程变量只要满足在使用它以前和函数以外这两个条件,可在程序的任何位置进行说明, 习惯上通常在程序的主函数
前说明。
    例如:
     #i nclude<stdio.h>
     int test;                /*定义全程变量*/
     void f1(int x, float y); /*子函数说明*/
     void f2(void);           /*子函数说明*/
     main()
     {
          test=5;             /*给全程变量赋值*/
          f1(20, 5.5);        /*调用有形式参数的子函数f1()*/
                              /*test的值变成115*/
          f2();               /*调用f2(), test的值变为1150*/
     }
     void f1(int x, float y)
     {
          float z;            /*z定义为局部变量*/
          z=x*y;              /*计算*/
          test=test+z;
     }
     void f2(void)
     {
          int count=10;       /*定义局部变量并初始化*/
          test=test*count;
     }

    由于全程变量可被整个程序内的任何一个函数使用, 所以可作为函数之间传递参数的手段,但全程变量太多时, 内存开销变大。
    4.3 变量存储类型
    Turbo C2.0支持四种变量存储类型。说明符如下:
     auto      static    extern    register
下面分别来介绍。
    一、auto
    auto称为自动变量, 已在前面作了介绍, 这里不再重复。
    二、static
    static称为静态变量。根据变量的类型可以分为静态局部变量和静态全程变量。
    1. 静态局部变量
    它与局部变量的区别在于: 在函数退出时, 这个变量始终存在, 但不能被其它函数使用, 当再次进入该函数时, 将保存上次的
结果。其它与局部变量一样。
    2. 静态全程变量
    Turbo C2.0允许将大型程序分成若干独立模块文件分别编译, 然后将所有模块的目标文件连接在一起, 从而提高编译速度, 同
时也便于软件的管理和维护。静态全程变量就是指只在定义它的源文件中可见而在其它源文件中不可见的变量。它与全程变量的区
别是: 全程变量可以再说明为外部变量(extern), 被其它源文件使用, 而静态全程变量却不能再被说明为外部的, 即只能被所在的
源文件使用。
    三、extern
    extern称为外部变量。为了使变量除了在定义它的源文件中可以使用外, 还要被其它文件使用。因此, 必须将全程变量通知每
一个程序模块文件, 此时可用extern来说明。
    例如:
        文件1为file1.c                  文件2为file2.c
    int i, j;/*定义全程变量*/        extern int i, j;/*说明将i, j从文件1中复制过来*/
    char c;                          extern char c; /*将c复制过来*/
    void func1(int k);               func2()        /*用户定义函数*/
                                     {
    main()                              static float k;/*定义静态变量*/
    {                                   i=j*5/100;
          func1(20);/*调用函数*/        k=i/1.5;
          func2();                           .
          .                                  .
          .                                  .
          .                            }
     }
     func1(int k) /*用户定义函数*/
     {
          j=k*100;
     }

    对于以上两个文件file1.c和file2.c, 用Turbo C2.0的集成开发环境进行编译连接时, 首先应建立一个.prj的文件。例如
file.prj, 该文件内容如下:
     file1.c
     file2.c
    然后将file.prj的文件名写入主菜单Project中的Project Name项中。再用F9编译连接, 就可产生一个文件名为fioe.exe的可
执行文件。
    外部变量和FORTRAN语言中的COMMOM定义的公共变量一样。
    四、register
    register称为寄存器变量。它只能用于整型和字符型变量。定义符register说明的变量被Turbo C2.0存储在CPU的寄存器中, 而
不是象普通的变量那样存储在内存中, 这样可以提高运算速度。但是Turbo C2.0只允许同时定义两个寄存器变量, 一旦超过两个,
编译程序会自动地将超过限制数目的寄存器变量当作非寄存器变量来处理。因此, 寄存器变量常用在同一变量名频繁出现的地方。
    另外, 寄存器变量只适用于局部变量和函数的形式参数, 它属于auto型变量, 因此, 不能用作全程变量。定义一个整型寄存器
变量可写成:
      register int a;
    对于以上所介绍的变量类型和变量存储类型将会在以后的学习中, 通过例行程序中的定义、使用来逐渐加深理解。

    4.4  数组变量
    所谓数组就是指具有相同数据类型的变量集, 并拥有共同的名字。数组中的每个特定元素都使用下标来访问。数组由一段连续
的存贮地址构成, 最低的地址对应于第一个数组元素, 最高的地址对应最后一个数组元素。数组可以是一维的、也可以是多维的。
Turbo C2.0象它高级语方一样也使用数组变量。

    一、一维数组
    一维数组的说明格式是:
      类型  变量名[长度];
    类型是指数据类型, 即每一个数组元素的数据类型, 包括整数型、浮点型、字符型、指针型以及结构和联合。
    例如:
     int a[10];
     unsigned long a[20];
     char *s[5];
     char *f[];

    说明:
    1. 数组都是以0作为第一个元素的下标, 因此, 当说明一个int a[16] 的整型数组时, 表明该数组有16个元素, a[0]~a[15],
一个元素为一个整型变量。
    2. 大多数字符串用一维数组表示。数组元素的多少表示字符串长度, 数组名表示字符串中第一个字符的地址, 例如在语句
char str[8] 说明的数组中存入"hello"字符串后, str表示第一个字母"h"所在的内存单元地址。str[0] 存放的是字母"h"的ASCII
码值, 以此类推, str[4]存入的是字母"o"的ASCII码值, str[5]则应存放字符串终止符'\0'。
    3. Turbo C2.0对数组不作边界检查。例如用下面语句说明两个数组
    char str1[5], str2[6];
    当赋给str1一个字符串"ABCDEFG"时,只有"ABCDE"被赋给,"E"将会自动的赋给str2,这点应特别注意.

    三、多维数组
    多维数组的一般说明格式是:
       类型  数组名[第n维长度][第n-1维长度]......[第1维长度];
    这种说明方式与BASIC、FORTRAN等语言中多维数组的说明不一样。
    例如:
      int m[3][2];       /*定义一个整数型的二维数组*/
      char c[2][2][3];   /*定义一个字符型的三维数组*/
    数组m[3][2]共有3*2=6个元素, 顺序为:
      m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1];
    数组c[2][2][3]共有2*2*3=12个元素, 顺序为:
      c[0][0][0], c[0][0][1], c[0][0][2],
      c[0][1][0], c[0][1][1], c[0][1][2],
      c[1][0][0], c[1][0][1], c[1][0][2],
      c[1][1][0], c[1][1][1], c[1][1][2],
    数组占用的内存空间(即字节数)的计算式为:
     字节数=第1维长度*第2维长度*...*第n维长度*该数组数据类型占用的字节数
    4.5  变量的初始化和赋值

    一、变量的初始化
    变量的初始化是指变量在被说明的同时赋给一个初值。Turbo C2.0中外部变量和静态全程变量在程序开始处被初始化, 局部变
量包括静态局部变量是在进入定义它们的函数或复合语句时才作初始化。所有全程变量在没有明确的初始化时将被自动清零,而局部
变量和寄存器变量在未赋值前其值是不确定的。
    对于外部变量和静态变量, 初值必须是常数表达式, 而自动变量和寄存器变量可以是任意的表达式, 这个表达式可以包括常数
和前面说明过的变量和函数。
    1. 单个变量的初始化
    例如:
     float f0, f1=0.2;        /*定义全程变量, 在初始化时f0被清零, f1被赋0.2*/
     main()
     {
          static int i=10, j; /*定义静态局部变量, 初始化时i被赋10, j不确定*/
          int k=i*5;          /*定义局部变量, 初始化时k被赋10*5=50*/
          char c='y';         /*定义字符型指什变量并初始化*/
          .
          .
          .
     }

    2. 数组变量的初始化
    例如:
     main()
     {
          int p[2][3]={{2, -9, 0}, {8, 2, -5}};  /*定义数组p并初始化 */
          int m[2][4]={{27, -5, 19, 3}, {1, 8, -14, -2}};/*定义数组m并初始化*/
          char *f[]={'A', 'B', 'C'};             /*定义数组f并初始化*/
          .
          .
          .
     }
    从上例可以看出: Turbo C2.0中数组进行初始化有下述规则:
    (1) 数组的每一行初始化赋值用"{}"并用","分开, 总的再加一对"{}"括起来,最后以";"表示结束。
    (2) 多维数组的存储是按最右维数的变量变化最快的原则。
    (3) 多维数组存储是连续的, 因此可以用一维数组初始化的办法来初始化多维数组。
    例如:
     int x[2][3]={1, 2, 3, 4, 5, 6};/*用一维数组来初始化二维数组*/
    (4) 对数组初始化时, 如果初值表中的数据个数比数组元素少, 则不足的数组元素用0来填补。
    (5) 对指针型变量数组可以不规定维数, 在初始化赋值时, 数组维数从0 开始被连续赋值。
    例如:
     char *f[]={'a', 'b', 'c'};
    初始化时将会给3个字符指针赋值, 即: *f[0]='a', *f[1]='b', *f[2]='c'。

    3. 指针型变量的初始化
    例如:
     main()
     {
          int *i=7899;        /*定义整型数指针变量并初始化*/
          float *f=3.1415926; /*定义浮点数指针变量并初始化*/
          char *s="Good";     /*定义字符型指针变量并初始化*/
          .
          .
          .
     }

    二、变量的赋值
    变量赋值是给已说明的变量赋给一个特定值。
    1. 单个变量的赋值
    (1) 整型变量和浮点变量
    这两种变量采用下列格式赋值
          变量名=表达式;
    例如:
     main()
     {
          int a, m;      /*定义局部整型变量a, m*/
          float n;       /*定义局部浮点变量f*/
          a=100, m=20;   /*给变量赋值*/
          n=a*m*0.1;
          .
          .
          .
     }

    说明:
    Turbo C2.0中允许给多个变量赋同一值时可用连等的方式。
    例如:
     main()
     {
          int a, b, c;
          a=b=c=0;       /*同时给a,b,c赋值*/
          .
          .
          .
     }

    (2)  字符型变量
    字符型变量可以用三种方法赋值。
    例如:
     main()
     {
          char a0, a1, a2;    /*定义局部字符型变量a0, a1, a2*/
          a0='b';             /*将字母b赋给a0*/
          a1=50;              /*将数字2(十进制ASCII值为50赋给a1*/
          a2='\x0d';          /*将回车符赋给a2*/
          .
          .
          .
     }

    (3) 指针型变量
    例如:
     main()
     {
          int *i;
          char *str;
          *i=100;
          str="Good";
          .
          .
          .
     }
    *i表示i是一个指向整型数的指针, 即*i是一个整型变量, i是一个指向该整型变量的地址。
    *str表示str是一个字符型指针, 即保留某个字符地址。在初始化时, str没有什么特殊的值, 而在执行str="Good"时, 编译器
先在目标文件的某处保留一个空间存放"Good\0"的字符串, 然后把这个字符串的第一个字母"G"的地址赋给str, 其中字符串结尾符
"\0"是编译程序自动加上的。
    对于指针变量的使用要特别注意。上例中两个指针在说明前没有初始化, 因此这两指针为随机地址, 在小存储模式下使用将会
有破坏机器的危险。正确的使用办法如下:
    例如:
     main()
     {
          int *i;
          char *str;
          i=(int*)malloc(sizeof(int));
          i=420;
          str=(char*)malloc(20);
          str="Good, Answer!";
          .
          .
          .
     }
    上例中, 函数(int*)malloc(sizeof(int))表示分配连续的sizeof(int)=2个字节的整型数存储空间并返回其首地址。同样
(char*)malloc(20)表示分配连续20个字节的字符存储空间并返回首地址(有关该函数以后再详述)。由动态内存分配函数malloc()
分配了内存空间后, 这部分内存将专供指针变量使用。
    如果要使i指向三个整型数, 则用下述方法。
    例如:
     #i nclude<alloc.h>
     main()
     {
          int *a;
          a=(int*)malloc(3*sizeof(int));
          *a=1234;
          *(a+1)=4567;
          *(a+2)=234;
          .
          .
          .
     }
    *i=1234表示把1234存放到i指向的地址中去, 但对于*(i+1)=4567, 如果认为将4567存放到i指向的下一个字节中就错了。
Turbo C2.0中只要说明i为整型指针,
则   (i+1) 等价于 i+1*sizeof(int)
同样 (i+2) 等价于 i+2*sizeof(int)

    2. 数组变量的赋值
    (1) 整型数组和浮点数组的赋值
    例如:
     main()
     {
          int m[2][2];
          float n[3];
          m[0][0]=0, m[0][1]=17, m[1][0]=21;/*数组元素赋值*/
          n[0]=109.5, n[1]=-8.29, n[2]=0.7;
          .
          .
          .
     }

    (2)字符串数组的赋值
    例如:
      main()
     {
          char s[30];
          strcpy(s, "Good News!");  /*给数组赋字符串*/
          .
          .
          .
     }
    上面程序在编译时, 遇到char s[30]这条语句时, 编译程序会在内存的某处留出连续30个字节的区域, 并将第一个字节的地
址赋给s。当遇到strcpy( strcpy 为Turbo C2.0的函数)时, 首先在目标文件的某处建立一个"Good News!\0" 的字符串。
其中\0表示字符串终止, 终止符是编译时自动加上的,然后一个字符一个字符地复制到s所指的内存区域。因此定义字符串数组时,
其元素个数至少应该比字符串的长度多1。
    注意:
    1. 字符串数组不能用"="直接赋值, 即s="Good News!"是不合法的。所以应分清字符串数组和字符串指针的不同赋值方法。
    2. 对于长字符串, Turbo C2.0允许使用下述方法:
    例如:
     main()
     {
          char s[100];
          strcpy(s, "The writer would like to thank you for"
                    "your interest in his book. He hopes you"
                    "can get some helps from the book.");
          .
          .
          .
     }

    (3)指针数组赋值
    例如:
     main()
     {
          char *f[2];
          int *a[2];
          f[0]="thank you";   /*给字符型数组指针变量赋值*/
          f[1]="Good Morning";
          *a[0]=1, *a[1]=-11; /*给整型数数组指针变量赋值*/
          .
          .
          .
     }

    三、数组与指针
    数组与指针有密切的联系。数组名本身就是该数组的指针, 反过来, 也可以把指针看成一个数组, 数组名和指针实质上都是地
址, 但是指针是变量, 可以作运算。而数组名是常量, 不能进行运算。
    例如:
     main()
     {
          char s[30], *p; /*定义字符型数组和指针变量*/
          p=s;            /*指针p指向数组s的第一个元素s[0]的地址*/
          .
          .
          .
          *(p+8);         /*指针p指向数组s的第9个元素s[8]的地址*/
          .
          .
          .
     }
    由上例可以看出数组和指针有如下关系:
    (p+i)=&(s[i])
    *(p+i)=s[i]
    因此, 利用上述表达式可以对数组和指针进行互换。两者的区别仅在于: 数组s是程序自动为它分配了所需的存储空间; 而指针
p则是利用动态分想函数为它分配存储空间或赋给它一个已分配的空间地址。

看《匠人手记》,与匠人同行!北航出版,正在热卖!

发表评论:
载入中...

芯片专题

器件专题

软件专题

硬件专题

综合专题

项目专题

原创专题

器件检测
LCD LED
按键 触摸键
E2PROM
电池 电机
电阻 电容 电感

指令系统
软件算法
编程规范
滤波算法
串行通讯

PCB设计
I2C PWM
红外遥控
充电技术
中断 ADC 

匠人手记
匠人夜话
网络心路
一周热点串烧
从零开始玩PIC
DIY旋转时钟

广告5号位 [投放]


学习板、开发板、编程器、下载器、仿真器(查看详情……)

广告3号位 [投放]

站内搜索


站外搜索


百度  google
mp3  歌词 
图片  FLASH 
知道  文档
新闻  词典 
地图  mp3 
软件  天网 
雅虎  爱问 
搜狗  讯雷 
网讯  华军 
天空 

21IC器件搜索
百宝箱分站
  • 《匠人的百宝箱》21IC站
  • 《匠人的百宝箱》21IC笔记团队
  • 《匠人手记》21IC书友会
  • 《匠人的百宝箱》MCUBLOG站
  • 《匠人的百宝箱》MCUBLOG笔记团队
  • 《匠人的百宝箱》EDN站
  • 《匠人手记》EDN书友会
  • 《匠人的百宝箱》与非网站
  • 《匠人的百宝箱》新浪站
  • 《匠人的百宝箱》百度站
  • 《匠人的百宝箱》网易126站
  • 《匠人的百宝箱》网易163站
  • 《匠人的百宝箱》互动出版网站
  • 广告4号位 [投放]

     
     

    匠人原创

    往日酷贴

     
     
     

    大千八卦

    友情连接

    新浪新闻:
    新浪财经:
    AK58新闻:
    新浪股票:
    新浪股票:
    证券之星:

     [更多酷站连接]

     

     

    [欢迎交换连接]

    [百宝箱之与非门分舵]

    [电脑圈圈的家当]

    [IC921的博客]

    [柔月阁]

    [八楼的呼吸]

    [hotpower 的水潭]

    [xwj的文君阁]

    [所长的BLOG]

    [阿摆手记]

    [电子伙伴]

    [unaided的笔记]

    [小飞的笔记]

    [单片机开发联盟]

    [网址之家]

    [好东西网址大全]

    [美萍中文精选]

    [数字电视之家]

    [SMARTCODE电子书斋]

    [软件开发之窗]

    [Armoric]

    [我爱研发网]

    [infernal的笔记]

    [雄鹰的空中加油站]

    [SunK]

    [逍遥电子]

    [ningpanda的博客]

    [C-Design]

    [一网见天下]

    [海边淘沙]

    [嵌入式365]

    [水牛的仓库]

    [股剩是怎样炼成的]

    [PIC论坛]

    [ICC AVR开发网]

    [中国高校自动化网]

     

     

     

    MCU博客-中国电子工程师博客网 

    大学生电子网 

     

     

     

     

     

    !!! 《匠人的百宝箱》 !!!