精华内容
下载资源
问答
  • 作者:starwing83网友 谭书其实和C语言有一个很相像地方,就是都出了很多个版本。然而C语言出新版本是为了方面程序员、适应新变化和开发风格。...定义变量的位置:一般在函数开头声明部分定义变量...

    作者:starwing83网友
      谭书其实和C语言有一个很相像的地方,就是都出了很多个版本。然而C语言出新的版本是为了方面程序员、适应新的变化和开发风格。而一本教材出新的版本无非就是修正错误和描述语言的新方向。然而,如果一本教材的第一版就是概念不清胡说八道,却又碍着面子不肯承认自己的错误,那最终的结果就是越错越远了。
      就比如这里:

    定义变量的位置:一般在函数开头的声明部分定义变量,也可以在函数外定义变量(即外部变量、全局变量,见第7章)。C99允许在函数中的复合语句(用一句花括号括起来)中定义变量。
    ————谭浩强 ,《C程序设计》(第四版),清华大学出版社, 2010年6月,(前言)p41

      我相信谭老一定没有亲自去看过C99标准,不知道是英文不好还是自信满满觉得自己比标准要牛。所以,虽然谭老的确知道有“标准化”这么一个说法,却只有错上加错的份儿。事实上,我看不出这里的“一般”有什么凭据,难道谭老从没有看过正式地C语言项目吗?一般情况下,只有八十年代到九十年代的C语言项目才会“一般”在函数开头定义变量,新的项目一般定义变量的位置是复合语句的开头。将自己的臆测煞有介事地说成业界惯例,不知道这是无耻还是做得太多已经麻木了。
      让我们来揭开谜底吧。实际上,这段话几乎每一句都是错误的。”一般在函数开头的声明部分“,很遗憾地,C99根本就没有“声明部分”的说法,而C90中,声明部分根本就不止限于函数开头!“也可以在函数外定义变量”这一句是对的,然而括号坏事了:“(即外部变量,全局变量)”,事实上C语言根本没有全局变量的说法,只有外部变量,静态变量的说法,因为事实上这里的全局是有两个含义的:文件域的全局,和整个程序范围的全局。这两个含义是根据变量的链接性来定义的,我们之前就提到了链接性的概念,而谭书对此只字不提。“C99运行在函数中的复合语句(用一对花括号括起来)中定义变量”,首先这是C90的特性,而不是C99的,其次,括号内的部分明显代表谭老根本就不知道什么是复合语句,花括号本身是复合语句的一部分,复合语句花括号内的部分在标准中是被叫做“块项列表(block-item-list)”的,而列表中的一个块项既可以是声明,也可以是语句。对基本概念都不清晰,也难怪错的这么离谱了。
      我们总结一下:
      - C99实际上是允许你在任何地方声明变量的。
      - C90声明部分实际上是可以在任何复合语句的开头的。
      也就是说,下面的代码在C90里面仍然是合法的:

        void reverse(int array[], size_t size) {
            int i = 0, j = size - 1;
            for (; i < j; ++i, --j) {
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    

     

       只有唯一一种情况是必须在函数开头申请变量的:即该变量在整个函数的执行过程中都必须存在。而真正有这么一个需求是很罕见的。如同这里的 temp 变量,它只需要在交换的时候才存在,因此就不该把它和 i, j 声明在一起。上面的代码是合法的 C90 代码,可以在任何严格支持 C90 (而不支持 C99)的编译器下编译。
      就算你用的是C90的编译器,你也仍然可以获得“随处声明变量”的特权,很简单,在需要使用局部变量的时候,直接用复合语句即可,这也是复合语句作为一种单独的语句类型出现的另一个理由。(前一个理由是作为其他语句(如if for)中的语句部分存在)
      在真正使用的时候申请变量是个好习惯,这也是 C99 真正的改变是允许变量在任意位置定义,而不仅限复合语句开头的缘故。这可以防止变量的名字冲突,简化逻辑——新申请的变量哪怕名字和之前申请的一致,也不会对旧的变量有任何影响,一旦新变量超过作用域,旧的变量仍然有效。这是C语言的一个重大特性,也被认为是C语言最优秀的一个特性,这个特性就是大名鼎鼎的“词法作用域”。它被广泛地用在了大量的语言上,是编程语言的一个约定俗成的基本特性。如果不允许在复合语句内申请变量,无异于让C语言自废武功。
      并且,我们知道,C语言的局部变量是分配在栈上的。那么局部变量的及时释放也帮助节省栈空间:对于两个平行的复合语句块,其内部的局部变量事实上是共享一块区域的,这就是词法作用域的另一个实际好处。
      为什么谭老即使是愿意让C语言自废武功,也不愿意介绍真正的C99的变量声明特性呢?原因是谭书的前一个版本言之凿凿地说明“变量只允许声明在函数开头”,记得我最开始看谭书的时候,就一直是这么申请变量的,直到自行翻阅C90标准才走出这个误区。08年的时候我帮助一个上海交大的生物系研究生修改其 DNA 检测代码,就发现一堆的 i,j, k, l, m, n 被申请在函数开头,整个程序十分难维护,后来花了很大功夫才将代码整理完成,由此可见谭书危害之深。
      程序员一个重要的素质就是肯承认错误,肯承认失误。程序本就是思维的结晶,是智慧最集中的产品。不肯承认错误,就一定会被更先进者替代。而谭书却死死抓住“权威”两字不放,宁愿错上加错也不肯承认自己不是完人。这样的心态怎么符合一个程序员的自我修养呢?又怎么培育合格的程序员呢?书的销量越好,事实上是流毒越多而已。
      下面我们介绍一下C99真正的新特性,看看标准委员会为C语言的进步做出了什么样的努力。
    C99从C++中引进了可以“随处申请变量”的特性,并修改了 for 语句的语法,添加了一个新的 for 语句形式。对C99来说,复合语句内已经不区分“声明部分”和“语句部分”,在任何地方都可以书写声明或者语句,而新加入的 for 语句的语法是允许 for 的第一个部分是声明,后跟可选的表达式(注意声明本身会带上一个分号),后跟必须的分号,再跟可选的表达式。也就是说,上面的反转函数实际上可以这么写:

        void reverse(int array[], size_t size) {
            for (int i = 0, j = size - 1; i < j; ++i, --j) {
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    

     

       这时,i, j, temp 就同属一个作用域了,即 for 语句的语句体。在 for 语句之外使用 i, j, temp 会造成编译错误。
      注意和C++不同,对C99来说只有 for语句才有在第一部分申请变量的殊荣, if、while等等语句都是不允许的。而在C++里面这些语句的条件判断部分都是可以申请新变量的。
      从C99的新特性可以看出,C语言显然易见地是支持并鼓励“使用处声明”的编程方法的。而谭书却对此只字不提,挂着着C99的羊头,卖着C89的狗肉,不愿大大方方地承认自己的错误,甚至连一点点改过的意向都没有,只是一门心思的一错再错,一条路走到黑。这种态度不止是一本教科书编撰者,就算只是一个普通的程序员,恐怕也逃不过被开除的命运。

    转载于:https://www.cnblogs.com/pmer/archive/2012/04/22/2464766.html

    展开全文
  • 这句话是错误,因为一个函数内部可以有多个复合语句。 举个栗子: void main(void) { // 复合语句1 { // 复合语句2 int a = 10; } printf("%d\n",a);...这说明在复合语句(代码块)中定义的变量...

    这句话是错误的,因为一个函数内部可以有多个复合语句。
    举个栗子:

    void main(void)
    {	// 复合语句1
    	{	// 复合语句2
    		int a = 10;
    	}
    	printf("%d\n",a);
    }```
    编译后报错:[Error] 'a' undeclared (first use in this function)(变量a未声明)
    这说明在复合语句(代码块)中定义的变量,不可以在复合语句之外使用。
    (第一次用这玩意,排版就这样吧,懒得折腾了)
    
    展开全文
  • <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ... 多个语句用括号{}括起来组成一个语句称复合语句。...程序应把复合语句看成是单条语句,而不是多条语句。 如: {   

    多个语句用括号{}括起来组成的一个语句称复合语句。 

    在程序中应把复合语句看成是单条语句,而不是多条语句。
    如:

    {  

         x=y+z;  

         a=b+c;  

         printf("%d%d",x,a);  

    }  

    是一条复合语句。

    复合语句内的各条语句都必须以分号“;”结尾;此外,在括号“}”外不能加分号。



    定义变量可能有三种情况: 

    (1)在函数的开头定义;

    (2)在函数内的复合语句内定义.;

    (3)在函数的外部定义.;

           在一个函数内部定义的变量只在本函数范围内有效,也就是说只有在本函数内才能引用它们,在此函数以外是不能使用这些变量的.在复合语句内定义的变量只在本复合语句范围内有效,只有在本复合语句内才能引用它们.在该复合语句以外是不能使用这些变量的.以上这些成为"局部变量".

           程序的编译单位是源程序文件,一个源文件可以包含一个或若干个函数.在函数内定义的变量是局部变量,而在函数之外定义的变量称为外部变量,外部变量是全局变量(也称全程变量).全局变量可以为本文件中其他函数所共用.它的有效范围为从定义变量的位置开始到本源文件结束.

    展开全文
  • c语言之函数中的变量

    2020-05-29 17:18:40
    一、局部变量与全局变量 ... 一个函数内部,复合语句(块)中定义变量,这些变量只复合语句中有效。 如果局部变量有效范围重叠,则有效范围小优先。 #include "stdio.h" void main() { int i=2,j=3,k;

    一、局部变量与全局变量

    1.1、局部变量

    函数内部或块内定义的变量。

    1.2、局部变量的作用域(作用范围)

    • 主函数中定义的变量只在主函数中有效,因为主函数也是一个函数,它与其他函数是平行关系。
    • 不同的函数中可以使用相同的变量名,因为它们代表不同的变量,它们之间互不干扰。
    • 在一个函数内部,在复合语句(块)中定义变量,这些变量只在本复合语句中有效。
    • 如果局部变量的有效范围重叠,则有效范围小的优先。
    #include "stdio.h"
    void main()
    {
    int i=2,j=3,k;
    k=j+i;
    
    {
    int h=8;
    printf("%d\n",h);
    
    }
    printf("%d\n",k);
    }

     

     

    1.3、全局变量

    在函数外面定义的变量为全局变量

    1.4、全局变量的作用域

    全局变量为文本中的其他函数共有,它的有效范围是从定义点开始,直到源文件结束,全局变量又称为外部变量。

    /*打印10个100~200之间的随机数并输出最大和最小数*/
    #include "stdio.h"
    #include "math.h"
    #include "stdlib.h"
    int min;  // 全局变量
    int fid()
    {
        int max,r,i;  // max局部变量
    	r=rand()%101+100;
    	//printf(" %d",r);
    	max=r;min=r;
    	for(i=1;i<10;i++){
    		r=rand()%101+100;   // 产生100 ~200之间的随机数
    	if(r>max)
    		max=r;
    	if(r<min)
    		min=r;
    
    	printf("%d\t",r);
    	}
    	return max;
    
    }
    void main()
    {
      int m = fid();
      printf("\n最大数:%d\n,最小数:%d\n",m,min);
    }

    /*局部变量与全局变量同名案例
    当局部变量与全局变量同名,在局部变量的作用范围内,全局变量不起作用,局部变量优先
    */
    #include "stdio.h"
    //#include "math.h"
    //#include "stdlib.h"
    int a=3,b=5;        // 全局变量 a,b
    int max(int a, int b)  // 局部变量 a,b
    {
    int c;
    c=a>b?a:b;
    return c;
    }
    void main()
    {
    int a=8;   // 局部变量a
    printf("%d\n",max(a,b));
    }
    
    /*
    不建议使用全局变量的原因:
    为了方便区别全局变量和局部变量,将局部变量的第一个字母用大写表示
    
    1、全局变量在程序的全部执行过程中都占用存储单元,而不是在需要时才开辟单元。
    2、它使等函数的通用性降低。
    3、全局变量过多,会降低程序的清晰性
    
    
    
    
    
    */

    1.5、全局变量的注意事项

    为了方便区别全局变量和局部变量,将局部变量的第一个字母用大写表示

    1、全局变量在程序的全部执行过程中都占用存储单元,而不是在需要时才开辟单元。
    2、它使等函数的通用性降低。
    3、全局变量过多,会降低程序的清晰性

    二、变量的存储类别

    按变量的存在时间(生命周期)来划分,可以分为静态存储变量和动态存储变量。

    动态存储变量(这时一种节省内存空间的存储方式):当程序运行进入定义它的函数或复合语句时才被分配存储空间;程序运行结束离开此函数或复合语句时,释放动态动态存储变量所占用的空间。

    静态存储变量:在程序运行的整个过程中,始终占用固定的内存空间,直到程序运行结束,才释放占用的内存空间。静态存储类别的变量被放于内在空间的静态存取区域

    c程序运行时,占用三部分的内存空间

    • 程序运行时数据分别存储在静态存储区动态存储区
    • 静态存储区用来存放程序运行周期内所占用固定存储单元的变量,如全局变量;
    • 动态存储区用来存放不需要长期占用内存的变量,如函数的形参等;
    • 变量的存储类别有四种:自动类型(auto),寄存器类型(register),静态类型(static)外部类型(extern)
    • 动态变量:自动类型、寄存器类型
    • 静态变量:静态类型,外部类型

    2.1、自动类型变量(auto)

    用关键字auto说明变量是自动类型变量


    格式:
    auto 类型  变量名;

     自动类型变量属于动态局部变量,存储在动态存储区,定义时可以加auto也可以不加,由此可知局部变量都是自动类型变量
     自动类型的分配和释放存储空间的工作是由编译系统自动处理

    int function1(int a)
    {
    auto int b,c=3;
    /*形参a,变量b,c都是自动类型变量
    在调用该函数时,系统给它们分配存储空间调用结束时自动释放存储空间*/
    }

    2.3、寄存器类型变量(register)

    用关键字register说明变量是寄存器类型
    格式:
    register 类型  变量名;
    register int a;

    寄存器变量是动态局部变量,存放于CPU的寄存器或动态存储区中,以提高存取速度,寄存器的存取速度比内存快。
    该类变量的作用域、生存期与自动类型变量相同;如果没有存放在通用寄存器中,按自动类型变量处理


    计数机中寄存器个数是有限的,使用register的注意事项

    • 寄存器类型变量不宜过多,一般将频繁使用的变量放在寄存器中(循环涉及的内部变量),以提高程序执行的速度
    • 变量的长度应该与常用寄存器的长度相当,一般为int型或char型。
    • 寄存器变量的定义通常是不必要的,当今优化的编译系统能够识别频繁使用的变量,并能够在不需要编译人员说明变量是register的时候,把频繁使用的变量放到寄存器中。
    
    #include "stdio.h"
    //#include "math.h"
    //#include "stdlib.h"
    void main()
    {
    
    	int x=5,y=10,k;     // 自动类型变量
    	for(k=1;k<=2;k++)
    	{
    	register int m=0,n=0;
    	m=m+1;
    	n=n+y;
    	printf("m=%d\t=%d\n",m,n);
    	}
    }
    
    /*
    用关键字register说明变量是寄存器类型
    格式:
    register 类型  变量名;
    register int a;
    
    寄存器变量是动态局部变量,存放于CPU的寄存器或动态存储区中,以提高存取速度,寄存器的存取速度比内存快。
    该类变量的作用域、生存期与自动类型变量相同;如果没有存放在通用寄存器中,按自动类型变量处理
    
    
      计数机中寄存器个数是有限的,使用register的注意事项
      1、寄存器类型变量不宜过多,一般将频繁使用的变量放在寄存器中(循环涉及的内部变量),以提高程序执行的速度
       2、变量的长度应该与常用寄存器的长度相当,一般为int型或char型。
     
    
    
    */

    2.4、静态变量(static)

    • 静态类型的变量占用静态存储区,用static关键字来说明
    • static  类型  变量名;
    • static int a;
    • 静态变量=静态局部变量+静态全局变量
    • c语言规定了静态局部变量(静态全局变量)有默认值:
    • int类型等于0
    • float型等于0.0
    • 自动变量和寄存器变量没有默认值,值为随机数
    • char型为'\0'

    静态局部变量

    静态局部变量是存储在静态存储区的,所以在整个程序开始的时候就被分配固定的存储单元,整个程序运行期间内不再被重新分配,故其生存期是整个程序的运行期间。

    静态局部变量本身也是局部变量,具有局部变量的性质,即其作用域是局限在定义它的本函数内的,如果离开了定义它的函数,该变量就不再起作用,但其值任在,因为存储空间并未释放。

    静态局部变量赋初值的时间是编译阶段,并且只被初值一次,即使它所有的函数调用结束,也不释放存储单元,因此不管调用多少此该静态局部变量的函数,它任保留上一次调用函数时的值。

    2.5、外部变量

    • 定义在任何函数之外的变量都叫做外部变量。外部变量通常用关键字extern说明。
    • 一般形式:  extern  类型  变量名;
    • extern  int a;
    • extern double k;

        
        一个文件中定义的全局变量默认为外部的,即extern关键字可以省略。但是如果其他文件要使用这个文件中定义的全局变量,则必须在使用前用extern作为外部声明,外部声明通常放在文件的开头

    三、案例

    #include <stdio.h>
    extern int days();
    extern int year,month,day;
    void main(){
    printf("输入年,月,日:\n");
    scanf("%d%d%d",&year,&month,&day);
    printf("%d月%d日是%d年的第%d\n",month,day,year,days());
    }
    int year,month,day;
    int days()
    {
    
    int i,count=0;
    int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    if((year%100)&&!(year%4)||!(year%400))
    a[2]=20;
    for(i=0;i<month;i++)
    count+=a[i];
    count=count+day;
    return count;
    }
    
    

     

    展开全文
  • C++局部变量C++局部变量是指:一个函数内部定义的变量,它只函数范围内有效,也就是说只有函数内才能使用它,函数以外是不能使用...可以一个函数的复合语句中定义变量,这些变量只本复合语句中...
  • 一、变量按作用域范围...(4)在复合语句中也可以定义变量,但其作用域只能在复合语句内。 全局变量:在函数外定义变量,它作用域是从变量定义开始,到程序文件末尾。如果在定义点前函数要使用该外部变量,要
  • 4.11局部变量和全局变量 每一个变量都有其有效作用范围,这就是变量的作用域。 4.11.1局部变量 ...同样在复合语句中定义的变量本复合语句范围内有效,这些内部变量称为局部变量(local variabl...
  • C语言中,我们知道放在函数普通变量的值只能通过return语句返回值,但是如果只是把复合语句放在主函数中,则复合语句中的变量定义又该如何呢?我们来看下边一个例子: #include <conio.h> #include &...
  • 变量的定义必须写在复合语句的开头,并且任何其他语句前面。可以一次声明多个相同类型的变量。如果需要,可以使用 DEFAULT 赋默认值。 定义一个变量的语法如下: DECLARE var_name[,...] type [DEFAULT valu...
  • 同样,在复合语句中定义的变量本复合语句范围内有效。这称为局部变量(local variable)。如: 对局部变量的一些说明: 1) 主函数main中定义的变量(m, n)也只主函数中有效,不会因为主函数中定义而整个...
  • 局部变量定义变量一般有三种形式:在函数的开头定义在函数的外部定义在复合语句中定义其中在函数的开头和在复合语句中定义的时候,只能在函数内部和该复合语句中使用,像这种变量称为局部变量。 例...
  • 有些书讲局部变量的作用域是在函数,在函数调用时全部入栈,其实这种理解只在c89的标准下是对的,在c99局部变量是可以在函数的任何地方声明的,他的左右域也可是复合语句 ,  下面我们就来了解一下,复合语句...
  • 函数中形参和在函数中定义局部变量包括在复合语句中定义的局部变量 调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间,auto可以省略,大部分变量都是自动类型 不在编译时赋...
  • 我们知道函数中的形参变量只有被调用时候才分配内存单元,调用结束立即释放。这说明形参变量只有在函数内部才有效,离开函数就...如果变量在某个复合语句定义变量具有从定义位置开始到复合语句结束为止局部作用
  • 全局变量 全局变量默认初始化为0,字符型变量为空字符’’ ...如果定义在符合语句内,只在复合语句中有效 同一文件中全局变量和局部变量可以同名,局部变量作用域内,全局变量不起作用 静态全局变量 静态...
  • 点击上方“C语言入门到精通”,选择置顶第一时间关注程序猿身边故事作者闫小林白天搬砖,晚上做梦。...同样,在复合语句中定义的变量本复合语句范围内有效,如下就是局部变量:#include//头文件 usingnames...
  • 局部变量:在一个函数中或复合语句中定义的变量,存储在栈中。局部变量在动态存储区分配存储单元,在调用时动态分配,在函数或复合语句结束时自动释放。 静态局部变量:在一个函数中定义局部变量时,若加上static...
  • 局部变量与全局变量

    2021-01-08 11:31:01
    局部变量与全局变量的关系是一个非常重要且细致问题,这方面,稍不注意就非常容易出问题。现稍作总结。 变量的作用域 变量的作用域是指变量的...复合语句中定义的变量只能该复合语句中使用 for()循环中定义
  • C语言中的局部变量和全局变量

    千次阅读 2019-03-17 16:25:02
    一.作用域 首先,我们先明白一个重要的概念,...(1)在函数的开头定义变量。 (2) 在函数内的复合语句定义。 (3)形式参数 在一个函数内部定义变量只在本函数范围内有效,也就是只有本函数内才能引用它们,在此...
  • 由第1章已知,一个程序包含一个或多个程序单位(每个程序单位构成一个程序文件)。...包括函数首部和函数体,在函数可以包含若干声明语句和执行语句。  如下面是一个完整C++程序:  复制纯文本新窗口  #inclu
  • 局部变量 :  一个函数内部定义变量是局部变量,它只函数范围内有效,也就是说只有函数内才能使 ... (3) 一个函数内部,可以再复合语句中定义变量,这些变量仅本复合语句中有效,
  • 局部变量在函数的开头定义在函数内的符合语句内定义作用范围在包含该局部变量的函数内有效一个函数内部,可以在复合函数语句中定义变量,这些变量只在本复合语句中有效,这种符合语句称为分程序或程序块 #include<...
  • 4.在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效。 (2)全局变量 定义:在函数外定义变量是全局变量,全局变量可以为本文件中其它函数所共用,它有效范围从定义变 量位置开始到...
  • 全局变量 首先一个源文件里面包含若干个函数,所有函数之外...在复合语句定义变量只能复合语句范围内有效,只有本复合语句内才能引用他们,复合语句外不能使用这些变量。还有就是函数的形参,只该函数
  • 另一种是在函数的复合语句(如{}包含的程序块)中定义变量,它只能在本复合语句内使用,该复合语句外不能使用。  2、全局变量是在函数之外定义的变量。全局变量可以为本文件中函数所共用(用extern声明后也可被外

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 426
精华内容 170
关键字:

在函数的复合语句中定义变量