7.2.3 结构体与函数
早期的 C 语言是不允许将结构体作为函数的参数或者返回值类型的,想要在函数中传递和使用结构体数据,只能以结构体指针的方式进行。但如今,这已经不是问题了,用户可以非常方便地将结构体变量作为函数的参数或者返回值。那么,这两种方式之间有何不同?孰优孰劣呢?下面就用一个案例来进行说明。
【 例 7-1 】编写程序,定义一个关于矩形的结构体 Rect,它的 3 个成员名分别为 length、width 和 area,都为 float 类型,用来表示矩形的长、宽和面积。再定义一个函数 calculate,该函数能够根据矩形结构体变量中的长和宽,计算出矩形面积。要求程序运行时,由用户输入矩形的长和宽,通过调用 calculate 函数,计算出矩形面积,并在主函数中将矩形的面积打印输出。
首先,先将这个矩形结构体定义出来,代码如下:
下面定义函数 calculate,分以下两种。
(1)将结构体变量作为函数参数或返回值。
首先将 calculate 定义为一个无返回值、参数类型为 struct Rect 的函数,代码如下:
函数体内就一条语句,通过成员访问运算符访问参数结构体变量的成员 length 和成员 width,并将它们的乘积赋值给成员 area。
主函数的代码如下:
在主函数中,首先定义一个 Rect 结构体的变量 rc,在提示用户输入矩形的长和宽后,使用 scanf 函数获取用户所输入的长和宽,并将其分别存储至 rc 的 length 成员和 width 成员。接着调用 calculate 函数,它会计算矩形面积并保存到成员 area 中,最后通过 printf 函数打印输出 rc 的 area 成员。编译运行程序,结果如下:
Please enter the length and width of the rectangle: 4 5 The area of the rectangle is: 0.00.
程序运行后,用户所输入的矩形长和宽分别为 4 和 5,正确的面积应该为 20,但程序的打印结果却是 0。很明显,程序代码是有问题的,但问题出在哪儿呢?
问题在于函数的参数传递是值传递的形式,实参与形参是两个不同的对象,有着各自不同的内存空间,因此,在函数中访问和修改的只是形参结构体变量,影响不到实参结构体变量。也就是说,calculate 函数中所访问和修改的只是形参结构体变量 rect,而不是实参结构体变量 rc。
为了解决这个问题,可以让 calculate 函数将修改后的结构体变量返回,即将 calculate 函数定义为一个有返回值的函数,并且返回值类型为 struct Rect。例如:
在主函数中,将 calculate 函数调用后的返回值,重新赋值给实参结构体变量 rc。例如:
rc = calculate(rc);
重新编译运行程序,结果如下:
Please enter the length and width of the rectangle: 4 5 The area of the rectangle is: 20.00.
可见,这次打印输出了正确的结果。
(2)将结构体指针作为函数参数或返回值。
下面再看一下将 calculate 函数的参数定义为结构体指针类型的情况。例如:
由于参数 pRect 是一个结构体指针,因此,在函数体内,可以使用箭头运算符来访问它所指向的结构体变量的成员。
在主函数中,调用 calculate 函数时,需要通过取地址运算符将结构体变量 rc 的内存地址取出,作为函数调用的实参。例如:
calculate(&rc);
其他部分代码不变,我们编译运行程序,结果如下:
Please enter the length and width of the rectangle: 4 5 The area of the rectangle is: 20.00.
可见,打印输出的结果是正确的。在 calculate 函数被执行时,形参 pRect 被初始化为实参 rc 的内存地址,即 pRect 是一个指向 rc 的结构体指针,通过这个指针来访问 rc 的成员 length 和 width,并将它们的乘积再重新赋值给成员 area。因此,可以通过指针 pRect 来访问和修改到实参 rc。所以可以将 calculate 函数定义为无返回值的函数。
如果想让 calculate 函数具有一个结构体指针类型的返回值,也是没有任何问题的。例如:
将返回值类型定义为 struct Rect*,即一个指向 Rect 结构体变量的指针。在函数体中,就可以将形参 pRect 作为返回值进行返回。
主函数中,由于 calculate 函数的返回值是一个结构体指针,因此,我们需要对其进行解引用,然后再重新赋值给实参结构体变量 rc。例如:
rc = *calculate(&rc);
其他部分代码不变,我们再次编译运行程序,仍会得到与之前相同的结果。
calculate 函数的返回值是一个指向结构体变量 rc 的指针,对该指针进行解引用,就访问到了结构体变量 rc,然后再把它赋值给 rc。实际上就是自己赋值给自己,所以意义不大,这样来使用,纯粹是为了展示如何将结构体指针作为函数返回值而已。不过,在第 8 章中,读者会真正看到结构体指针作为函数返回值的好处。
由于指针的大小是固定的,并且通常情况下,会小于结构体变量的大小。因此,将结构体指针作为函数的参数或返回值,会比使用结构体变量作为函数的参数或返回值所花费的系统开销更小、执行效率更高。这也是程序员喜欢使用结构体指针作为函数参数或返回值的重要原因之一。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论