您的位置:首页 > 编程语言 > C语言/C++

c语言的作用域、变量与结构体

2014-12-10 22:46 323 查看
一、变量的作用域根据变量的作用域,可以分为:1.局部变量:1>定义:在函数(代码块)内部定义的变量(包括函数的形参)2>作用域:局部变量只有在定义它的函数内部使用,其它函数不能使用它。从定义变量的那一行开始,一直到代码块结束3>生命周期:从定义变量的那一行开始分配存储空间,代码块结束后,就会被回收4>没有固定的初始值2.全局变量1>定义:在函数外面定义的变量2>作用域:从定义变量的那一行开始,一直到文件结尾(能被后面的所有函数共享)3>生命周期:程序一启动就会分配存储空间,程序退出时才会被销毁4>默认的初始值就是0
inta;

intmain()
{
intb;
return0;
}
第1行的变量a是全局变量,第7行的变量b是局部变量。
//全局变量:a、b、c
//局部变量:v1、v2、e、f

#include<stdio.h>
//变量a的初值是10
inta=10;

//变量b的初值是0
//变量c的初值是20
intb,c=20;

intsum(intv1,intv2)
{
returnv1+v2;
}

voidtest()
{
b++;

inti=0;
i++;

printf("b=%d,i=%d\n",b,i);
}

intmain()
{
test();
test();
test();

inte=10;

{
{
intf=30;
}
}

return0;
}

二、变量的存储类型

*变量的存储类型就是指变量存储在什么地方。有3个地方可以用于存储变量:普通内存、运行时堆栈、硬件寄存器。变量的存储类型决定了变量何时创建、何时销毁以及它的值能保持多久,也就是决定了变量的生命周期。*C语言根据变量的存储类型的不同,可以把变量分为:自动变量、静态变量、寄存器变量。

1.自动变量

1>定义:自动变量是存储在堆栈中的。2>哪些是自动变量:被关键字auto修饰的局部变量都是自动变量,但是极少使用这个关键字,基本上是废的,因为所有的局部变量在默认情况下都是自动变量。2.静态变量1>定义:静态变量是存储在静态内存中的,也就是不属于堆栈。2>哪些是静态变量:所有的全局变量都是静态变量被关键字static修饰的局部变量也是静态变量3>生命周期:静态变量在程序运行之前创建,在程序的整个运行期间始终存在,直到程序结束。

3.寄存器变量

1>定义:存储在硬件寄存器中的变量,称为寄存器变量。寄存器变量比存储在内存中的变量访问效率更高(默认情况下,自动变量和静态变量都是放在内存中的)2>哪些变量是寄存器变量:被关键字register修饰的自动变量都是寄存器变量只有自动变量才可以是寄存器变量,全局变量和静态局部变量不行寄存器变量只限于int、char和指针类型变量使用3>生命周期:因为寄存器变量本身就是自动变量,所以函数中的寄存器变量在调用该函数时占用寄存器中存放的值,当函数结束时释放寄存器,变量消失。
intmain(){
registerinta;
return0;
}
第2行的变量a是个寄存器变量。
4>使用注意:由于计算机中寄存器数目有限,不能使用太多的寄存器变量。如果寄存器使用饱和时,程序将寄存器变量自动转换为自动变量处理为了提高运算速度,一般会将一些频繁使用的自动变量定义为寄存器变量,这样程序尽可能地为它分配寄存器存放,而不用内存3>生命周期:静态变量在程序运行之前创建,在程序的整个运行期间始终存在,直到程序结束。
#include<stdio.h>

inta;

voidtest(){
staticintb=0;
b++;

intc=0;
c++;

printf("b=%d,c=%d\n",b,c);
}

intmain(){
inti;
//连续调用3次test函数
for(i=0;i<3;i++){
test();
}

return0;
}
*第3行的变量a、第6行的变量b都是静态变量,第9行的变量c、第16行的变量i是自动变量。*因为第6行的变量b是静态变量,所以它只会被创建一次,而且生命周期会延续到程序结束。因为它只会创建一次,所以第6行代码只会执行一次,下次再调用test函数时,变量b的值不会被重新初始化为0。*注意:虽然第6行的变量b是静态变量,但是只改变了它的存储类型(即生命周期),并没有改变它的作用域,变量b还是只能在test函数内部使用。*我们在main函数中重复调用test函数3次,输出结果为:

