C Primer Plus--结构和其他数据类型(1)
[TOC]结构变量 structure variable
C中struct是用来将多种数据类型组合到一起包装成一种新的类型。创建一个struct
数据类型需要:
- 建立结构的格式或布局
- 声明遵循该布局的变量
- 获取对一个结构变量的各个成员(member)或者字段(field)的访问
建立结构声明
struct book {
char title[30];
char author[30];
int price;
};
这样的声明是解释了一个标记(可以理解为别名)为book
的struct
类型所包含的数据类型:一个字符串数组-书名,一个字符串数组-作者,一个int-价格,就像一个模板一样。这样的声明只是声明了这样的一个数据对象,并没有实际非配存储空间。当使用这个数据类型时,才会分配空间:
struct book my_book;
这里就定义了一个book
类型的struct
对象,需要注意的是它里面的数据是没有进行默认初始化的。
定义结构声明
struct book my_book;
这个语句会使得编译器分配空间来容纳两个数组一个int。还可以这样定义:
struct
初始化类似于数组的初始化:
struct book mybook = {
"爱你就像爱生命",
"王小波",
29;
};
还可以指定初始化项目:
struct book book1 = {
.author = "王小波",
.title = "爱你就像爱生命",
.price = 29
};
这样初始化不需要保持顺序,而且可以只初始化若干个字段。类似于数组的指定元素初始化,会出现值的覆盖情况:
struct book book1 = {
.price = 29,
.author = "王小波"
35
};
此时书的价格变为35。
struct
结构的元素访问可以用点运算符:
struct book {
char title[30];
char author[30];
int price;
};
int main() {
struct book mybook = {
"爱你就像爱生命",
"王小波",
29.
};
printf("%s",mybook.title);
return 0;
}
结构数组
声明结构数组:
struct book books[20]
声明了一个可以容纳20本书的数组books
。
嵌套结构
允许一个结构的组成元素里面包含另一种结构。
struct publishing_house {
char name[30];
char location[30];
};
struct book {
struct publishing_house publishingHouse;//book这个类型包含出版社信息结构
char title[30];
char author[30];
int price;
};
int main() {
struct book mybook = {
{"上海文艺出版社",
"上海"},
"爱你就像爱生命",
"王小波",
29
};
return 0;
}
结构指针
声明一个指向结构的指针与普通指针声明方式差不多:
struct book * ptobook;
但是和数组不同之处在于结构的名字并不是该结构的地址,对ptobook
进行赋值时应该使用&
运算符进行取地址操作:
ptobook = & my_book;
使用指针访问结构成员
两种方法:
->
运算符
ptobook->author
返回的是ptobook
指向的book结构的author
字段值,是个字符串数组。*
运算符与.
运算符结合
(*ptobook).author
也是如此。
结构用于传参
结构用于传参可以有三种方式:
- 传递结构成员给函数
- 传递结构指针给函数
- 传递结构本身给函数
需要注意的是不同于传递结构指针的方式中函数会操作原有结构,向函数传递结构本身会产生一个原有结构的拷贝,这个拷贝是一个自动变量。
不同于数组无法互相赋值:
struct book mybook = {
{"上海文艺出版社",
"上海"},
"爱你就像爱生命",
"Bob",
29
};
// int array1[2] = {1,2};
// int array2[2];
// array2 = array1;//报错:Array type 'int [2]' is not assignable array2是常量,=左边应该是变量。数组无法整体赋值。
struct book the_same_book;
the_same_book = mybook;//合法
mybook.price = 10;
mybook.author[0] = 'A';
printf("my_book: %s
",mybook.author);
printf("the same book: %s
",the_same_book.author);
发现这样操作my_book
里面的所有成员都被重新拷贝了另一份,即使是数组也被完整拷贝了。
结构也可以作为函数的返回值。
在结构中使用指针的危害
struct name {
char firs[20];
char last[20];
};
struct pname {
char *first;
char *second;
};
在上面的代码中,两个struct结构中用了数组和指针两种方式来表明两个字符串变量。但是在指针方式中,指针没有初始化,那么创建的pname
对象中的字符串存储位置也就不确定,很可能会造成程序的崩溃。而使用数组方式就不用担心,因为数组会被分配专门的空间,不会造成修改其他正在被占用的内存里的数据。
联合(Union)数据结构
union
这种数据结构很有意思,它允许你像声明struct
那样创建一个模板,里面可以有各种数据类型。但是不同的是,它在某个时刻只能存储一个模板里的数据类型,也就是说,union
是用来存放不确定数据类型的数据。
union union_ {
int money;
double price;
char name;
};
这样的一个union_
某个时刻只能存储int
、double
、char
三种类型其中的一个数据。使用示例:
union union_ foo;
foo.money = 1000;//将1000存储在foo中
foo.name = 'A';//清除1000,将'A'存储在foo中
foo.price = 100.5;//清除'A',将100.5存储在foo中
编译器给foo
分配的空间按int
、double
、char
三种数据类型中所需的最大字节数来分配以保证可以满足可能出现的三种存储情况。union
同样支持互相赋值及->
运算符。union
可以声明struct
是它可能需要存储的数据类型。