精华内容
下载资源
问答
  • C语言函数的定义和声明

    万次阅读 多人点赞 2019-08-08 14:38:17
    本科学C语言的时候,就对函数的定义和声明的作用很迷糊,刚看到一篇博客,写得非常清楚,贴出来与各位共享! 一、函数的声明 1.在C语言中,函数的定义顺序是有讲究的:默认情况下,只有后面定义的函数才可以调用...

    本科学C语言的时候,就对函数的定义和声明的作用很迷糊,刚看到一篇博客,写得非常清楚,贴出来与各位共享!

    一、函数的声明

    1.在C语言中,函数的定义顺序是有讲究的:默认情况下,只有后面定义的函数才可以调用前面定义过的函数

    复制代码

    1 int sum(int a, int b) {
    2     return a + b;
    3 }
    4 
    5 int main()
    6 {
    7     int c = sum(1, 4);
    8     return 0;
    9 }

    复制代码

    第5行定义的main函数调用了第1行的sum函数,这是合法的。如果调换sum函数和main函数的顺序,在标准的C编译器环境下是不合法的(不过在GCC编译器环境下只是一个警告)

     

    2.如果想把函数的定义写在main函数后面,而且main函数能正常调用这些函数,那就必须在main函数的前面进行函数的声明

    复制代码

     1 // 只是做个函数声明,并不用实现
     2 int sum(int a, int b);
     3 
     4 int main()
     5 {
     6     int c = sum(1, 4);
     7     return 0;
     8 }
     9 
    10 // 函数的定义(实现)
    11 int sum(int a, int b) {
    12     return a + b;
    13 }

    复制代码

    在第11行定义了sum函数,在第2行对sum函数进行了声明,然后在第6行(main函数中)就可以正常调用sum函数了。

     

    3.函数的声明格式

    1> 格式

    返回值类型  函数名 (参数1, 参数2, ...)

    只要你在main函数前面声明过一个函数,main函数就知道这个函数的存在,就可以调用这个函数。而且只要知道函数名、函数的返回值、函数接收多少个参数、每个参数是什么类型的,就能够调用这个函数了,因此,声明函数的时候可以省略参数名称。比如上面的sum函数声明可以写成这样:

    int sum(int, int);

    究竟这个函数是做什么用的,还要看函数的定义。

     

    2> 如果只有函数的声明,而没有函数的定义,那么程序将会在链接时出错

    下面的写法是错误的:

    复制代码

    1 int sum(int a, int b);
    2 
    3 int main()
    4 {
    5     
    6     sum(10, 11);
    7 
    8     return 0;
    9 }

    复制代码

    • 在第1行声明了一个sum函数,但是并没有对sum函数进行定义,接着在第6行调用sum函数
    • 这个程序是可以编译成功的,因为我们在main函数前面声明了sum函数(函数的声明和定义是两码事),这个函数声明可以理解为:在语法上,骗一下main函数,告诉它sum函数是存在的,所以从语法的角度上main函数是可以调用sum函数的。究竟这个sum函数存不存在呢,有没有被定义呢?编译器是不管的。在编译阶段,编译器并不检测函数有没有定义,只有在链接的时候才会检测这个函数存不存在,也就是检测函数有没有被定义。
    • 因此,这个程序会在链接的时候报错,错误信息如下:

    • 我这里的源文件是main.c文件,所以编译成功后生成一个main.o文件。链接的时候,链接器会检测main.o中的函数有没有被定义。
    • 上面的错误信息大致意思是:在main.o文件中找不到sum这个标识符。
    • 错误信息中的linker是链接器的意思,下次看到这个linker,说明是链接阶段出错了。链接出错了,就不能生成可执行文件,程序就不能运行。
    • 这个错误的解决方案就是加上sum函数的定义。

     

    二、多源文件开发

    1.为什么要有多个源文件

    1> 在编写第一个c语言程序的时候已经提到:我们编写的所有C语言代码都保存在拓展名为.c的源文件中,编写完毕后就进行编译、链接,最后运行程序。

    2> 在前面的学习过程中,由于代码比较少,因此所有的代码都保存在一个.c源文件中。但是,在实际开发过程中,项目做大了,源代码肯定非常多,很容易就上万行代码了,甚至上十万、百万都有可能。这个时候如果把所有的代码都写到一个.c源文件中,那么这个文件将会非常庞大,也非常恶心,你可以想象一下,一个文件有十几万行文字,不要说调试程序了,连阅读代码都非常困难。

    3> 而且,公司里面都是以团队开发为主,如果多个开发人员同时修改一个源文件,那就会带来很多麻烦的问题,比如张三修改的代码很有可能会抹掉李四之前添加的代码。

    4> 因此,为了模块化开发,一般会将不同的功能写到不同的.c源文件中,这样的话,每个开发人员都负责修改不同的源文件,达到分工合作的目的,能够大大提高开发效率。也就是说,一个正常的C语言项目是由多个.c源文件构成。

     

    2.将sum函数写到其他源文件中

    接下来就演示一下多个源文件的开发,我将前面定义的sum函数写在另一个源文件(命名为sum.c)中。这时候就有两个源文件:

    1> main.c文件

    1 int main()
    2 {
    3 
    4     return 0;
    5 }

    2> sum.c文件

    1 int sum(int a, int b)
    2 {
    3     return a + b;
    4 }

     

    3.在main函数中调用sum函数

    1> 现在想在main函数中调用sum函数,那么你可能会直接这样写:

    复制代码

    1 int main()
    2 {
    3     int c = sum(10, 11);
    4 
    5     return 0;
    6 }

    复制代码

    这种写法在标准C语言编译器中是直接报错的,因为main函数都不知道sum函数的存在,怎么可以调用它呢!!!

    2> 我们应该骗一下main函数,sum函数是存在的,告诉它sum函数的返回值和参数类型即可。也就是说,应该在main函数前面,对sum函数进行声明。

    main.c文件应该写成下面这样

    复制代码

     1 #include <stdio.h>
     2 
     3 int sum(int, int);
     4 
     5 int main()
     6 {
     7     int c = sum(10, 11);
     8     
     9     printf("c is %d\n", c);
    10     
    11     return 0;
    12 }

    复制代码

    注意第3行,加了一个sum函数的声明。为了检验sum函数的调用结果,在第9行用prinf函数将结果输出。

     

    4.编译所有的源文件

    sum.c和main.c都编写完毕后,就可以使用gcc指令进行编译了。同时编译两个文件的指令是:cc -c main.c sum.c

    编译成功后,生成了2个.o目标文件

    也可以单独编译:

    cc -c main.c

    cc -c sum.c

     

    5.链接所有的目标文件

    前面已经编译成功,生成了main.o和sum.o文件。现在应该把这2个.o文件进行链接,生成可执行文件。

    1> 注意,一定要同时链接两个文件。如果你只是单独链接main.o或者sum.o都是不可能链接成功的。原因如下:

    • 如果只是链接main.o文件:cc main.o,错误信息是:在main.o中找到不到sum这个标识符,其实就是找不到sum函数的定义。因为sum函数的定义在sum.o文件中,main.o中只有sum函数的声明

    • 如果只是链接sum.o文件:cc sum.o,错误信息是:找不到main函数。一个C程序的入口点就是main函数,main函数定义在main.o中,sum.o中并没有定义main函数,连入口都没有,怎么能链接成功、生成可执行文件呢?

    可以看出,main.o和sum.o有密不可分的关系,其实链接的目的就是将所有相关联的目标文件和C语言函数库组合在一起,生成可执行文件。

    2> 链接main.o和sum.o文件:cc main.o sum.o,生成了可执行文件a.out

    3> 运行a.out文件:./a.out,运行结果是在屏幕上输出了:

    c is 21

    说明函数调用成功,我们已经成功在main.c文件的main函数中调用了sum.c文件中的sum函数

    4> 从中也可以得出一个结论:只要知道某个函数的声明,就可以调用这个函数,编译就能成功。不过想要这个程序能够运行成功,必须保证在链接的时候能找到函数的定义。

    三、#include

    理解完前面的知识后,接下来就可以搞懂一个很久以前的问题:每次写在最前面的#include是干啥用的?

    1.#include的作用

    先来看一个最简单的C程序:

    复制代码

    1 #include <stdio.h>
    2 
    3 int main()
    4 {
    5     printf("Hello, World!\n");
    6     return 0;
    7 }

    复制代码

    这个程序的作用是在屏幕上输出Hello,World!这一串内容,我们主要关注第一行代码。

    • #include 是C语言的预处理指令之一,所谓预处理,就是在编译之前做的处理,预处理指令一般以 # 开头
    • #include 指令后面会跟着一个文件名,预处理器发现 #include 指令后,就会根据文件名去查找文件,并把这个文件的内容包含到当前文件中。被包含文件中的文本将替换源文件中的 #include 指令,就像你把被包含文件中的全部内容拷贝到这个 #include 指令所在的位置一样。所以第一行指令的作用是将stdio.h文件里面的所有内容拷贝到第一行中。
    • 如果被包含的文件拓展名为.h,我们称之为"头文件"(Header File),头文件可以用来声明函数,要想使用这些函数,就必须先用 #include 指令包含函数所在的头文件
    • #include 指令不仅仅限于.h头文件,可以包含任何编译器能识别的C/C++代码文件,包括.c、.hpp、.cpp等,甚至.txt、.abc等等都可以

    也就是说你完全可以将第3行~第7行的代码放到其他文件中,然后用 #include 指令包含进来,比如:

    1> 将第3行~第7行的代码放到my.txt中

    2> 在main.c源文件中包含my.txt文件

    • 编译链接后,程序还是可以照常运行的,因为 #include 的功能就是将文件内容完全拷贝到 #include 指令所在的位置
    • 说明:这里用txt文件纯属演示,平时做项目不会这样做,除非吃饱了撑着,才会把代码都写到txt中去

     

    2.#include可以使用绝对路径

    上面的#include "my.txt"使用的是相对路径,其实也可以使用绝对路径。比如#include "/Users/apple/Desktop/my.txt"

     

    3.#include <>和#include ""的区别

    二者的区别在于:当被include的文件路径不是绝对路径的时候,有不同的搜索顺序。

    1> 对于使用双引号""来include文件,搜索的时候按以下顺序:

    • 先在这条include指令的父文件所在文件夹内搜索,所谓的父文件,就是这条include指令所在的文件
    • 如果上一步找不到,则在父文件的父文件所在文件夹内搜索;
    • 如果上一步找不到,则在编译器设置的include路径内搜索;
    • 如果上一步找不到,则在系统的INCLUDE环境变量内搜索

    2> 对于使用尖括号<>来include文件,搜索的时候按以下顺序:

    • 在编译器设置的include路径内搜索;
    • 如果上一步找不到,则在系统的INCLUDE环境变量内搜索

    我这里使用的是clang编译器,clang设置include路径是(4.2是编译器版本):/usr/lib/clang/4.2/include

    Mac系统的include路径有:

    • /usr/include
    • /usr/local/include

     

    4.stdio.h

    我们已经知道#include指令的作用了,可是为什么要在第一行代码包含stdio.h呢?

    • stdio.h 是C语言函数库中的一个头文件,里面声明了一些常用的输入输出函数,比如往屏幕上输出内容的printf函数
    • 这里之所以包含 stdio.h 文件,是因为在第5行中用到了在 stdio.h 内部声明的printf函数,这个函数可以向屏幕输出数据,第7行代码输出的内容是:Hello, World!
    • 注意:stdio.h里面只有printf函数的声明。前面已经提到:只要知道函数的声明,就可以调用这个函数,就能编译成功。不过想要这个程序能够运行成功,必须保证在链接的时候能找到函数的定义。其实链接除了会将所有的目标文件组合在一起,还会关联C语言的函数库,函数库中就有printf函数的定义。因此前面的程序是可以链接成功的。

     

    5.头文件.h和源文件.c的分工

    跟printf函数一样,我们在开发中会经常将函数的声明和定义写在不同的文件中,函数声明放在.h头文件中,函数定义放在.c源文件中。

    下面我们将sum函数的声明和定义分别放在sum.h和sum.c中

    这是sum.h文件

    这是sum.c文件

    然后在main.c中包含sum.h即可使用sum函数

    其实sum.h和sum.c的文件名不一样要相同,可以随便写,只要文件名是合法的。但还是建议写成一样,因为一看文件名就知道sum.h和sum.c是有联系的。

    运行步骤分析:

    1> 在编译之前,预编译器会将sum.h文件中的内容拷贝到main.c中

    2> 接着编译main.c和sum.c两个源文件,生成目标文件main.o和sum.o,这2个文件是不能被单独执行的,原因很简单:

    * sum.o中不存在main函数,肯定不可以被执行

    * main.o中虽然有main函数,但是它在main函数中调用了一个sum函数,而sum函数的定义却存在于sum.o中,因此main.o依赖于sum.o

    3> 把main.o、sum.o链接在一起,生成可执行文件

    4> 运行程序

     

    说到这里,有人可能有疑惑:可不可以在main.c中包含sum.c文件,不要sum.h文件了?

    大家都知道#include的功能是拷贝内容,因此上面的代码等效于:

    这么一看,语法上是绝对没有问题的,main.c、sum.c都能编译成功,分别生成sum.o、main.o文件。但是当我们同时链接main.o和sum.o时会出错。原因:当链接这两个文件时链接器会发现sum.o和main.o里面都有sum函数的定义,于是报"标识符重复"的错误,也就是说sum函数被重复定义了。默认情况下,C语言不允许两个函数的名字相同。因此,不要尝试去#include那些.c源文件。

     

    有人可能觉得分出sum.h和sum.c文件的这种做法好傻B,好端端多出2个文件,你把所有的东西都写到main.c不就可以了么?

    • 没错,整个C程序的代码是可以都写在main.c中。但是,如果项目做得很大,你可以想象得到,main.c这个文件会有多么庞大,会严重降低开发和调试效率。
    • 要想出色地完成一个大项目,需要一个团队的合作,不是一个人就可以搞的定的。如果把所有的代码都写在main.c中,那就导致代码冲突,因为整个团队的开发人员都在修改main.c文件,张三修改的代码很有可能会抹掉李四之前添加的代码。
    • 正常的模式应该是这样:假设张三负责编写 main函数,李四负责编写其他自定义函数,张三需要用到李四编写的某个函数,怎么办呢?李四可以将所有自定义函数的声明写在一个.h文件中,比如 lisi.h,然后张三在他自己的代码中用#include包含lisi.h文件,接着就可以调用lisi.h中声明的函数了,而李四呢,可以独立地在另外一个文件中(比如lisi.c)编写函数的定义,实现那些在lisi.h中声明的函数。这样子,张三和李四就可以相互协作、不会冲突。
    展开全文
  • extern、定义和声明

    千次阅读 2019-03-07 11:41:23
    Extern的问题在于不知道这个关键词出现的时候到底是声明还是定义。 谨记:声明可以多次,定义...但是对于函数来说定义和声明完全不是一回事 。 void sum(int a,int b);这是函数的声明 void sum(int a,int ...

    Extern的问题在于不知道这个关键词出现的时候到底是声明还是定义。

    谨记:声明可以多次,定义只能一次。

        对于变量来说,定义就是声明.

       例如:  int a;  我们可是说它是定义也可以说它是声明。

       但是对于函数来说定义和声明完全不是一回事 。

        void   sum(int a,int b);这是函数的声明

        void   sum(int a,int b)

        {

        }

        整体是函数的定义  ,函数的定义没有分号 而且要加上一对花括号 ,里边是函数的实现。

       函数一定要在定义前声明否则会报错 。我一般在主函数前写上函数的声明 ,然后在主函数之后写函数的定义。

       当然 如果你用的函数是API已经封装好的  比如使用MFC里的open()打开文件或者文件夹函数时 ,就不需要声明  直接定义就可以了。
     

     demo:(大部分人看下demo应该就能理解)

    环境:vc++6.0

    运行结果(运行file2):

    函数的声明extern关键词是可有可无的,因为函数本身不加修饰的话就是extern的。但是引用的时候一样是需要声明的。

     

    全局变量在外部使用声明时,extern关键词是必须的,如果变量无extern修饰且没有显式的初始化,同样成为变量的定义,因此此时必须加extern,而编译器在此标记存储空间在执行时加载如内存并初始化为0。

    局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈部分分配内存。

     

     

    引用性声明、定义性声明

     

    强符号、弱符号

    出现在linux的gcc链接分析中,可以加深链接的理解。

    全局变量或函数本质上讲没有区别,函数名是指向函数二进制块开头处的指针。而全局变量是在函数外部声明的变量。函数名也在函数外,因此函数也是全局的。

     

    在使用中,要形成一种风格。

     

     

     

    头文件

    首先说下头文件,其实头文件对计算机而言没什么作用,她只是在预编译时在#include的地方展开一下,没别的意义了,其实头文件主要是给别人看的。

    我做过一个实验,将头文件的后缀改成xxx.txt,然后在引用该头文件的地方用

    #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;2、另一种是不需要建立存储空间,需要加extern 。如果你想在本源文件中使用另一个源文件的变量,就需要在使用前用extern声明该变量,或者在头文件中用extern声明该变量;

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

          

     

    extern "C"的用法 
    链接指示符extern C
        如果程序员希望调用其他程序设计语言尤其是C 写的函数,那么调用函数时必须告诉编译器使用不同的要求,例如当这样的函数被调用时函数名或参数排列的顺序可能
    不同,无论是C++函数调用它还是用其他语言写的函数调用它,程序员用链接指示符linkage directive 告诉编译器该函数是用其他的程序设计语言编写的,链接指示符有两种形式既可以是单一语句single statement 形式也可以是复合语句compound statement 形式。
    // 单一语句形式的链接指示符
    extern "C" void exit(int);
    // 复合语句形式的链接指示符
    extern "C" {
    int printf( const char* ... );
    int scanf( const char* ... );
    }
    // 复合语句形式的链接指示符
    extern "C" {
    #include <cmath>
    }
        链接指示符的第一种形式由关键字extern 后跟一个字符串常量以及一个普通的函数,声明构成虽然函数是用另外一种语言编写的但调用它仍然需要类型检查例如编译器会检查传递给函数exit()的实参的类型是否是int 或者能够隐式地转换成int 型,多个函数声明可以用花括号包含在链接指示符复合语句中,这是链接指示符的第二种形式花扩号被用作分割符表示链接指示符应用在哪些声明上在其他意义上该花括号被忽略,所以在花括号中声明的函数名对外是可见的就好像函数是在复合语句外声明的一样,例如在前面的例子中复合语句extern "C"表示函数printf()和scanf()是在C 语言中写的,函数因此这个声明的意义就如同printf()和scanf()是在extern "C"复合语句外面声明的一样,当复合语句链接指示符的括号中含有#include 时在头文件中的函数声明都被假定是用链接指示符的程序设计语言所写的在前面的例子中在头文件<cmath>中声明的函数都是C函数链接指示符不能出现在函数体中下列代码段将会导致编译错误。
    int main()
    {
    // 错误: 链接指示符不能出现在函数内
    extern "C" double sqrt( double );
    305 第七章函数
    double getValue(); //ok
    double result = sqrt ( getValue() );
    //...
    return 0;
    }
    如果把链接指示符移到函数体外程序编译将无错误
    extern "C" double sqrt( double );
    int main()
    {
    double getValue(); //ok
    double result = sqrt ( getValue() );
    //...
    return 0;
    }
        但是把链接指示符放在头文件中更合适在那里函数声明描述了函数的接口所属,如果我们希望C++函数能够为C 程序所用又该怎么办呢我们也可以使用extern "C"链接指示符来使C++函数为C 程序可用例如。
    // 函数calc() 可以被C 程序调用
    extern "C" double calc( double dparm ) { /* ... */ }
        如果一个函数在同一文件中不只被声明一次则链接指示符可以出现在每个声明中它,也可以只出现在函数的第一次声明中在这种情况下第二个及以后的声明都接受第一个声
    明中链接指示符指定的链接规则例如
    // ---- myMath.h ----
    extern "C" double calc( double );
    // ---- myMath.C ----
    // 在Math.h 中的calc() 的声明
    #include "myMath.h"
    // 定义了extern "C" calc() 函数
    // calc() 可以从C 程序中被调用
    double calc( double dparm ) { // ...
        在本节中我们只看到为C 语言提供的链接指示extern "C",extern "C"是惟一被保证由所有C++实现都支持的,每个编译器实现都可以为其环境下常用的语言提供其他链接指示例如extern "Ada"可以用来声明是用Ada 语言写的函数,extern "FORTRAN"用来声明是用FORTRAN 语言写的函数,等等因为其他的链接指示随着具体实现的不同而不同所以建议读者查看编译器的用户指南以获得其他链接指示符的进一步信息。

     

    总结 extern “C”

           extern “C” 不但具有传统的声明外部变量的功能,还具有告知C++链接器使用C函数规范来链接的功能。 还具有告知C++编译器使用C规范来命名的功能。

    展开全文
  • C语言变量定义和声明的区别

    千次阅读 2019-04-24 16:13:19
    变量的声明有两种情况 (1) 一种是分配内存空间的(声明)。例如:int a在声明的时候就已经分配了内存空间...可以理解为声明中包含着定义,但是并非所有的声明都是定义,例如:int a既是声明,同时又是定义。然而对于ext...

    变量的声明有两种情况
    (1) 一种是分配内存空间的(声明)。例如:int a在声明的时候就已经分配了内存空间。
    (2) 另一种是不需要分配内存空间的(声明)。例如:extern int a其中变量a是在别的文件中定义的。

    第一种是"定义性声明",或者称为”定义",第二种是"引用性声明"。
    可以理解为声明中包含着定义,但是并非所有的声明都是定义,例如:int a既是声明,同时又是定义。然而对于extern a来讲它只是声明不是定义。

    定义和声明的区别
    一般的情况下我们常常这样叙述,把分配内存空间的声明称之为"定义",把不需要分配内存空间称的声明之为"声明"。

    初始化和赋值
    给变量第一次赋值叫初始化,之后的赋值叫赋值

    总结

    extern int a; //声明
    
    int b;	//定义
    
    int b=1;	初始化
    
    b=2;	//赋值
    
    //另外在定义的时候也可以初始化,也就是我们常用的写法
    int c=3;
    
    展开全文
  • c++中定义和声明的区别

    万次阅读 多人点赞 2018-04-04 08:38:58
    定义和声明的简单说明a.声明就是指给除了当前变量或者函数,或者类什么的名字,不给其中的内容,就是先告诉你有这样一个什么类型的变量或者函数,但是这个变量或者函数的具体信息却是不知道的。就好比跟你介绍一个人...

    一.基本理解

    1.定义和声明的简单说明

    a.声明就是指给除了当前变量或者函数,或者类什么的名字,不给其中的内容,就是先告诉你有这样一个什么类型的变量或者函数,但是这个变量或者函数的具体信息却是不知道的。就好比跟你介绍一个人的时候,声明就是只告诉你这个人叫什么,但是缺不给你说这个人到底怎么样,他有哪些优点,缺点,喜好问题是什么的。

    b.定义就不一样了,定义直接告诉你了所有的东西,这个变量是什么,这个函数是什么功能,这个类里面包含了什么东西。很具体的说明。


    2.对于变量来说

    a.定义:可以为变量分配存储空间,并且可以给变量一个初始值

    b.声明:告诉编译器这个变量的名字和类型(extern int a;(在没有赋值的情况下,变量前加上关键字extern一定为声明))

    3.对于函数来说

    a.定义:就是这个函数具体的实现

    b.声明:告诉编译器在这个程序中会有这么一个函数

    简单来说,如果函数带有{},则其为定义;否则,就为声明。


    二.深入探讨

    1.在一个程序中只能对变量定义一次,因为我们不能让编译器一直为同一个变量,函数分配不同的存储空间;而可以对变量进行很多次的声明。

     2.在任何多文件中使用的变量都需要有与定义分离的声明。在这种情况下,一文件含有变量的定义,则使用该变量的其他文件中就要含有该变量的声明,而不是定义。

    3.在头文件中不能放变量的定义,一般存放变量的声明。因为头文件要被其他文件包含,如果放到头文件当中就不能避免变量被多次定义。(const,inline)

    三.类的声明

    类声明的一般形式:

    class类名

    {

         private: 私有数据成员; 私有的成员函数;

        protected: 被保护的数据成员; 被保护的成员函数;

        public: 公共的数据成员; 公共的成员函数;

    };

    其中:class是声明类的关键字,类名是要表明的类的名字,后面的花括号表示出类的声明范围;最后分号表示类声明结束。
    类的成员:①私有成员:被该类的成员函数访问
                        ②公有成员可被程序中的其它函数访问,是类的对外接口。
                       ③保护成员在类中等同于私有成员,在继承中等同于公有成员。
               注意:C++规定,在缺省情况下,类中的成员是私有的。
            类的作用域:指在类的声明中的一对花括号所形成的作用域。
    说明: 
    (1)数据成员可以是任何数据类型,但不能用自动(auto)寄存器(vegister)或外部(extern)  进行说明。
    (2)不能在类的声明中给数据成员赋初值。只有在类对象定义后才能给数据成员赋值。

    (3)成员函数,又称方法。其定义通常采取两种方式:外部定义,内部定义(①隐式定义:直接将函数定义在类内部; ②显式定义:在类定义体外定义内置函数,在函数定义前冠以"inline")。

    参考博客:http://lizhiyuan.bokee.com/907634.html




    展开全文
  • 定义和声明的区别

    万次阅读 多人点赞 2017-12-03 19:44:22
     但是对于函数来说定义和声明完全不是一回事 。  void sum(int a,int b);这是函数的声明  void sum(int a,int b)  {  }  整体是函数的定义 ,函数的定义没有分号 而且要加上一对花括号 ,里边是函
  • STM32全局变量的定义和声明

    万次阅读 2020-03-19 17:04:11
    STM32全局变量的定义和声明 今天在写SysTcik_Handler()这个中断函数时,总是报错,明明在开头定义的全局变量extern u16 ntime,(ntime–写在stm32f10x_it.c的systick中断函数中)但是编译时总是报错,百度之后才有...
  • C++中的类——类的定义和声明

    万次阅读 多人点赞 2018-08-23 10:49:04
    面向对象最大的特征就是提出了类对象的概念。在以面向对象的方式开发应用程序时,将遇到的各种事物抽象为类,类中通常包含数据...{数据方法的定义(可能含有类型成员)}; //类体 1、使用classstruct的...
  • C++类的定义和声明怎么写

    千次阅读 2019-01-08 17:42:59
    C++语言可以看成是C语言的扩展改进,相对于C语言,C++语言主要是增添了面向对象的特性。类(Class)则是C++面向对象编程的实现方式。 无论是何种编程语言,进行面向...首先我们来了解一下类的声明,先来看一个例子...
  • 变量的定义和声明的区别详解

    千次阅读 2015-08-31 14:39:21
    感言:我马上大三了,对计算机也算是有点感兴趣,但一直以来我对变量的定义和声明都很模糊,最开始看书上是这样讲的:定义-->就形如 int a;这就是定义了一个整形变量,然后就说变量的定义只能是一次而声明却可以多次...
  • Java中定义和声明的区别

    千次阅读 2016-05-22 16:50:31
    Java中最基本的就是定义变量和声明变量。 定义和声明的区别: 声明是向编译器介绍名字-标识符。它告诉编译器这个函数或变量在某处可以找到,它的模样像什么。而定义是说:“在这里建立变量”或“在这里建立函数”...
  • 4、c++定义和声明设置默认参数

    千次阅读 2017-11-20 10:09:01
    #include&lt;iostream&gt; using namespace std; int f(int a=4,int b=4);...}重载的时候,一个函数带有参数说明的时候,只能再定义时候或者声明的时候设置默认参数,不能在这两个地方同时设置;所
  • 定义和声明以及extern、static关键字

    千次阅读 2016-07-24 16:53:14
    3. 声明是表明变量的类型名称,因此定义也是声明。 4 . 没有初始化的时候,有extern表示这是声明,不是定义,不分配存储空间,如:extern int i; 5. 但是如果有初始化时,即使加了extern也是定义,如:...
  • 声明和定义的区别

    万次阅读 多人点赞 2019-01-10 13:21:07
    声明和定义的区别: 在我上课的书中并没有说明两者的区别,书上写着“在本书中,声明和定义有着相同的含义”,当时学的时候也没注意到这点,后来看到一些面试题,才注意到这些坑。  一种是需要建立存储空间的。...
  • 结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对问题事先自行定义,所以结构体类型变量的定义形式就增加了灵活性,共计有三种形式,分别介绍如下: 1) 先定义结构体类型,再定义...
  • C语言定义和声明

    千次阅读 2017-12-02 14:20:54
    什么是定义?什么是声明?它们有何区别?定义:(编译器)创建一个对象,为这个对象分配一块内存并给它 取上一个名字,并且这块内存的位置也...但是当啊a.cb.c编译成一个文件时将会报错(重复定义)分析: C语言编译
  • “通常情况下,你会在.h文件...因此,最好的办法就是将模板的声明和定义都放置在同一个.h文件中。这就是为什么所有的STL头文件都包含模板定义的原因。”[1] "标准要求编译器在实例化模板时必须在上下文中可以查看到其
  • 委托的定义和声明

    千次阅读 2017-12-11 22:59:28
    163-委托的定义和声明 C# 委托(Delegate)C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)特别用于...
  • 变量常量 定义和声明的其区别

    万次阅读 2016-07-26 21:12:39
    变量的声明和定义(初始化)是同时产生的; 而对于对象来说,声明和定义是分开的。 (我们声明的最终目的是为了提前使用,即在定义之前使用,如果不需要提前使用就没有单独声明的必要,变量...
  • java定义和声明的区别

    千次阅读 2018-01-04 17:07:50
    Java中,我们应该知道最基本的就是定义变量和声明变量了,那么定义声明这两者有没有区别呢?具体的区别又是哪些呢?下面学习啦小编来告诉你定义声明的区别。 定义和声明定义区别 1、一种是需要建立存储空间的...
  • 函数的声明和定义

    万次阅读 多人点赞 2019-04-03 16:26:45
    函数声明 1.让编译器知道函数的名字,参数,返回类型.但是具体是否存在,无关紧要. 2.函数的声明一般出现在函数...通过例子来看函数声明和函数定义. //函数定义 double Add(double x, double y){ return x+y; } //函数...
  • 动态数组的定义和声明(c++)

    千次阅读 2019-06-29 10:31:20
    动态数组的定义和声明:https://blog.csdn.net/singebogo/article/details/70477737
  • C语言中声明和定义详解

    万次阅读 多人点赞 2016-02-06 16:56:05
    变量声明和变量定义 变量定义:用于为变量分配存储空间,还可为变量指定初始值。程序中,变量有且仅有一个定义。 变量声明:用于向程序表明变量的类型和名字。 定义也是声明,extern声明不是定义 定义也是...
  • python:声明和定义

    千次阅读 2019-03-14 13:02:51
    由于是解释型,python中声明和定义是分不开的,即看见变量就要知道变量空间地址。 def func(): import packA # 函数内可以使用包 #函数外不可以使用包 python import可以import本文件 #A.py ...
  • C语言定义和声明区别

    千次阅读 2013-09-25 19:45:06
    C语言定义和声明分为变量的定义声明和函数的定义和声明。由于,函数是具有全局外部特性,并且函数的定义和声明区别是很明显的。其声明需要返回值类型,函数名和参数列表。而函数的定义需要函数体。所以,很容易...
  • 例如,一个学生类中一般需要有姓名、性别年龄等属性,这时就需要定义姓名、性别年龄 3 个属性。声明成员变量的语法如下: [public|protected|private][static][final]<type><variable_name> 各...
  • 结构体声明和定义

    千次阅读 2018-10-25 22:29:29
    1. 声明一个命名结构体 ​struct student { int age; char name[128]; }; ... 定义一个变量:struct student Lily;... 给结构体起别名:typedef...2. 声明一个命名结构体并定义一个变量 struct student { int ag...
  • C++:定义声明

    千次阅读 2018-10-05 17:48:51
    C++ 11标准规定了一种新的定义类型别名的方法:使用关键字using作为别名声明的开始,其后紧跟别名等号,其作用是把等号左侧的名字规定成等号右侧类型的别名。 标准库类型string #include using std::string;/...
  • 函数的定义声明的区别

    万次阅读 多人点赞 2019-01-06 15:42:38
    函数的声明可以与定义分离,要注意的是一个函数只能被定义一次,但可以声明多次。 函数声明由函数返回类型、函数名形参列表组成。形参列表必须包括形参类型,但是不必对形参命名。这三个元素被称为函数原型,函数...
  • C语言定义声明

    千次阅读 2019-04-05 21:50:14
    区分定义和声明 声明是普通的声明:这个名字已经匹配到一块内存上了,描述其他地方的创建的对象,声明可以声明多次 定义是特殊的声明:它为对象分配内存。声明没有分配内存,这是最大的区别。 定义指针时,编译器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,942,081
精华内容 776,832
关键字:

定义和声明

友情链接: LCD滚动显示汉字.zip