一、什么是结构体

*当一个整体由多个数据构成时,我们可以用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据。*在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。*结构体允许内部的元素是不同类型的。二、结构体的定义

1.定义形式

结构体内部的元素,也就是组成成分,我们一般称为"成员"。结构体的一般定义形式为:
struct 结构体名{

类型名1 成员名1;

类型名2 成员名2;

……

类型名n 成员名n;   

};
例如
structDate
{
intyear;
intmonth;
intday;
};
struct是关键字,是结构体类型的标志。

2.举例

比如,我们定义一个学生
structStudent{
char*name;//姓名
intage;//年龄
floatheight;//身高
};
上面定义了一个叫做Student的结构体,共有name、age、height3个成员。三、结构体变量的定义前面只是定义了名字为Student的结构体类型,并非定义了一个结构体变量,就像int一样,只是一种类型。接下来定义一个结构体变量,方式有好多种。

1.先定义结构体类型,再定义变量

1structStudent{
2char*name;
3intage;
4};
5
6structStudentstu;
第6行定义了一个结构体变量,变量名为stu。struct和Student是连着使用的。

2.定义结构体类型的同时定义变量

structStudent{

char*name;
intage;
}stu;
结构体变量名为stu

3.直接定义结构体类型变量,省略类型名

struct{

char*name;
intage;
}stu;
结构体变量名为stu
/*
数组:只能由多个相同类型的数据构成

结构体:可以由多个不同类型的数据构成
*/
#include<stdio.h>

intmain()
{
//intages[3]={[2]=10,11,27};

//intages[3]={10,11,29};

//1.定义结构体类型
structPerson
{//里面的3个变量,可以称为是结构体的成员或者属性
intage;//年龄
doubleheight;//身高
char*name;//姓名
};

//2.根据结构体类型,定义结构体变量
structPersonp={20,1.55,"jack"};
p.age=30;
p.name="rose";

printf("age=%d,name=%s,height=%f\n",p.age,p.name,p.height);

/*错误写法
structPersonp2;
p2={30,1.67,"jake"};
*/

structPersonp2={.height=1.78,.name="jim",.age=30};
//p2.age=25;

return0;
}
四、结构体的注意点

1.不允许对结构体本身递归定义

如下做法是错误的,注意第3行
structStudent{
intage;
structStudentstu;
};

2.结构体内可以包含别的结构体

#include<stdio.h>intmain()
{
structDate { intyear; intmonth; intday; };//类型
structStudent
{
intno;//学号structDatebirthday;//生日structDateruxueDate;//入学日期//这种写法是错误的
//structStudentstu;
};structStudentstu={1,{2000,9,10},{2012,9,10}};printf("year=%d,month=%d,day=%d\n",stu.birthday.year,stu.birthday.month,stu.birthday.day);printf("year=%d,month=%d,day=%d\n",stu.ruxueDate.year,stu.ruxueDate.month,stu.ruxueDate.day);return0;
}

3.定义结构体类型,只是说明了该类型的组成情况,并没有给它分配存储空间,就像系统不为int类型本身分配空间一样。只有当定义属于结构体类型的变量时,系统才会分配存储空间给该变量

structStudent{
char*name;
intage;
};

structStudentstu;
第1~4行并没有分配存储空间,当执行到第6行时,系统才会分配存储空间给stu变量。

4.结构体变量占用的内存空间是其成员所占内存之和,而且各成员在内存中按定义的顺序依次排列

比如下面的Student结构体:
structStudent{
char*name;//姓名
intage;//年龄
floatheight;//身高
};
在16位编译器环境下,一个Student变量共占用内存:2+2+4=8字节。

5.结构体类型不能重复定义
structStudent
{
intage;
};

structStudent
{
doubleheight;
};

structStudentstu;
五、结构体的初始化将各成员的初值,按顺序地放在一对大括号{}中,并用逗号分隔,一一对应赋值。比如初始化Student结构体变量stu
structStudent{
char*name;
intage;
};

structStudentstu={"xiaomeng",27};
只能在定义变量的同时进行初始化赋值,初始化赋值和变量的定义不能分开,下面的做法是错误的:
structStudentstu;
stu={"MJ",27};
六、结构体的使用

1.一般对结构体变量的操作是以成员为单位进行的,引用的一般形式为:结构体变量名.成员名

