- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C语言接口与实现方法实例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文以实例形式详细讲述了C语言接口与实现方法,对于深入掌握C语言程序设计有一定的借鉴价值。分享给大家供大家参考。具体分析如下:
一般来说,一个模块有两部分组成:接口和实现。接口指明模块要做什么,它声明了使用该模块的代码可用的标识符、类型和例程,实现指明模块是如何完成其接口声明的目标的,一个给定的模块通常只有一个接口,但是可能会有许多种实现能够提供接口所指定的功能。每个实现可能使用不同的算法和数据结构,但是它们都必须符合接口所给出的使用说明。客户调用程序是使用某个模块的一段代码,客户调用程序导入接口,而实现导出接口。由于多个客户调用程序是共享接口和实现的,因此使用实现的目标代码避免了不必要的代码重复,同时也有助于避免错误,因为接口和实现只需一次编写和调试就可多次使用.
接口 。
接口只需要指明客户调用程序可能使用的标识符即可,应尽可能地隐藏一些无关的表示细节和算法,这样客户调用程序可以不必依赖于特定的实现细节。这种客户调用程序和实现之间的依赖--耦合----可能会在实现改变时引起错误,当这种依赖性埋藏在一些关于实现隐藏的或是不明确的假设中时,这些错误可能很难修复,因此一个设计良好且描述精确的接口应该尽量减少耦合.
C语言对接口和实现的分离只提供最基本的支持,但是简单的约定能给接口/实现方法论带来巨大的好处。在C中,接口在头文件声明,头文件声明了客户调用程序可以使用的宏、类型、数据结构、变量以及例程。用户使用C语言的预处理指令#include导入接口.
下面的例子说明了本篇文章的接口中所使用的一些约定、接口:
1
2
3
4
5
6
|
extern
int
Arith_max(
int
x,
int
y);
extern
int
Arith_min(
int
x,
int
y);
extern
int
Arith_div(
int
x,
int
y);
extern
int
Arith_mod(
int
x,
int
y);
extern
int
Arith_ceiling(
int
x,
int
y);
extern
int
Arith_floor (
int
x,
int
y);
|
该接口的名字为Arith,接口头文件也相应地命名为arith.h,接口的名字以前缀的形式出现在接口的每个标识符中。模块名不仅提供了合适的前缀,而且还有助于整理客户调用程序代码.
Arith接口还提供了一些标准C函数库中没有但是很有用的函数,并为出发和取模提供了良好的定义,而标准C中并没有给出这些操作的定义和只提供基于实现的定义.
实现 。
一个实现导出一个接口,它定义了必要的变量和函数以提供接口所规定的功能,在C语言中,一个实现是由一个或多个.c文件提供的,一个实现必须提供其导出的接口所指定的功能。实现应包含接口的.h文件,以保证它的定义和接口的声明时一致的.
Arith_min和Arith_max返回其整型参数中的最小值和最大值:
1
2
3
4
5
6
|
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_div返回y除以x得到的商,Arith_mod返回相应的余数。当x与y同号的时候,Arith_div(x,y)等价于x/y,Arith_mod(x,y)等价于x%y 。
当x与y的符号不同的时候,C的内嵌操作的返回值就取决于具体的实现:
如果-13/5=2,-13%5=-3,如果-13/5=-3,-13%5=2 。
标准库函数总是向零取整,因此div(-13,2)=-2,Arith_div和Arith_mod的语义同样定义好了:它们总是趋近数轴的左侧取整,因此Arith_div(-13,5)=-3,Arith_div(x,y)是不超过实数z的最大整数,其中z满足z*y=x.
Arith_mod(x,y)被定义为x-y*Arith_div(x,y)。因此Arith_mod(-13,5)=-13-5*(-3)=2 。
函数Arith_ceiling和Arith_floor遵循类似的约定,Arith_ceiling(x,y)返回不小于实数商x/y的最小整数 。
Arith_floor(x,y)返回不超过实数商x/y的最大整数 。
完整实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include "arith.h"
int
Arith_max(
int
x,
int
y) {
return
x > y ? x : y;
}
int
Arith_min(
int
x,
int
y) {
return
x > y ? y : x;
}
int
Arith_div(
int
x,
int
y) {
if
(-13/5 == -2
&& (x < 0) != (y < 0) && x%y != 0)
return
x/y - 1;
else
return
x/y;
}
int
Arith_mod(
int
x,
int
y) {
if
(-13/5 == -2
&& (x < 0) != (y < 0) && x%y != 0)
return
x%y + y;
else
return
x%y;
}
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);
}
|
抽象数据类型 。
抽象数据类型(abstract data type,ADT)是一个定义了数据类型以及基于该类型值提供的各种操作的接口 。
一个高级类型是抽象的,因为接口隐藏了它的表示细节,以免客户调用程序依赖这些细节。下面是一个抽象数据类型(ADT)的规范化例子--堆栈,它定义了该类型以及五种操作:
1
2
3
4
5
6
7
8
9
10
11
|
#ifndef STACK_INCLUDED
#define STACK_INCLUDED
#define T Stack_T
typedef
struct
T *T;
extern
T Stack_new (
void
);
extern
int
Stack_empty(T stk);
extern
void
Stack_push (T stk,
void
*x);
extern
void
*Stack_pop (T stk);
extern
void
Stack_free (T *stk);
#undef T
#endif
|
实现 。
包含相关头文件:
1
2
3
4
5
|
#include <stddef.h>
#include "assert.h"
#include "mem.h"
#include "stack.h"
#define T Stack_T
|
Stack_T的内部是一个结构,该结构有个字段指向一个栈内指针的链表以及一个这些指针的计数:
1
2
3
4
5
6
7
|
struct
T {
int
count;
struct
elem {
void
*x;
struct
elem *link;
} *head;
};
|
Stack_new分配并初始化一个新的T:
1
2
3
4
5
6
7
|
T Stack_new(
void
) {
T stk;
NEW(stk);
stk->count = 0;
stk->head = NULL;
return
stk;
}
|
其中NEW是一个另一个接口中的一个分配宏指令。NEW(p)将分配该结构的一个实例,并将其指针赋给p,因此Stack_new中使用它就可以分配一个新的Stack_T 。
当count=0时,Stack_empty返回1,否则返回0:
1
2
3
4
|
int
Stack_empty(T stk) {
assert
(stk);
return
stk->count == 0;
}
|
assert(stk)实现了可检查的运行期错误,它禁止空指针传给Stack中的任何函数.
Stack_push和Stack_pop从stk->head所指向的链表的头部添加或移出元素:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
void
Stack_push(T stk,
void
*x) {
struct
elem *t;
assert
(stk);
NEW(t);
t->x = x;
t->link = stk->head;
stk->head = t;
stk->count++;
}
void
*Stack_pop(T stk) {
void
*x;
struct
elem *t;
assert
(stk);
assert
(stk->count > 0);
t = stk->head;
stk->head = t->link;
stk->count--;
x = t->x;
FREE(t);
return
x;
}
|
FREE是另一个接口中定义的释放宏指令,它释放指针参数所指向的空间,然后将参数设为空指针 。
1
2
3
4
5
6
7
8
9
|
void
Stack_free(T *stk) {
struct
elem *t, *u;
assert
(stk && *stk);
for
(t = (*stk)->head; t; t = u) {
u = t->link;
FREE(t);
}
FREE(*stk);
}
|
完整实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#include <stddef.h>
#include "assert.h"
#include "mem.h"
#include "stack.h"
#define T Stack_T
struct
T {
int
count;
struct
elem {
void
*x;
struct
elem *link;
} *head;
};
T Stack_new(
void
) {
T stk;
NEW(stk);
stk->count = 0;
stk->head = NULL;
return
stk;
}
int
Stack_empty(T stk) {
assert
(stk);
return
stk->count == 0;
}
void
Stack_push(T stk,
void
*x) {
struct
elem *t;
assert
(stk);
NEW(t);
t->x = x;
t->link = stk->head;
stk->head = t;
stk->count++;
}
void
*Stack_pop(T stk) {
void
*x;
struct
elem *t;
assert
(stk);
assert
(stk->count > 0);
t = stk->head;
stk->head = t->link;
stk->count--;
x = t->x;
FREE(t);
return
x;
}
void
Stack_free(T *stk) {
struct
elem *t, *u;
assert
(stk && *stk);
for
(t = (*stk)->head; t; t = u) {
u = t->link;
FREE(t);
}
FREE(*stk);
}
|
相信本文所述对大家的C程序设计有一定的借鉴价值.
最后此篇关于C语言接口与实现方法实例详解的文章就讲到这里了,如果你想了解更多关于C语言接口与实现方法实例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试在我的代码库中为我正在编写的游戏服务器更多地使用接口(interface),并了解高级概念以及何时应该使用接口(interface)(我认为)。在我的例子中,我使用它们将我的包相互分离,并使
我有一个名为 Widget 的接口(interface),它在我的整个项目中都在使用。但是,它也用作名为 Widget 的组件的 Prop 。 处理此问题的最佳方法是什么?我应该更改我的 Widget
有一个接口(interface)可以是多个接口(interface)之一 interface a {x:string} interface b {y:string} interface c {z:st
我遇到了一种情况,我需要调用第三方服务来获取一些信息。这些服务对于不同的客户可能会有所不同。我的界面中有一个身份验证功能,如下所示。 interface IServiceProvider { bool
在我的例子中,“RequestHandlerProxy”是一个结构,其字段为接口(interface)“IAdapter”,接口(interface)有可能被调用的方法,该方法的输入为结构“Reque
我有一个接口(interface)Interface1,它已由类A实现,并且设置了一些私有(private)变量值,并且我将类A的对象发送到下一个接受输入作为Interface2的类。那么我怎样才能将
假设我有这样的类和接口(interface)结构: interface IService {} interface IEmailService : IService { Task SendAs
有人知道我在哪里可以找到 XML-RPC 接口(interface)的定义(在 OpenERP 7 中)?我想知道创建或获取对象需要哪些参数和对象属性。每个元素的 XML 示例也将非常有帮助。 最佳答
最近,我一直在阅读有关接口(interface)是抽象的错误概念的文章。一篇这样的帖子是http://blog.ploeh.dk/2010/12/02/InterfacesAreNotAbstract
如果我有一个由第三方实现的现有 IInterface 后代,并且我想添加辅助例程,Delphi 是否提供了任何简单的方法来实现此目的,而无需手动重定向每个接口(interface)方法?也就是说,给定
我正在尝试将 Article 数组分配给我的 Mongoose 文档,但 Typescript 似乎不喜欢这样,我不知道为什么它显示此警告/错误,表明它不可分配. 我的 Mongoose 模式和接口(
我有两个接口(interface): public interface IController { void doSomething(IEntity thing); } public inte
是否可以创建一个扩展 Serializable 接口(interface)的接口(interface)? 如果是,那么扩展接口(interface)的行为是否会像 Serilizable 接口(int
我试图在两个存储之间创建一个中间层,它从存储 A 中获取数据,将其转换为相应类型的存储 B,然后存储它。由于我需要转换大约 50-100 种类型,我希望使用 map[string]func 并根据 s
我正在处理一个要求,其中我收到一个 JSON 对象,其中包含一个日期值作为字符串。我的任务是将 Date 对象存储在数据库中。 这种东西: {"start_date": "2019-05-29", "
我们的方法的目标是为我们现有的 DAO 和模型类引入接口(interface)。模型类由各种类型的资源 ID 标识,资源 ID 不仅仅是随机数,还带有语义和行为。因此,我们必须用对象而不是原始类型来表
Collection 接口(interface)有多个方法。 List 接口(interface)扩展了 Collection 接口(interface)。它声明与 Collection 接口(int
我有一个 Java 服务器应用程序,它使用 Jackson 使用反射 API 对 DTO 进行一般序列化。例如对于这个 DTO 接口(interface): package com.acme.libr
如果我在 Kotlin 中有一个接口(interface): interface KotlinInterface { val id: String } 我可以这样实现: class MyCla
我知道Java中所有访问修饰符之间的区别。然而,有人问了我一个非常有趣的问题,我很难找到答案:Java 中的 private 接口(interface)和 public 接口(interface)有什
我是一名优秀的程序员,十分优秀!