精华内容
下载资源
问答
  • 对于一个含有n个变量的程序
    千次阅读
    2021-03-08 04:16:34

    用指针方式编写程序,从键盘输入10个整形整数,并存入数组,要求将10个数中最大的数与第1个输入的数交换;将10个数中最小

    #includevoidmain(){inta[10],i,*m,*n,k=0;\x09printf("请输入十个数\n");for(i=0;i

    用指针方式编写程序,从键盘输入10个整形整数,并存入数组,要求将10个数中最大的数与第1个输入的数交换;

    "float*Grade(float*num,inti)//用来冒泡排序num传入数组指针,i传入数组个数{intj,k;floattemp;for(j=0;j

    编写程序,从键盘输入任意n个整数,用指针方法找出其中最大和最小的数?

    #includeintmain(){inta,b=0,c=100;int*pmax,*pmin;scanf("%d",&a);pmax=&b;pmin=&c;while(a!=-1)//输入-1结束{if(*pmaxa)*pmin=a;sc

    VisualC++ 编写程序,从键盘输入10个实数,计算并输出其算数平均值

    #includevoidmain(){floatnum[10],sum=0,avg;inti;for(i=0;i<10;i++){printf("请输入第%d个数:\n",i+1);s

    用C语言编写一个程序:从键盘输入n(0

    1:次数最多2:在次数最多的基础上,数值最大_______________________________________________以下为程序:#include//设置最大值#defineMAX100typedefstructreco

    编写一个程序,用12个月份的英文名称初始化一个字符指针数组,当键盘输

    更多相关内容
  • 功能测试技术——边界值分析法

    千次阅读 2021-11-05 22:09:47
    一、边界值分析法的概念 二、常见的边界值 三、边界值分析法设计测试用例 四、标准型(一般性)测试 五、健壮性测试 一、边界值分析法的概念 ... 边界值分析法就是对...例如,一个循环条件为“≤”时,却错写成...

    一、边界值分析法的概念

    二、常见的边界值

    三、边界值分析法设计测试用例

    四、标准型(一般性)测试

    五、健壮性测试


    一、边界值分析法的概念

           边界值分析法就是对输入的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其测试用例来自等价类的边界

    1 为什么引入边界值分析法?

    测试实践表明,大量的故障往往发生在输入定义域的边界上,而不是在其内部。因此,针对各种边界情况设计测试用例,通常会取得很好的测试效果。
    例如,一个循环条件为“≤”时,却错写成“<”;计数器发生少计数一次。

    2.怎么用边界值分析法设计测试用例

    ( 1)首先确定边界情况
    通常边界就是应该着重测试的边界情况。
    (2)选取正好等于、刚刚大于或刚刚小于边界的值作为测试数据,
    而不是选取等价类中的典型值或任意值

    二、常见的边界值

    • 对16-bit 的整数而言 32767 和 -32768 是边界
    • 屏幕上光标在最左上、最右下位置
    • 报表的第一行和最后一行
    • 数组元素的第一个和最后一个
    • 循环的第 0 次、第 1 次和倒数第 2 次、最后一次

    三、边界值分析法设计测试用例

     

    假设有两个变量x和y的程序F,x、y在下列范围内取值:
    a≤x≤b,c≤y≤d。区间[a,b]和[c,d]是x、y的值域,程序F的输入定义域如图所示,那么带阴影
    矩形中的任何点都是程序F的有效输入。

    四、标准型(一般性)测试

    对于一个含有n个变量的程序,保留其中一个变量,让其余的变量取正常值,被保留的变量依次取min、min+、nom、max-、max值,对每个变量都重复进行。这样,对于一个有n个变量的程序,边界值分析测试程序会产生4n+1个测试用例。边界值分析法是基于可靠性理论中称为“单故障”的假设,即有两个或两个以上故障同时出现而导致软件失效的情况很少,也就是说,软件失效基本上是由单故障引起的。

    五、健壮性测试

    • 健壮性测试是边界值分析测试的一种扩展,除了取边界值外,还需要考虑采用一个略超过最大值(max+)及略小于最小值(min-)的取值,检查超过极限值时系统的情况
    • 对于一个含有n个变量的程序,保留其中一个变量,让其余的变量取正常值,被保留的变量依次取min、min+、min-,nom、max-、max, max+值,对每个变量都重复进行。这样,对于一个有n个变量的程序,边界值分析测试程序会产生6n+1个测试用例

    展开全文
  • 头文件只是用来声明的,不参与编译,#include “1.h” 只是把1.h里的代码给复制到这个源文件里来,建议还是好好...1)不管变量还是函数先声明 或者直接定义才能使用,声明能声明n次,同一个作用域里面 定义只能定义...

    c++ 头文件的使用:https://blog.csdn.net/weixin_42018112/article/details/82357002

    头文件只是用来声明的,不参与编译,#include “1.h”  只是把1.h里的代码给复制到这个源文件里来,建议还是好好看看上面这个

    明确几个点:

    1)不管变量还是函数先声明 或者直接定义才能使用,声明能声明n次,同一个作用域里面 定义只能定义一次

    2) 根据C++标准的规定,一个变量声明必须同时满足两个条件,否则就是定义:  
     (1)声明必须使用extern关键字;(2)不能给变量赋初值    
     extern  int  a;  //声明 

     int  a;   //定义

     int  a  =  0; //定义

     extern  int  a  =0;   //定义

    3)一个全局变量的作用域默认是整个程序, 加了static 或者加了 const 则是这个源文件

    4)如果在多个源文件 包含同一个名字的 全局变量的 定义,就会引起重定义

     因此 要想在多个文件共用一个全局变量,我们只需在一个头文件里 声明(注意是声明)这个变量 : extern int i;

    然后在 其中一个源文件 只能是一个(通常就是头文件的同名源文件)里面 定义这个变量   int i =1;

    注意不能用 i =1;  要用 int i =1;

    最后在要使用这个变量的源文件里面  #include 头文件就行了

    但是 const 或者 static 的全局变量 你在头文件里定义就没啥错,因为 它的作用域只是当前文件,也就是包含了这个头文件的这个源文件里面,就是内部链接,所以const的全局变量通常放在头文件内

    所以如果在一个 头文件:

    int i =1;

    const int j = 2;

    static int n =3;

    然后在两个源文件都include了这个头文件,i是错的,重定义了,j和n没错

    例子:

    头文件:state.h   源文件:state.cpp       

     其它源文件:t1.cpp  t2.cpp  t3.cpp, 这些源文件都包含头文件state.h。

    需要定义一个全局变量供这些源文件中使用:方法如下

    1、在 state.h声明全局变量: extern int a;

    2、在state.cpp中定义该全局变量:int a =10;

    这样其它源文件就可以使用该变量啦

     

     

     

    C++编译模式

    通常,在一个C++程序中,只包含两类文件——.cpp文件和.h文件。其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码;而.h文件则被称作C++头文件,里面放的也是C++的源代码。

    C++支持“分别编译”(separate compilation)。也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里。.cpp文件里的东西都是相对独立的,在编译(compile)时不需要与其他文件互通,只需要在编译成目标文件后再与其他的目标文件做一次链接(link)就行了。比如,在文件a.cpp中定义了一个全局函数“void a() {}”,而在文件b.cpp中需要调用这个函数。即使这样,文件a.cpp和文件b.cpp并不需要相互知道对方的存在,而是可以分别地对它们进行编译,编译成目标文件之后再链接,整个程序就可以运行了。

    这是怎么实现的呢? 
    在文件b.cpp中,在调用“void a()”函数之前,先声明一下这个函数“void a();”,就可以了。这是因为编译器在编译b.cpp的时候会生成一个符号表(symbol table),像“void a()”这样的看不到定义的符号,就会被存放在这个表中。再进行链接的时候,编译器就会在别的目标文件中去寻找这个符号的定义。一旦找到了,程序也就可以顺利地生成了。

    注意这里提到了两个概念,一个是“定义”,一个是“声明”。简单地说,“定义”就是把一个符号完完整整地描述出来:它是变量还是函数,返回什么类型,需要什么参数等等。而“声明”则只是声明这个符号的存在,即告诉编译器,这个符号是在其他文件中定义的,我这里先用着,你链接的时候再到别的地方去找找看它到底是什么吧。定义的时候要按C++语法完整地定义一个符号(变量或者函数),而声明的时候就只需要写出这个符号的原型了。需要注意的是,一个符号,在整个程序中可以被声明多次,但却要且仅要被定义一次。试想,如果一个符号出现了两种不同的定义,编译器该听谁的?

    这种机制给C++程序员们带来了很多好处,同时也引出了一种编写程序的方法。考虑一下,如果有一个很常用的函数“void f() {}”,在整个程序中的许多.cpp文件中都会被调用,那么,我们就只需要在一个文件中定义这个函数,而在其他的文件中声明这个函数就可以了。一个函数还好对付,声明起来也就一句话。但是,如果函数多了,比如是一大堆的数学函数,有好几百个,那怎么办?能保证每个程序员都可以完完全全地把所有函数的形式都 准确地记下来并写出来吗?

    什么是头文件

    很显然,答案是不可能。但是有一个很简单地办法,可以帮助程序员们省去记住那么多函数原型的麻烦:我们可以把那几百个函数的声明语句全都先写好,放在一个文件里,等到程序员需要它们的时候,就把这些东西全部copy进他的源代码中。

    这个方法固然可行,但还是太麻烦,而且还显得很笨拙。于是,头文件便可以发挥它的作用了。所谓的头文件,其实它的内容跟.cpp文件中的内容是一样的,都是C++的源代码。但头文件不用被编译。我们把所有的函数声明全部放进一个头文件中,当某一个.cpp源文件需要它们时,它们就可以通过一个宏命令 “#include”包含进这个.cpp文件中,从而把它们的内容合并到.cpp文件中去。当.cpp文件被编译时,这些被包含进去的.h文件的作用便发挥了。

    举一个例子吧,假设所有的数学函数只有两个:f1和f2,那么我们把它们的定义放在math.cpp里:

    并把“这些”函数的声明放在一个头文件math.h中:

    在另一个文件main.cpp中,我要调用这两个函数,那么就只需要把头文件包含进来:

    这样,便是一个完整的程序了。需要注意的是,.h文件不用写在编译器的命令之后,但它必须要在编译器找得到的地方(比如跟main.cpp在一个目录下)。 main.cpp和math.cpp都可以分别通过编译,生成main.o和math.o,然后再把这两个目标文件进行链接,程序就可以运行了。

    include

    include 是一个来自C语言的宏命令,它在编译器进行编译之前,即在预编译的时候就会起作用。#include的作用是把它后面所写的那个文件的内容,完完整整地、 一字不改地包含到当前的文件中来。值得一提的是,它本身是没有其它任何作用与副功能的,它的作用就是把每一个它出现的地方,替换成它后面所写的那个文件的 内容。简单的文本替换,别无其他。因此,main.cpp文件中的第一句(#include “math.h”),在编译之前就会被替换成math.h文件的内容。即在编译过程将要开始的时候,main.cpp的内容已经发生了改变:

    不多不少,刚刚好。同理可知,如果我们除了main.cpp以外,还有其他的很多.cpp文件也用到了f1和f2函数的话,那么它们也通通只需要在使用这两个函数前写上一句#include “math.h”就行了。

    头文件中应该写什么

    通 过上面的讨论,我们可以了解到,头文件的作用就是被其他的.cpp包含进去的。它们本身并不参与编译,但实际上,它们的内容却在多个.cpp文件中得到了 编译。通过“定义只能有一次”的规则,我们很容易可以得出,头文件中应该只放变量和函数的声明,而不能放它们的定义。因为一个头文件的内容实际上是会被引入到多个不同的.cpp文件中的,并且它们都会被编译。放声明当然没事,如果放了定义,那么也就相当于在多个文件中出现了对于一个符号(变量或函数)的定 义,纵然这些定义都是相同的,但对于编译器来说,这样做不合法。

    所以,应该记住的一点就是,.h头文件中,只能存在变量或者函数的声明, 而不要放定义。即,只能在头文件中写形如:extern int a;和void f();的句子。这些才是声明。如果写上int a;或者void f() {}这样的句子,那么一旦这个头文件被两个或两个以上的.cpp文件包含的话,编译器会立马报错。(关于extern,前面有讨论过,这里不再讨论定义跟 声明的区别了。)

    但是,这个规则是有三个例外的。

    一,头文件中可以写const对象的定义。因为全局的const对象默 认是没有extern的声明的,所以它只在当前文件中有效。把这样的对象写进头文件中,即使它被包含到其他多个.cpp文件中,这个对象也都只在包含它的 那个文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。同时,因为这些.cpp文件中的该对象都是从一个头文件中包含进去的,这样也就保证 了这些.cpp文件中的这个const对象的值是相同的,可谓一举两得。同理,static对象的定义也可以放进头文件。

    二,头文件中可 以写内联函数(inline)的定义。因为inline函数是需要编译器在遇到它的地方根据它的定义把它内联展开的,而并非是普通函数那样可以先声明再链 接的(内联函数不会链接),所以编译器就需要在编译时看到内联函数的完整定义才行。如果内联函数像普通函数一样只能定义一次的话,这事儿就难办了。因为在 一个文件中还好,我可以把内联函数的定义写在最开始,这样可以保证后面使用的时候都可以见到定义;但是,如果我在其他的文件中还使用到了这个函数那怎么办 呢?这几乎没什么太好的解决办法,因此C++规定,内联函数可以在程序中定义多次,只要内联函数在一个.cpp文件中只出现一次,并且在所有的.cpp文 件中,这个内联函数的定义是一样的,就能通过编译。那么显然,把内联函数的定义放进一个头文件中是非常明智的做法。

    三,头文件中可以写类(class)的定义。因为在程序中创建一个类的对象时,编译器只有在这个类的定义完全可见的情况下,才能知道这个类的对象应该如何布局,所以,关于类的 定义的要求,跟内联函数是基本一样的。所以把类的定义放进头文件,在使用到这个类的.cpp文件中去包含这个头文件,是一个很好的做法。在这里,值得一提 的是,类的定义中包含着数据成员和函数成员。数据成员是要等到具体的对象被创建时才会被定义(分配空间),但函数成员却是需要在一开始就被定义的,这也就 是我们通常所说的类的实现。一般,我们的做法是,把类的定义放在头文件中,而把函数成员的实现代码放在一个.cpp文件中。这是可以的,也是很好的办法。 不过,还有另一种办法。那就是直接把函数成员的实现代码也写进类定义里面。在C++的类中,如果函数成员在类的定义体中被定义,那么编译器会视这个函数为 内联的。因此,把函数成员的定义写进类定义体,一起放进头文件中,是合法的。注意一下,如果把函数成员的定义写在类定义的头文件中,而没有写进类定义中, 这是不合法的,因为这个函数成员此时就不是内联的了。一旦头文件被两个或两个以上的.cpp文件包含,这个函数成员就被重定义了。

    头文件中的保护措施

    考虑一下,如果头文件中只包含声明语句的话,它被同一个.cpp文件包含再多次都没问题——因为声明语句的出现是不受限制的。然而,上面讨论到的头文件中的 三个例外也是头文件很常用的一个用处。那么,一旦一个头文件中出现了上面三个例外中的任何一个,它再被一个.cpp包含多次的话,问题就大了。因为这三个 例外中的语法元素虽然“可以定义在多个源文件中”,但是“在一个源文件中只能出现一次”。设想一下,如果a.h中含有类A的定义,b.h中含有类B的定义,由于类B的定义依赖了类A,所以b.h中也#include了a.h。现在有一个源文件,它同时用到了类A和类B,于是程序员在这个源文件中既把 a.h包含进来了,也把b.h包含进来了。这时,问题就来了:类A的定义在这个源文件中出现了两次!于是整个程序就不能通过编译了。你也许会认为这是程序 员的失误——他应该知道b.h包含了a.h——但事实上他不应该知道。

    使用”#define”配合条件编译可以很好地解决这个问题。在一 个头文件中,通过#define定义一个名字,并且通过条件编译#ifndef…#endif使得编译器可以根据这个名字是否被定义,再决定要不要继 续编译该头文中后续的内容。这个方法虽然简单,但是写头文件时一定记得写进去。

    头文件如何来关联源文件?

    这个问题实际上是说,已知头文件“a.h”声明了一系列函数(仅有函数原型,没有函数实现),“b.cpp”中实现了这些函数,那么如果我想在“c.cpp”中使用“a.h”中声明的这些在“b.cpp”中实现的函数,通常都是在“c.cpp”中使用#include “a.h”,那么c.cpp是怎样找到b.cpp中的实现呢?

    其实.cpp和.h文件名称没有任何直接关系,很多编译器都可以接受其他扩展名。 
    谭浩强老师的《C程序设计》一书中提到,编译器预处理时,要对#include命令进行“文件包含处理”:将headfile.h的全部内容复制到#include “headfile.h”处。 
    这也正说明了,为什么很多编译器并不care到底这个文件的后缀名是什么—-因为#include预处理就是完成了一个“复制并插入代码”的工作。

    程序编译的时候,并不会去找b.cpp文件中的函数实现,只有在link的时候才进行这个工作。我们在b.cpp或c.cpp中用#include “a.h”实际上是引入相关声明,使得编译可以通过,程序并不关心实现是在哪里,是怎么实现的。源文件编译后成生了目标文件(.o或.obj文件),目标文件中,这些函数和变量就视作一个个符号。在link的时候,需要在makefile里面说明需要连接哪个.o或.obj文件(在这里是b.cpp生成的.o或.obj文件),此时,连接器会去这个.o或.obj文件中找在b.cpp中实现的函数,再把他们build到makefile中指定的那个可以执行文件中。

    在VC中,一帮情况下不需要自己写makefile,只需要将需要的文件都包括在project中,VC会自动帮你把makefile写好。
    通常,编译器会在每个.o或.obj文件中都去找一下所需要的符号,而不是只在某个文件中找或者说找到一个就不找了。因此,如果在几个不同文件中实现了同一个函数,或者定义了同一个全局变量,链接的时候就会提示“redefined”.

     

    展开全文
  • 例子: 头文件:state.h 源文件:state.cpp 其它源文件:t1.cpp t2.cpp t3.cpp, 这些源文件都包含头文件state.h。...需要定义一个全局变量供这些源文件中使用:方法如下 1、在 state.h声明全局变量: extern ...

    转载地址:https://www.cnblogs.com/invisible2/p/6905892.html

    例子:

    头文件:state.h 源文件:state.cpp

    其它源文件:t1.cpp t2.cpp t3.cpp, 这些源文件都包含头文件state.h。

    需要定义一个全局变量供这些源文件中使用:方法如下

    1、在 state.h声明全局变量: extern inta;

    2、在state.cpp中定义该全局变量:int a =10;

    这样其它源文件就可以使用该变量啦

    这里需要的是“声明”,不是“定义”!根据C++标准的规定,一个变量声明必须同时满足两个条件,否则就是定义:
    (1)声明必须使用extern关键字;(2)不能给变量赋初值
    extern int a; //声明

    int a; //定义

    int a = 0; //定义

    extern int a =0; //定义

    头文件中应使用extern关键字声明全局变量(不定义),如果这个变量有多个文件用到,可以新建一个cpp,在其中定义,把这个cpp加入工程即可。头文件请不要定义任何变量,那是非常业余的行为……

    一般在头文件中申明,用extern,在cpp中定义。 如果在头文件中定义,如果这个头文件被多个cpp引用,会造成重复定义的链接错误。
    
    头文件只能申明全局变量(extern),不可定义(不推荐使用)    .cpp里,在最外层定义即可(int gi),直接引用
    

    如果在.cpp里使用static定义,则该变量只在当前cpp文件中有效,在别的文件中无效
    在.h里使用static定义,不会进行编译(.h文件不编译),只会在其每个include的cpp文件中包含编译,相当于在.cpp里使用static定义。

    转载:http://www.cnblogs.com/yyxt/p/3891712.html

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。

      也就是说extern有两个作用,第一个,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的,这要看编译器的"脾气"了(不同的编译器采用的方法不一样),为什么这么做呢,因为C++支持函数的重载啊,在这里不去过多的论述这个问题,如果你有兴趣可以去网上搜索,相信你可以得到满意的解释!(C++ 和 C 采用的名称修饰规则不同)
    第二,当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。
    

    2 问题:extern 变量
      在一个源文件里定义了一个数组:char a[6];
      在另外一个文件里用下列语句进行了声明:extern char *a;
      请问,这样可以吗?
      答案与分析:
      1)、不可以,程序运行时会告诉你非法访问。原因在于,指向类型T的指针并不等价于类型T的数组。extern char *a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]。
      2)、例子分析如下,如果a[] = “abcd”,则外部变量a=0x61626364 (abcd的ASCII码值),*a显然没有意义
      显然a指向的空间(0x61626364)没有意义,易出现非法内存访问。
      3)、这提示我们,在使用extern时候要严格对应声明时的格式,在实际编程中,这样的错误屡见不鲜。
      4)、extern用在变量声明中常常有这样一个作用,你在.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在.h中并用extern来声明。

    3 问题:单方面修改extern 函数原型
      当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的extern申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会照成系统错误,这种情况应该如何解决?
      答案与分析:
      目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明(extern),然后调用方include该头文件,从而省去extern这一步。以避免这种错误。
      宝剑有双锋,对extern的应用,不同的场合应该选择不同的做法。

    4 问题:extern “C”
      在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,应该如何解决这种情况呢?

      答案与分析:
      C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
      下面是一个标准的写法:
      

    //在.h文件的头上
    #ifdef __cplusplus
    #if __cplusplus
    extern "C"{
     #endif
     #endif /* __cplusplus */ 
     …
     …
     //.h文件结束的地方
     #ifdef __cplusplus
     #if __cplusplus
    }
    #endif
    #endif /* __cplusplus */ 

    5 问题:extern 函数声明
      常常见extern放在函数的前面成为函数声明的一部分,那么,C语言的关键字extern在函数的声明中起什么作用?
      答案与分析:
      如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有明显的区别:
      

    extern int f(); 
    
    int f();

    当然,这样的用处还是有的,就是在程序中取代include “*.h”来声明函数,在一些复杂的项目中,我比较习惯在所有的函数声明前添加extern修饰。关于这样做的原因和利弊可见下面的这个例子:“用extern修饰的全局变量”

    (1) 在test1.h中有下列声明:
    
        #ifndef TEST1H
        #define TEST1H
        extern char g_str[]; // 声明全局变量g_str
        void fun1();
        #endif

    (2) 在test1.cpp中

    #include "test1.h"
            char g_str[] = "123456"; // 定义全局变量g_str
            void fun1() { cout << g_str << endl; }

    (3) 以上是test1模块, 它的编译和连接都可以通过,如果我们还有test2模块也想使用g_str,只需要在原文件中引用就可以了

    #include "test1.h"
    
    void fun2()    { cout << g_str << endl;    }

    以上test1和test2可以同时编译连接通过,如果你感兴趣的话可以用ultraEdit打开test1.obj,你可以在里面找到”123456”这个字符串,但是你却不能在test2.obj里面找到,这是因为g_str是整个工程的全局变量,在内存中只存在一份,test2.obj这个编译单元不需要再有一份了,不然会在连接时报告重复定义这个错误!

    注意:如果使用到sizeof,声明数组需要指定大小 extern char g_str[7]; 因为test2模块中只是声明了一个数组,但具体多大,并不知道。若没有在.h文件中声明数组大小,会报“非法的sizeof操作数”的错误。
    (4) 有些人喜欢把全局变量的声明和定义放在一起,这样可以防止忘记了定义,如把上面test1.h改为

    extern char g_str[] = "123456"; // 这个时候相当于没有extern

    然后把test1.cpp中的g_str的定义去掉,这个时候再编译连接test1和test2两个模块时,会报连接错误,这是因为你把全局变量g_str的定义放在了头文件之后,test1.cpp这个模块包含了test1.h所以定义了一次g_str,而test2.cpp也包含了test1.h所以再一次定义了g_str,这个时候连接器在连接test1和test2时发现两个g_str。如果你非要把g_str的定义放在test1.h中的话,那么就把test2的代码中#include “test1.h”去掉 换成:

    extern char g_str[];  // 没有include “test1.h”
    void fun2()   {  cout << g_str << endl;   }

    这个时候编译器就知道g_str是引自于外部的一个编译模块了,不会在本模块中再重复定义一个出来,但是我想说这样做非常糟糕,因为你由于无法在test2.cpp中使用#include “test1.h”,那么test1.h中声明的其他函数你也无法使用了,除非也用都用extern修饰,这样的话你光声明的函数就要一大串,而且头文件的作用就是要给外部提供接口使用的,所以 请记住, 只在头文件中做声明,真理总是这么简单。

    1. extern 和 static

      (1) extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量.
      (2) static 表示静态的变量,分配内存的时候, 存储在静态区,不存储在栈上面.

      static 作用范围是内部连接的关系, 和extern有点相反.它和对象本身是分开存储的,extern也是分开存储的,但是extern可以被其他的对象用extern 引用,而static 不可以,只允许对象本身用它. 具体差别首先,static与extern是一对“水火不容”的家伙,也就是说extern和static不能同时修饰一个变量;其次,static修饰的全局变量声明与定义同时进行,也就是说当你在头文件中使用static声明了全局变量(类外部)后(如果在头文件的class内部声明static变量,那么其定义式通常位于实现(.cpp)文件中,例外的,只有const int类型可以in class 初值设定),它也同时被定义了;最后,static修饰全局变量的作用域只能是本身的编译单元(内部链接,参见 存储持续性、作用域和链接性),也就是说它的“全局”只对本编译单元有效,其他编译单元则看不到它,如:
      (1) test1.h:

    #ifndef TEST1H
    #define TEST1H
    static char g_str[] = "123456"; 
    void fun1();
    #endif

    (2) test1.cpp:

    #include "test1.h"
    void fun1()  {   cout << g_str << endl;  }

    (3) test2.cpp

    #include "test1.h"
    void fun2()  {   cout << g_str << endl;  }

    以上两个编译单元可以连接成功, 当你打开test1.obj时,你可以在它里面找到字符串”123456”,同时你也可以在test2.obj中找到它们,它们之所以可以连接成功而没有报重复定义的错误是因为虽然它们有相同的内容,但是存储的物理地址并不一样,就像是两个不同变量赋了相同的值一样,而这两个变量分别作用于它们各自的编译单元。 也许你比较较真,自己偷偷的跟踪调试上面的代码,结果你发现两个编译单元(test1,test2)的g_str的内存地址相同,于是你下结论static修饰的变量也可以作用于其他模块,但是我要告诉你,那是你的编译器在欺骗你,大多数编译器都对代码都有优化功能,以达到生成的目标程序更节省内存,执行效率更高,当编译器在连接各个编译单元的时候,它会把相同内容的内存只拷贝一份,比如上面的”123456”, 位于两个编译单元中的变量都是同样的内容,那么在连接的时候它在内存中就只会存在一份了,如果你把上面的代码改成下面的样子,你马上就可以拆穿编译器的谎言:
    (1) test1.cpp:

    #include "test1.h"
    void fun1()
    {
       g_str[0] = ''a'';
       cout << g_str << endl;
    }

    (2) test2.cpp

    #include "test1.h"
    void fun2()  {  cout << g_str << endl;  }

    (3)

    void main()     {
            fun1(); // a23456
            fun2(); // 123456
        }

    这个时候你在跟踪代码时,就会发现两个编译单元中的g_str地址并不相同,因为你在一处修改了它,所以编译器被强行的恢复内存的原貌,在内存中存在了两份拷贝给两个模块中的变量使用。正是因为static有以上的特性,所以一般定义static全局变量时,都把它放在原文件中而不是头文件,这样就不会给其他模块造成不必要的信息污染,同样记住这个原则吧!

    1. extern 和const

      C++中const修饰的全局常量据有跟static相同的特性,即它们只能作用于本编译模块中,但是const可以与extern连用来声明该常量可以作用于其他编译模块中, 如extern const char g_str[];
      然后在原文件中别忘了定义: const char g_str[] = “123456”;

      所以当const单独使用时它就与static相同,而当与extern一起合作的时候,它的特性就跟extern的一样了!所以对const我没有什么可以过多的描述,我只是想提醒你,const char* g_str = “123456” 与 const char g_str[] =”123465”是不同的, 前面那个const 修饰的是char 而不是g_str,它的g_str并不是常量,它被看做是一个定义了的全局变量(可以被其他编译单元使用), 所以如果你像让char*g_str遵守const的全局常量的规则,最好这么定义const char const g_str=”123456”.

    【转】http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777431.html

    /***************************************************************/

    extern 用法,全局变量与头文件(重复定义)
    用#include 可以包含其他头文件中变量、函数的声明,为什么还要extern关键字,如果我想引用一个全局变量或函数a,我只要直接在源文件中包含#include

    include”xxx.txt”

    编译,链接都很顺利的过去了,由此可知,头文件仅仅为阅读代码作用,没其他的作用了!

    不管是C还是C++,你把你的函数,变量或者结构体,类啥的放在你的.c或者.cpp文件里。然后编译成lib,dll,obj,.o等等,然后别人用的时候最基本的gcc hisfile.cpp yourfile.o|obj|dll|lib 等等。
    但对于我们程序员而言,他们怎么知道你的lib,dll…里面到底有什么东西?要看你的头文件。你的头文件就是对用户的说明。函数,参数,各种各样的接口的说明。
    那既然是说明,那么头文件里面放的自然就是关于函数,变量,类的“声明”了。记着,是“声明”,不是“定义”。
    那么,我假设大家知道声明和定义的区别。所以,最好不要傻嘻嘻的在头文件里定义什么东西。比如全局变量:

    ifndef XX头文件.H

    define XX头文件.H

    int A;

    endif

    那么,很糟糕的是,这里的int A是个全局变量的定义,所以如果这个头文件被多次引用的话,你的A会被重复定义.
    显 然语法上错了。只不过有了这个#ifndef的条件编译,所以能保证你的头文件只被引用一次,不过也许还是会岔子,但若多个c文件包含这个头文件时还是会 出错的,因为宏名有效范围仅限于本c源文件,所以在这多个c文件编译时是不会出错的,但在链接时就会报错,说你多处定义了同一个变量,

    Linking…
    incl2.obj : error LNK2005: “int glb” (?glb@@3HA) already defined in incl1.obj
    Debug/incl.exe : fatal error LNK1169: one or more multiply defined symbols found
    注意!!!

    extern

    这个关键字真的比较可恶,在声明的时候,这个extern居然可以被省略,所以会让你搞不清楚到底是声明还是定义,下面分变量和函数两类来说:

    (1)变量

    尤其是对于变量来说。

    extern int a;//声明一个全局变量a
    int a; //定义一个全局变量a
    extern int a =0 ;//定义一个全局变量a 并给初值。
    int a =0;//定义一个全局变量a,并给初值,
    第四个 等于 第 三个,都是定义一个可以被外部使用的全局变量,并给初值。
    糊涂了吧,他们看上去可真像。但是定义只能出现在一处。也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。

    当你要引用一个全局变量的时候,你就要声明,extern int a;这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。

    (2)函数
    对于函数也一样,也是定义和声明,定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。 但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体,所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行。两者如此不同,所以省略了extern也不会有问题。
    比如:
    int fun(void)
    {
    return 0;
    }
    很好,我们定义了一个全局函数

    int fun(void);
    我们对它做了个声明,然后后面就可以用了, 加不加extern都一样.
    我们也可以把对fun的声明 放在一个头文件里,最后变成这样

    int fun(void);//函数声明,所以省略了extern,完整些是extern int fun(void);
    int fun(void)
    {
      return 0;
    }//一个完整的全局函数定义,因为有函数体,extern同样被省略了。
    然后,一个客户,一个要使用你的fun的客户,把这个头文件包含进去,ok,一个全局的声明。没有问题。
    但是,对应的,如果是这个客户要使用全局变量,那么要extern 某某变量;不然就成了定义了。

    总结下:

    对变量而言,如果你想在本源文件中使用另一个源文件的变量,就需要在使用前用extern声明该变量,或者在头文件中用extern声明该变量;

    对函数而言,如果你想在本源文件中使用另一个源文件的函数,就需要在使用前用声明该变量,声明函数加不加extern都没关系,所以在头文件中函数可以不用加extern。

    C程序采用模块化的编程思想,需合理地将一个很大的软件划分为一系列功能独立的部分合作完成系统的需求,在模块的划分上主要依据功能。模块由头文件和实现文件组成,对头文件和实现文件的正确使用方法是:
    规则1 头文件(.h)中是对于该模块接口的声明,接口包括该模块提供给其它模块调用的外部函数及外部全局变量,对这些变量和函数都需在.h中文件中冠以extern关键字声明;
    规则2 模块内的函数和全局变量需在.c文件开头冠以static关键字声明;
    规则3 永远不要在.h文件中定义变量;
    许多程序员对定义变量和声明变量混淆不清,定义变量和声明变量的区别在于定义会产生内存分配的操作,是汇编阶段的概念;而声明则只是告诉包含该声明的模块在连接阶段从其它模块寻找外部函数和变量。如:
    int a = 5;

    include “module1.h”

    include “module1.h”

    include “module1.h”

    以上程序的结果是在模块1、2、3中都定义了整型变量a,a在不同的模块中对应不同的地址单元,这明显不符合编写者的本意。正确的做法是:
    extern int a;

    include “module1.h”

    int a = 5;

    include “module1.h”

    include “module1.h”  

    这样如果模块1、2、3操作a的话,对应的是同一片内存单元。

    规则4 如果要用其它模块定义的变量和函数,直接包含其头文件即可。
    许多程序员喜欢这样做,当他们要访问其它模块定义的变量时,他们在本模块文件开头添加这样的语句:
    extern int externVar; 
    抛弃这种做法吧,只要头文件按规则1完成,某模块要访问其它模块中定义的全局变量时,只要包含该模块的头文件即可。

    共享变量声明
    就像在函数间共享变量的方式一样,变量可以在文件中共享。为了共享函数,要把函数的定义放在一个源文件中,然后在需要调用此函数的其他文件中放置声明。共享变量的方法和此方式非常类似。
    在此之前,不需要区别变量的声明和它的定义。为了声明变量i,写成如下形式:
    int i;
    这样不仅声明i是int型的变量,而且也对i进行了定义,从而使编译器为i留出了空间。为了声明没有定义的变量i,需要在变量声明的开始处放置关键字extern:
    extern int i;
    extern提示编译器变量i是在程序中的其他位置定义的(大多数可能是在不同的源文件中),因此不需要为i分配空间。
    顺便说一句,extern可以用于所有类型的变量。在数组的声明中使用extern时,可以忽略数组的长度:
    extern int a[];
    因为此刻编译器不用为数组a分配空间,所以也就不需要知道数组a的长度了。
    为了在几个源文件中共享变量i,首先把变量i的定义放置在一个文件中:
    int i;
    如果需要对变量i初始化,那么可以在这里放初始值。在编译这个文件时,编译器将会为变量i分配内存空间,而其他文件将包含变量i的声明:
    extern int i;
    通过在每个文件中声明变量i,使得在这些文件中可以访问/或修改变量i。然而,由于关键字extern,使得编译器不会在每次编译其中某个文件时为变量i分配额外的内存空间。
    当在文件中共享变量时,会面临和共享函数时相似的挑战:确保变量的所有声明和变量的定义一致。
    为了避免矛盾,通常把共享变量的声明放置在头文件中。需要访问特殊变量的源文件可以稍后包含适当的头文件。此外,含有变量定义的源文件包含每一个含有变量声明的头文件,这样使编译器可以检查两者是否匹配。

    如果工程很大,头文件很多,而有几个头文件又是经常要用的,那么
    1。把这些头文件全部写到一个头文件里面去,比如写到preh.h
    2。写一个preh.c,里面只一句话:#include “preh.h”
    3。对于preh.c,在project setting里面设置creat precompiled headers,对于其他c文件,设置use precompiled header file

    展开全文
  • 距离上一篇文章的发布有一个多月了。现在接上,来分享一些MATLAB软件的内容,同时自己也来更加深入地学习这个软件。01前言网上的学习视频很多了,我就从matlab官网的文档(2019a版)入手,对某些点进行选择性的介绍。...
  • 功能测试技术--边界值分析法

    千次阅读 2020-04-28 16:33:20
    一、边界值分析法的概念 边界值分析法就是对输入的边界值进行测试的一种黑盒测试方法。通常边界值分析法是作为对等价类划分法的补充,这种情况下,其...例如,一个循环条件“≤”时,却错写成“<”;计算器发生...
  • 用C语言编写程序,输入一个正整数n(1#include"stdio.h"intmain(){\x09inti,j,n;\x09inta[12];\x09intmin,mx;\x09scanf("%d",&n);\x09for(i=0;ic语言输出所有三位数中各个位数的立方等于这个三位数的数#include...
  • 【汇编语言】 变量

    千次阅读 多人点赞 2021-03-29 08:49:48
    变量的概念 二、变量的定义 (1)变量名 (2)变量定义伪指令 1.助记符:BYTE 2.助记符:WORD 3.助记符:DWORD (3)初值表 三、多字节数据的存储顺序 (1)字节编址的主存储器 (2)数据的存储顺序 (3)小端存储和大端存储...
  • 展开全部public class Student {//1、定义成员变量private String no;//学号private String name;//姓名private String sex;//性别private String age;//年龄private float score;//成绩//2、通过构造方法初始化成...
  • MATLAB使用变量和数组

    千次阅读 2021-04-18 04:10:06
    本文概述在任何MATLAB程序中, 数据的结构单位都是数组。数组是记录值的集合, 这些记录值被组织成行和列, 并且以单个名称已知。数组可以分配为向量或矩阵。术语”向量”通常用于定义仅具有维的数组, 而术语”矩阵”...
  • java声明变量

    千次阅读 2022-03-01 15:23:26
    1.关键字 ...不能使用关键字作为变量名或方法名 2. 标识符 就是给类,接口,方法,变量等起名字的字符序列。用来查找、定位、标明、唯一确认内容。 ·表示类名的标识符用大写字母开始。如: Man , ..
  • 1.shell中变量的定义和使用 你可在任何编程语言中使用变量,但是在脚本编程(shell)中它们是没有类型的,简称弱类型编程语言,在这个变量中可以保含一个数字,一个字符串,一个单词等。你并不需要声明这个变量,它会...
  • N个数的最大公约数和最小公倍数以及Hankson"逆问题"(python) 、题目要求 1.基本要求: 求N个数的最大公约数和最小公倍数。用C或C++或java或python语言实现程序解决问题 2.提高要求: 已知正整数a0,a1,b0,b1,...
  • CUDA C/C++ 教程:加速应用程序

    千次阅读 多人点赞 2022-02-19 20:45:51
    编写一个Hello GPU核函数5. CUDA线程的层次结构5.1. 启动可并行运行的核函数6. CUDA提供的线程层次结构变量6.1. 线程和块的索引6.2. 加速for循环6.3. 协调并行线程7. 分配将要在GPU和CPU上访问的内存 1. CUDA简介 ...
  • 一个c程序

    万次阅读 2018-05-23 19:19:29
    认识第一个C语言程序: #inlcude &lt;stdio.h&gt; #include &lt;stdlib.h&gt; int main() { printf("hehe\n");//printf用于在标准输出下打印信息 } 一、在写程序的过程中我们通常需要...
  • 例题:编写一个程序用于创建一格结构BOOK,用来储存书的信息:书名,作者姓名,页数和价格,接受输入和输出 。 代码如下: #include <stdio.h> #include <string.h> /*自定BOOK结构*/ struct book { ...
  • 【C语言程序设计】~求两整数之和

    千次阅读 2021-02-01 22:56:23
    求两整数之和 ... //本行是程序的声明部分,定义a,b,sum为整形变量 a=345; //将数值赋值给a b=678; sum=a+b; //将a,b的运算结果赋值给变量sun printf("sum is %d\n",sum); //输出结果 return 0;
  • 算法分析: 1、以字符串“abcabcd”为例,最长不重复子串是后四位“abcd”; 算法实际上跟冒泡法排序类似: ...需要从第n位开始遍历第0-(n-1)位字符串,均不同则记录长度,例如:d与abc比较(前面的abc三位已经...
  • 本文将介绍我曾经做过的一个项目的服务器架构和服务器编程的一些重要细节。 一、程序运行环境 ...该程序总共有17个线程,其中分为9个数据库工作线程D和一个日志线程L,6个普通工作线程W,一个主线程M。(以
  • Java 习题4 答案及解析

    千次阅读 2021-03-11 12:47:18
    问答题(1)面向对象语言有哪三特性?(2)类名应当遵守怎样的编程风格?(3)变量和方法的名字应当遵守怎样的编程风格?(4)类体内容中声明成员变量是为了体现对象的属性还是行为?(5)类体中定义的非构造方法是为了体现...
  • 【Linux】篇文章搞定环境变量

    千次阅读 多人点赞 2020-11-19 17:54:12
    Linux中环境变量详解
  • 文章目录导航经典单方程计量 经济学模型:专门问题5.1虚拟变量模型、虚拟变量的引入二、虚拟变量的设置原则5.2滞后变量模型、滞后变量模型二、分布滞后模型的参数估计三、自回归模型的参数估计四、格兰杰因果...
  • 怎样判断一个字符是否是一个字母? 字母表中的所有字母(包括计算机键盘上的所有键)都被赋予了一个值,这些字符及其相应的值一起组成了ASCII字符集,该字符集在北美、欧洲和许多讲英语的国家中得到了广泛的使用。 ...
  • matlab全局变量和局部变量和子函数

    千次阅读 2020-05-23 17:09:04
    函数文件中的变量都是局部的,即一个函数文件中定义的变量不能被另一个函数文件或其它 M 文件使用 当函数调用完毕后,该函数文件中定义的所有局部变量都将被释放,即全部被清除 函数通过输入和输出参数与其它 M 文件...
  • 输入1个整数,判断该数是奇数还是偶数.(用C语言编程)#includevoidmain(){intn;printf("输入一个整数:");...}else{printf求解c语言中 输入一个正整数,判断该数是奇数还是偶数.#includevoidmain(){intn;&c语言...
  • 满意答案lwchfqz2018.10.24采纳率:46%等级:6已帮助:157人首先,你的程序由于定义了变量a,又定义了数组a,而此时数组名a不是变量,与前面定义的变量a重复,只要把数组名a改成非a,b,c,maax,min,i,j的其他字母就行啦...
  • 在前面只探讨了单变量/特征的回归模型,然而,在实际生活中,多重因素构成一个含有多个变量的模型,模型中的特征为(????1, ????1, . . . , ????????) eg: 在实际生活中,有卧室的数量,楼层的数量…都会影响房价的 ...
  • 编写程序检查某一个整数中是否有重复的数字,如检 查2822中存在重复数字2 */ #include int main(void) { int n,i; int num[10] = {0}; scanf("%d", &n); do{ num[n%10]++; }while((n = n/10) != 0 ); /...
  • 变量的三种命名方法

    千次阅读 2020-10-31 22:07:03
    比如代码中的变量命名,这属于我们印象中的“小”问题,对于代码量小的程序来说,将变量命名为a、b、aa、string1、string2等类型,并不会影响程序的编写及阅读,如果是代码量大的程序,如果通篇都是字母、*1、*2等...
  • 本节书摘来自华章计算机《Python程序设计》书中的第2章,第2.1节,作者:[美]戴维 I.施奈德(David I. Schneider)著,更多章节内容可以访问云栖社区“华章计算机”公众号查看 第2章 核心对象、变量、输入和输出 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 132,822
精华内容 53,128
热门标签
关键字:

对于一个含有n个变量的程序