本节书摘来自异步社区《C语言接口与实现:创建可重用软件的技术》一书中的第2章,第2.2节,作者 傅道坤,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.2 实现
实现会导出接口。它定义了必要的变量和函数,以提供接口规定的功能。实现具体解释了接口的语义,并给出其表示细节和算法,但在理想情况下,客户程序从来都不需要看到这些细节。不同的客户程序可以共享实现的目标码,通常是从(动态)库加载实现的目标码。
一个接口可以有多个实现。只要实现遵循接口的规定,完全可以在不影响客户程序的情况下改变实现。例如,不同的实现可能会提供更好的性能。设计完善的接口会避免对特定机器的依赖,但也可能强制实现依赖于机器,因此对用到接口的每种机器,可能都需要一个不同的实现(也可能是实现的一部分)来支持。
在C语言中,一个实现通过一个或多个.c文件来提供。实现必须提供其导出的接口规定的功能。实现会包含接口的.h文件,以确保其定义与接口的声明一致。但除此之外,C语言中没有其他语言机制来检查实现与接口是否符合。
如同本书中的接口,本书描述的实现也具有一种风格化的格式,如arith.c所示:
〈arith.c〉≡
#include "arith.h"
〈arith.c functions 14〉
〈arith.c functions 14〉≡
int Arith_max(int x, int y) {
return x > y ? x : y;
}
int Arith_min(int x, int y) {
return x > y ? y : x;
}
除了〈arith.c functions 14〉,更复杂的实现可能包含名为〈data〉、〈types〉、〈macros〉、〈prototypes〉等的代码块。在不会造成混淆时,代码块中的文件名(如arith.c)将略去。
在Arith_div的参数符号不同时,它必须处理除法的两种可能行为。如果除法向零舍入,而y不能整除x,那么Arith_div(x,y)的结果为x/y - 1,否则,返回x/y即可:
〈arith.c _functions _14_〉+≡
int Arith_div(int x, int y) {
if (〈division truncates toward 0 14〉
&& 〈x and y have different signs 14〉 && x%y != 0)
return x/y - 1;
else
return x/y;
}
前一节的例子,即将-13除以5,可以测试除法所采用的舍入方式。首先判断x和y是否小于0,然后比较两个判断结果是否相等,即可检查符号问题:
〈division truncates toward 0 14〉≡
-13/5 == -2
〈x and y have different signs 14〉≡
(x < 0) != (y < 0)
Arith_mod可以按其定义实现:
int Arith_mod(int x, int y) {
return x - y*Arith_div(x, y);
}
如果Arith_mod也像Arith_div那样进行判断,那么也可以使用%运算符实现。在相应的条件为真时,
Arith_mod(x,y) = x - y*Arith_div(x, y)
= x - y*(x/y - 1)
= x - y*(x/y) + y
加下划线的子表达式是标准C对x%y的定义,因此Arith_mod可定义为:
〈arith.c functions 14〉+≡
int Arith_mod(int x, int y) {
if (〈division truncates toward 0 14〉
&& 〈x and y have different signs 14〉 && x%y != 0)
return x%y + y;
else
return x%y;
}
Arith_floor刚好等于Arith_div,而Arith_ceiling等于Arith_div加1,除非y能整除x:
〈arith.c functions 14〉+≡
int Arith_floor(int x, int y) {
return Arith_div(x, y);
}
int Arith_ceiling(int x, int y) {
return Arith_div(x, y) + (x%y != 0);
}