structStudent{
char*name;
intage;
};
structStudentstu;

//访问stu的age成员
stu.age=27;
第8行对结构体的age成员进行了赋值。"."称为成员运算符,它在所有运算符中优先级最高

2.如果某个成员也是结构体变量,可以连续使用成员运算符"."访问最低一级成员

structDate{
intyear;
intmonth;
intday;
};

structStudent{
char*name;
structDatebirthday;
};

structStudentstu;

stu.birthday.year=1986;
stu.birthday.month=9;
stu.birthday.day=10;
注意第14行以后的代码

3.相同类型的结构体变量之间可以进行整体赋值

structStudent{
char*name;
intage;
};

structStudentstu1={"MJ",27};

//将stu1直接赋值给stu2
structStudentstu2=stu1;

printf("ageis%d",stu2.age);
注意第9行。输出结果为:
补齐算法
#include<stdio.h>
intmain()
{
structStudent
{//补齐算法
intage;//4个字节chara;//1个字节//char*name;//8个字节
};structStudentstu;
//stu.age=20;
//stu.name="jack";
//补齐算法(对齐算法)
//结构体所占用的存储空间必须是最大成员字节数的倍数ints=sizeof(stu);
printf("%d\n",s);return0;
}
七、结构体数组

1.定义

跟结构体变量一样,结构体数组也有3种定义方式
structStudent{
char*name;
intage;
};
structStudentstu[5];//定义1
structStudent{
char*name;
intage;
}stu[5];//定义2
struct{
char*name;
intage;
}stu[5];//定义3
上面3种方式,都是定义了一个变量名为stu的结构体数组,数组元素个数是5

2.初始化

struct{
char*name;
intage;
}stu[2]={{"MJ",27},{"JJ",30}};
也可以用数组下标访问每一个结构体元素,跟普通数组的用法是一样的举例
#include<stdio.h>
intmain()
{
structRankRecord
{
intno;//序号4
char*name;//名称8
intscore;//积分4
};//intages[3]={10,19,29};//intages[3];
//对齐算法
//能存放3个结构体变量,每个结构体变量占16个字节
//72
structRankRecordrecords[3]=
{
{1,"jack",5000},{2,"jim",500},{3,"jake",300}
};records[0].no=4;
//错误写法
//records[0]={4,"rose",9000};for(inti=0;i<3;i++)
{
printf("%d\t%s\t%d\n",records[i].no,records[i].name,records[i].score);
}//printf("%d\n",sizeof(records));return0;
}
八、结构体作为函数参数将结构体变量作为函数参数进行传递时,其实传递的是全部成员的值,也就是将实参中成员的值一一赋值给对应的形参成员。因此,形参的改变不会影响到实参。
#include<stdio.h>//定义一个结构体
structStudent{
intage;
};voidtest(structStudentstu){
printf("修改前的形参:%d\n",stu.age);
//修改实参中的age
stu.age=10;printf("修改后的形参:%d\n",stu.age);
}intmain(intargc,constchar*argv[]){structStudentstu={30};
printf("修改前的实参:%d\n",stu.age);//调用test函数
test(stu);printf("修改后的实参:%d\n",stu.age);
return0;
}
*首先在第4行定义了一个结构体类型Student*在第18行定义了一个结构体变量stu,并在第22行将其作为实参传入到test函数输出结果为:

,形参是改变了,但是实参一直没有变过九、指向结构体的指针*每个结构体变量都有自己的存储空间和地址,因此指针也可以指向结构体变量*结构体指针变量的定义形式:struct结构体名称*指针变量名*有了指向结构体的指针,那么就有3种访问结构体成员的方式结构体变量名.成员名(*指针变量名).成员名指针变量名->成员名
#include<stdio.h>
intmain()
{
structStudent
{
intno;
intage;
};
//结构体变量
structStudentstu={1,20};//指针变量p将来指向structStudent类型的数据
structStudent*p;//指针变量p指向了stu变量
p=&stu;p->age=30;//第一种方式
printf("age=%d,no=%d\n",stu.age,stu.no);//第二种方式
printf("age=%d,no=%d\n",(*p).age,(*p).no);//第三种方式
printf("age=%d,no=%d\n",p->age,p->no);return0;
}
输出结果:age=30,no=1     age=30,no=1    age=30,no=1

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: