你可能不知道的,定义,声明,初始化

声明定义虽然无处不在,但是真正的想区分它们,却不是表面上那么简单。
首先,从广义的角度来讲声明中包含着定义:定义又可以称之为,“声明性定义”;而狭义的声明,有可称之为“引用性声明”。
下面,我们就来讨论“声明性定义”与“引用性声明”。的区别,之后简称定义与声明。

1、定义时系统会为定义的变量分配空间,而声明时,不会分配空间。这个是本质上的区别。

2、定义在程序中只能出现一次,而声明可以多次。比如:
如果两个c中有相同的全局变量“定义”,且没有初始化,编译器会认为第二个是声明而不是定义。
所以连续写两个int a;int a; 编译也不会出错,但是连续写int a = 1;int a = 1;编译出错。(函数也一样)

3、由2可见,在定义变量时初始化的副作用是告诉编译器,这是一个定义,而不是一个声明。因为声明时,是不可以
初始化的,具体的例子就是  extern int a; 这表示这是个声明而不是定义。如果写成extern int a = 1;编译就会报错。
结合1来想,这个就很正常了,因为声明是没有分配空间的,如何赋值呢?

4、定义时可以完成声明,并且初始化!例如 int a = 0; //定义,声明,初始化就包含这一条语句之中。
//--------关于extern的用法-------------------
    extern的作用就是进行声明,实现调用其他文件的全局变量,或者函数。
由于声明可以多次,一般有的变量会被其他文件文件调用,如果不想用include包含整个头文件中的声明,而是想暴漏其中的某个全局变量和全局函数,就用extern。

extern的作用就是告诉编译器,去其他地方找找~~~
//--------关于struct的声明定义初始化-------------------
1、struct的定义(这里注意的是,struct定义的是类型,而不是变量;但是以上结论同样适用!)
struct people        //定义类型
{
    char name[20];
    int age;
};

2、struct people;    //声明类型,同样写两句一模一样的不会错!但是类型定义也只能一次。

3、定义类型时,同时利用类型声明(定义)变量。这里类肯定是定义好了,而s1如果没有其他初始化代码,这里就是即声明又定义了。
struct student
{
    char name[20];
    int age;
}s1;

   4、结构体变量的初始化,这个需要在3的前提下,这种形式的初始化可以不按照定义时的顺序,可帅气的称之为“乱序初始化”
struct student s1 =
{
    .age = 10,   
    .name = "linux",    //注意初始化结构体变量是用的是逗号,而定义结构体类型时,用的是分号。
};

5、省略掉类型的声明(定义)
struct
{
    char name[20];
    int age;
}s1;
但是无法像4中那样单独的初始化。

6、定义结构体类型时,无法初始化结构体变量,如下写法会报错:
struct student  //错误写法
{
    char name[20] = linux ;
    int age = 10;
}s1;

7、于似乎再次发现一种神奇的写法:这样写也是有效的
struct student
{
    char name[20];
    int age;
}s1 =
{
    .age = 10,
    .name = "linux",
};

8、去掉类型名字,这样写也是有效的
struct
{
    char name[20];
    int age;
}s1 =
{
    .age = 10,
    .name = "linux",
};
定义结构体类型,同时定义结构体变量,并初始化变量,就是这么帅~~

9、struct {}a和 struct a{} 的区别
前者是定义了a(结构体)变量,后者是定义了结构体类型a。

 

//--------关于enum的声明定义初始化-------------------
这个就直接摘抄朱老师(朱有鹏)笔记吧。
/*
****************************************************************
*     enumeration 类型定义
****************************************************************
*/
// 定义方法1,定义类型和定义变量分离开
enum week
{
    SUN,        // SUN = 0
    MON,        // MON = 1;
    TUE,
    WEN,
    THU,
    FRI,
    SAT,
};

enum week today;

// 定义方法2,定义类型的同时定义变量
enum week
{
    SUN,        // SUN = 0
    MON,        // MON = 1;
    TUE,
    WEN,
    THU,
    FRI,
    SAT,
}today,yesterday;

// 定义方法3,定义类型的同时定义变量
enum
{
    SUN,        // SUN = 0
    MON,        // MON = 1;
    TUE,
    WEN,
    THU,
    FRI,
    SAT,
}today,yesterday;

// 定义方法4,用typedef定义枚举类型别名,并在后面使用别名进行变量定义
typedef enum week
{
    SUN,        // SUN = 0
    MON,        // MON = 1;
    TUE,
    WEN,
    THU,
    FRI,
    SAT,
}week;


// 定义方法5,用typedef定义枚举类型别名,并在后面使用别名进行变量定义
typedef enum
{
    SUN,        // SUN = 0
    MON,        // MON = 1;
    TUE,
    WEN,
    THU,
    FRI,
    SAT,
}week;

结构体,枚举,使用方法总结:
1、结构体,枚举使用有很多相似的地方;
2、定义枚举类型时,用的是分号。而且可以同时初始化其实的变量。
3、枚举类型不管是类型名还是,枚举内部的变量都是全局的,所以都不能重名。而结构体内部的变量是局部的。
4、使用枚举是可以直接用其中的变量如:SUN;而结构体需要这么访问:s1.age

最后是关于static的声明:
static来声明一个变量的作用有二个:
(1)对于局部变量用static声明,则是为该变量拥有全局变量的特性——在整个程序的执行期内都始终存在。因为他和全局变量一样在数据段。而不再栈上。
同时拥有局部变量的特性——无法被外部程序访问,这个就是生命周期的问题。
(2)全局变量或者是函数用static来声明,则起到“隐蔽”的作用——该变量的作用域只限于本文件。其他文件无法访问。
加上extern也不行。

posted @ 2015-12-14 12:31  宋桓公  阅读(4147)  评论(0编辑  收藏  举报