------ Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! -------
1.结构体
结构体是一种构造类型,像数组一样,也是由多个不同的数据构成的整体,但是允许数据成员的类型不同。基本数据类型,例如int之类的是单个的,那么他们的组合有两种方式,第一种是同类型的,叫做数组,一种是不同类型的数据搞个组合,叫做结构体。
在这里记住一句话:有了类型才能定义变量,定义了变量才会分配存储空间
1.定义结构体类型
格式: struct name { ...; ...; }; //元素用分号分隔
struct Student {
int age; //年龄
char* name; //姓名
float heght; //身高
};
定义了一个结构体的类型,只是定义了一个类型,不分配内存空间。
结构体变量的定义
a.struct Student stu;
struct Student是变量的类型,stu是变量的名称,类似于int n;
定义结构体类型时不分配内存,定义变量时才分配内存。
b.struct Student { ... } stu; //结构体定义就相当于int,这样就相当于int stu;
stu.name = "MJ"; stu.age = 27; stu.height = 1.80;
或者struct Student { ... } stu = {27, "mj", 1.8f}; //可以直接赋值,相当于int s = 5;
这样定义的结构体类型还可以继续使用:struct Student stu2;
c.struct { ... } stu = {27, "mj", 1.8f};
这种情况就不能再定义其它同类型的变量了,只能定义一个,每次定义变量都得重新写一遍。
#import <Foundation/Foundation.h>
int main()
{
struct Person
{
int age;
double height;
char *name;
};
struct Person p = {35,1.78,"jack"};
p.age = 25;
NSLog(@"age=%d,height=%f,name=%s",p.age,p.height,p.name);
return 0;
}
2.结构体内存
a定义结构体类型时,不会在内存中分配存储空间。定义结构体变量时会在内存中给它分配存储空间用于存放它的属性值。
b.一个结构体变量所占用的内存大小大约等于它各个属性的内存大小之和。会补齐为占用内存最大的属性所占空间的整数倍。( 补齐算法 )
#import <Foundation/Foundation.h>
int main()
{
struct Person
{
int age; // 4个
double height; // 8个
char *name; // 指针永远是8个字节,struct占用的内存一定是最大字节的倍数(补齐算法)
};
struct Person m = {35,1,"ja"};
int w = sizeof(m);
NSLog(@"p字节是%d",w);
NSLog(@"age=%d,height=%f,name=%s",m.age,m.height,m.name);
NSLog(@"%p",&m); // %p代表地址, &m代表取m的地址
return 0;
}
3.结构体类型的作用域
a.结构体类型的作用域和一般变量的作用域一样,从定义类型的那行开始,到当前代码块结束.
b.如果结构体类型定义在函数体内,那么其它函数就不可以使用它来定义变量.
c.可把结构体类型写在函数体外,就是全局类型.
d.如果在函数体外定义了一个结构体类型,在函数体内部又定义了一个同名的结构体类型,是可以的.在这个函数体内部定义结构体变量时,用的是内部定义的结构体类型,需要按照内部定义的类型来给变量赋值.
访问结构体的成员变量
结构体变量名.成员变量名
stu.age; stu.name; stu.height;
初始化
a.定义结构体变量时可以初始化,对所有成员变量赋值:
struct Student stu = {27, "mj", 1.55f};//按照定义的顺序逐个赋值。
b.定义时也可以按照任意顺序赋值
struct Student stu = {.name = "mj", .height = 1.80, .age = 20};
c定义后再赋值就必须逐个属性赋值
struct Student stu;
stu = {15, "mj", 1.55}; //不允许!
stu.name = "mj"; stu.age = 15; //可以
struct Date // 作用范围是全局,如果是定义在某个函数中的,那作用范围就是那个函数了,其他函数引用,就会报错了
{
int year;
int month;
int day;
};
int main()
{
struct Date d = {2001,10,9};
int s = sizeof(d);
NSLog(@"p字节是%d",s);
NSLog(@"%d年%d月%d月",d.year,d.month,d.day);
NSLog(@"%p",&d); // %p代表地址, &m代表取m的地址
return 0;
}
4.复合结构体
a.结构体类型的内部不可以有自身结构体(不允许对结构体本身递归定义)
struct Student {
int age;
struct Student stu; //错误:不可以在定义内部使用本身
};
b.结构体类型的定义可以包含其它结构体
struct Date {
int year, month, day;
};
struct Student {
char *name;
struct Date birthday; //可以在定义内包含别的结构体
};
复合结构体的使用
a.变量定义和赋值
struct Student stu = {"mj", {2010, 10, 10}); // <----这样赋值
b.访问成员变量
stu.name;
stu.birthday.year;
stu.birthday.month;
stu.birthday.day;
5.结构体数组
struct Student {
int age;
char* name;
} a[2] = { {27, "mj"}, {25, "abc"} };
注意
外面的大括号是初始化数组的大括号,里面的大括号是初始化结构体的大括号。 定义后就不可以再使用初始化的大括号.
a[0] = {29, "mj"}; 错误!
a[0].age = 29; 正确!
b.struct Student {...}; //定义结构体类型
struct Student a[2] = {{}, {}}; //定义一个struct Student类型的数组
struct Student b[2] = {{}, {}};
注意struct Student就是一个类型,它们是一个整体。
int main()
{
struct Rankrecord
{
int no;
char *name;
int scores;
};
struct Rankrecord records[3] =
{
{1,"jack",78},
{2,"rose",87},
{3,"halla",98}
};
records[1].name = "baba";
for (int i = 0;i<3;i++)
{
NSLog(@"%d,%s,%d",records[i].no,records[i].name,records[i].scores);
}
return 0;
}
6.结构体指针
struct Student {...};
struct Student *s; //定义一个struct Student类型的指针
struct Student stu = {...}; //定义同种类型的结构体变量
s = &stu; //指针指向同种类型的变量
使用结构体指针访问成员,两种方式:
(*s).age; //相当于 stu.age,括号不可以省略
s -> age; // ->成员访问符,通常使用这种方式,只有指针可以使用这种方式
int main()
{
struct Student
{
int age;
int weight;
};
struct Student S1 = {23,2};
struct Student *p;
p = &S1; // 把s1地址给p
NSLog(@"%d,%d",S1.age,S1.weight);
NSLog(@"%d,%d",(*p).age,(*p).weight);
NSLog(@"%d,%d",p->age,p->weight);
return 0;
}
7.结构体嵌套
int main()
{
struct Date
{
int year;
int month;
int day;
};
struct Student
{
int no;
struct Date birthday;
struct Date ruxue;
};
struct Student S1 = {1,{1990,10,24},{2012,9,8}};
NSLog(@"%d,%d,%d",S1.birthday.year,S1.birthday.month,S1.birthday.day);
return 0;
}
2.枚举
枚举类型由一组数据组成,用来声明一组命名的常数。枚举变量就是其中的一个常数。
当一个变量只有几个固定的可能取值时,可以将这个变量定义为枚举类型。比如,季节只有春夏秋冬四种可能取值,可以定义为一个枚举类型的变量。
定义枚举类型
格式: enum name { ..., ... }; 括号里罗列可能的取值,用逗号分隔。
比如 enum Season {spring, summer, autumn, winter}; //定义类型,没有等号
定义枚举变量
enum Season s = spring;
定义枚举变量的方式:
a.先定义枚举类型,再定义枚举变量:
enum Season {spring, summer, autumn, winter}; //定义一个枚举类型
enum Season s=spring; //定义一个枚举变量
b.定义枚举类型的同时定义一个变量:
enum Season {spring, summer, autumn, winter} s = spring;
这个枚举类型以后也可以用来定义其它变量
c.枚举类型的名字也可以省略,直接定义一个枚举变量:
enum {spring, summer, autumn, winter} s = winter;
这个枚举类型不能再用于定义其它变量,是一次性的
int main()
{
enum Season{spring,summer,autumn,winter};
enum Season p = summer;
NSLog(@"%d",p);
return 0;
}
注意
不同的枚举类型不能使用相同的元素名称.因此,枚举类型的元素,通常以枚举类型的名称开头
enum SexA { SexAMale, SexAFemale };
enum SexB { SexBFemale, SexBMale, SexBUnknown };