有时候,程序需要多个基本类型的组成一个有机整体,比如说定义一个矩形,就需要 x,y,width,height 4个值。这就需要使用 语言提供的结构体。
语法格式:
struct 结构体类型名
{
//成员列表;
}
其中,struct 是关键字。结构体类型名可以任意指定,成员列表可以是基本类型也可以是结构体类型。
定义一个 rect 结构体类型,示例:
struct rect
{
int x;
int y;
int width;
int height;
}
定义结构体类型后,就可以利用该结构体定义变量了。利用结构体类型定义变量有2种形式:
语法格式如下:struct 结构体名 变量名;
注意不要忘了 struct 关键字。示例代码:
#import
int main(int argc , char * argv[])
{
@autoreleasepool{
// 定义point结构体类型
struct point
{
int x;
int y;
};
// 使用结构体类型定义2个变量
struct point p1;
struct point p2;
// 定义rect结构体类型
struct rect
{
int x;
int y;
int width;
int height;
};
// 使用结构体类型定义2个变量
struct rect rect1;
struct rect rect2;
}
}
这种每次定义变量时都需要使用 struct 关键字,比较繁琐。有2种简化方法:
一是:使用#define 预编译指令为 struct point,struct rect 定义成一个简短的字符串,比如:
//简化 struct 类型名为POINT,RECT
#define POINT struct point
#define RECT struct rect
二是:使用 typedef 为已有的结构体类型定义新名称。
typedef语句是给已有 的数据类型另起一个名称。语法格式为:typedef 已有类型 新名称;
typedef 语句是为了给已有的数据类型一个可读性更强的名字,但不可滥用,否则会造成数据类型混乱。
typedef 语句常用的地方:
1.当定义枚举类型后,通过typedef 为枚举类型起一个别名可能更简洁。
2.使用typedef为结构体类型起一个可读性强的别名。
示例代码:
#import
int main(int argc , char * argv[])
{
@autoreleasepool{
// 定义point结构体类型的同时,还定义结构体变量
struct point
{
int x;
int y;
};
// 为struct point类型起一个新名称:FKPoint
typedef struct point FKPoint;
// 定义一个season枚举类型
enum season {spring, summer, fall , winter};
// 为enum season类型起一个新名称:FKSeason
typedef enum season FKSeason;
// 使用FKPoint定义p1、p2两个结构体变量
FKPoint p1;
FKPoint p2;
// 使用FKSeason定义s1枚举变量
FKSeason s1;
}
}
语法格式:
struct 结构体名
{
//成员列表
}结构体变量1,结构体变量2...;
示例代码如下:
#import
int main(int argc , char * argv[])
{
@autoreleasepool{
// 定义point结构体类型的同时,还定义结构体变量
struct point
{
int x;
int y;
} p1;
// 使用结构体类型定义1个变量
struct point p2;
// 定义rect结构体类型的同时,还定义结构体变量
struct rect
{
int x;
int y;
int width;
int height;
} rect1;
// 使用结构体类型定义1个变量
struct rect rect2;
}
}
特别说明:这种方式下,如果程序只需要定义结构体类型的同时定义变量,以后无需再次使用该结构体类型来定义变量,程序甚至可以在定义结构体类型时省略结构体类型名。如下示例代码:
struct
{
int x;
int y;
}p1;
一般来说,结构体变量不允许直接赋值。只能分别对结构体的成员进行赋值或者访问结构体变量的某个成员。访问结构体成员变量的语法:结构体变量.成员名
只有在定义结构体变量时才能执行初始化。在定义结构体类型的同时定义结构体变量,OC 允许在定义结构体变量时对结构体变量执行初始化;使用 typedef 定义的别名来定义结构体变量时,可以对结构体变量执行初始化。
对结构体变量执行初始化的语法格式:{值1,值2,值3……};
,初始化的成员变量值的数量可以少于结构体变量所包含的成员数量。这种情况下,该初始化只对结构体变量的前面几个成员执行初始化。示例代码:
#import
int main(int argc , char * argv[])
{
@autoreleasepool{
// 定义point结构体类型的同时,还定义结构体变量
// 可以直接对结构体变量执行初始化
struct rect
{
int x;
int y;
int width;
int height;
} rect1 = {20 , 30 , 100 , 200};
// 下面代码是错误的
// rect1 = {1 , 2 , 3 , 4};
// 定义结构体类型
struct point
{
int x;
int y;
};
// 为struct point类型起一个新名称:FKPoint
typedef struct point FKPoint;
// 使用FKPoint定义结构体变量时,允许直接初始化
FKPoint p1 = {20 , 30};
FKPoint p2 = {10};
NSLog(@"p1的x为:%d, p1的y为:%d" , p1.x , p1.y);
NSLog(@"p2的x为:%d, p2的y为:%d" , p2.x , p2.y);
// 下面代码是错误的
// p1 = {2 , 3};
FKPoint p3;
// 依次对结构体变量的每个成员赋值,这总是正确的
p3.x = 10;
p3.y = 100;
NSLog(@"p3的x为:%d, p3的y为:%d" , p3.x , p3.y);
}
}
结构体数组与普通类型数组没有大区别,同样可以爱定义数组的时候对所有的数组元素执行初始化。但在此之后不能在程序运行中对结构体数组元素整体赋值。示例代码:
#import
int main(int argc , char * argv[])
{
@autoreleasepool{
// 定义结构体类型
struct point
{
int x;
int y;
};
// 为struct point类型起一个新名称:FKPoint
typedef struct point FKPoint;
// 定义结构体数组,并初始化数组元素
FKPoint points[] = {
{20 , 30},
{12 , 20},
{4 , 8}
};
// 下面代码是错误的
// points[1] = {20 , 8}; // ①
// 单独对结构体变量的每个成员赋值是允许的
points[1].x = 20;
points[1].y = 8;
// 遍历每个结构体数组元素
for (int i = 0 ; i < 3 ; i++)
{
NSLog(@"points[%d]的x是:%d, points[%d]的y是:%d"
, i , points[i].x, i , points[i].y);
}
}
}