结构体与指针
在C语言中,指针可以指向万物,自然也少不了结构体。
使用结构体指针,有4点好处:
- 就像指向数组的指针比数组本身更容易操控一样,指向结构的指针通常比结构本身更容易操控
- 在早期的C中,结构不能作为参数传递给函数,但是可以传递指向结构的指针
- 即使能传递一个结构,传递指针通常更有效率
- 一些用于表示数据的结构中包含指向其他结构的指针
根据这4点好处,证明学习结构体指针的重要性
// Book结构体沿用上面
int main(void) {
struct Book books[2] = {
{"C Primer Plus", "Stephen Prata", 59.4},
{"黑客与画家", "Paul Graham", 49.00}
};
struct Book * book1; // 这是一个指向结构的指针
book1 = &books[0]; // 告诉编译器指针指向何处:结构数组第一个结构
printf("[book1] title = %s, author = %s, price = %f\n", book1->title, book1->author, book1->price);
book1++;
printf("[book1] title = %s, author = %s, price = %f", book1->title, book1->author, book1->price);
return 0;
}
Output:
[book1] title = C Primer Plus, author = Setphen Prata, price = 59.4
[book1] title = 黑客与画家, author = Paul Graham, price = 49
声明和初始化结构指针
声明结构指针很简单:
struct Book * book;
首先是关键字struct,其次就是结构标记Book,然后星号(*)代表着指针,跟着指针名。语法与其他指针声明一样。
该声明并未创建一个新的结构,但是指针book现在可以指向任意现有的Book类型的结构。例如,如果book1是一个Book类型的结构,那么就可以这样写:
book = &book1;
使用指针访问结构成员
使用指针访问结构成员有两种方法。
第一种也是最常用的一种就是使用 -> 运算符,该运算符由一个连接号 ( - ) 后跟一个大于号 ( > ) 组成
第二种方法就是老套的指针取值,使用*获取结构成员的值
printf("Book's title = %s\n", book->title);
printf("Book's title = %s\n", (*book).title);
向函数传递结构信息
函数的参数把值传递给函数,每个值都是一个数字----可能是int类型、float类型,可能是ASCII字符码,或者是一个地址。然而,一个结构比一个单独的值复杂,所以较早时期的C实现不允许把结构作为参数传递给函数。当前的实现已经移除了这个限制,C允许把结构作为参数使用。所以可以选择是传递结构本身,还是传递指向结构的指针。
传递结构成员
struct Book {
char title[128];
char author[40];
float price;
}
void output(char title[], float price);
int main(void) {
struct Book book = {"C Primer Plus", "Stephen Prata", 59.4};
output(book.title, book.price);
return 0;
}
void output(char title[], float price) {
printf("书名: 《%s》, 价格: %f\n", title, price);
}
传递参数没问题,因为output()函数即不知道也不关心实际的参数是否是结构的成员,它只要求被传入的数据是char数组和float类型。
如果想要再被调函数中修改主调函数中成员的值,就要传递成员的地址。
传递结构的地址
struct Formula {
int a;
int b;
}
int sum(struct Formula *); // 参数是一个指针
int main(void) {
struct Formula formula = {1, 2};
int result = sum(&formula);
return 0;
}
int sum(struct Formula * formula) {
return (formula->a + formula->b);
}
传递结构
struct Formula {
int a;
int b;
}
int sum(struct Formula);
int main(void) {
struct Formula formula = {1, 2};
int result = sum(formula);
return 0;
}
int sum(struct Formula form) {
return (form.a + form.b);
}
调用sum()时,编译器根据Formula模板创建了一个名为form的自动结构变量。然后,该结构的各成员被初始化为formula结构变量相应成员的值的副本。因此,程序使用原来结构的副本进行计算,然而,传递指针的程序使用的是原始的结构进行计算。由于form是另一个结构,所以该程序使用form.a,而不是form->a。