c - 有没有办法避免多个类似功能中的代码重复?
问题描述
我正在编写一系列函数,这些函数将嵌入一个几乎实时运行的小型微控制器中,因此每个时钟周期都很重要。功能几乎相同。
我可以看到在不复制大量代码的情况下做到这一点的唯一方法是使用非常丑陋且不赞成在包含文件中声明代码的方法,然后有意包含多次。
以下作品展示了这个概念:
// func.inc
// The absence of an include guard is intentional, as each time this file gets included
// the output will be different
void FUNC(int x)
{
/* SNIP - lots and lots of code that is duplicated between
variant A and B (and more) of the function
for ( ... 4096 )
{
for( lots more nested loops)
{
*/
// IMPORTANT - I do not want to call functions here as it is
// in a tight loop withconsecutive memory accesses of
// different sizes of strided sparse arrays
#ifdef A
printf("A %d\n", x);
#endif
#ifdef B
printf("B %d\n", x);
#endif
/*
}
}
*/
// main.c
#include <stdio.h>
#define FUNC func_A
#define A
#include "func.inc"
#undef A
#undef FUNC
#define FUNC func_B
#define B
#include "func.inc"
#undef B
#undef FUNC
#define FUNC func_AB
#define A
#define B
#include "func.inc"
int main()
{
func_A(10);
func_B(20);
func_AB(30);
printf("Done\n");
return 0;
}
我的问题是,虽然这可行,但它看起来很可怕,并且可能会让其他试图理解它的人感到非常困惑。在这种情况下,使用指向函数的指针效率太低,不能成为可行的选择。
是否有任何人都可以建议的解决方案,而无需简单地复制同一功能的几个略有不同的版本?
解决方案
这里并不清楚什么是伪代码和真实代码,但总体而言,您不应该将++#define
用于不同的代码生成目的。(尽管作为最后的手段,您可以使用“X 宏”来做到这一点。这不是一个理想的解决方案,但比这更好。)#undef
#include
“重要 - 我不想在这里调用函数”的解决方案是调用函数。
函数内联已经存在了大约 30 年,而 20 年前,C 得到了明确的语言支持。现在编译器比程序员更能确定内联的内容。我将做一个明确的例子inline
来证明调用函数不会影响性能,如果正确完成。
使用传统的 C,你会做这样的事情:
#include <stdio.h>
static inline void SNIP (void)
{
puts(__func__);
}
static inline void A_stuff (int val)
{
printf("%s %d\n", __func__, val);
}
static inline void B_stuff (int val)
{
printf("%s %d\n", __func__, val);
}
typedef enum { A=1, B=2 } AB_t;
void func(AB_t ab, int val)
{
SNIP();
if(ab & A)
A_stuff(val);
if(ab & B)
B_stuff(val);
}
int main()
{
func(A, 10);
func(B, 20);
func(A|B, 30);
printf("Done\n");
return 0;
}
这是理智的解决方案。在生成的机器代码中实际调用的唯一函数是func
打印函数。
或者,您也可以使用“X 宏”进行代码生成 - 这些仅出于避免代码重复的目的而存在,以牺牲可读性为代价。在这里不会真的推荐它,但我会包括一个完整的例子:
#include <stdio.h>
#define FUNC_LIST \
X(A, 10) \
X(B, 20) \
X(AB, 30) \
static inline void SNIP (void)
{
puts(__func__);
}
static inline void A_stuff (int val)
{
printf("%s %d\n", __func__, val);
}
static inline void B_stuff (int val)
{
printf("%s %d\n", __func__, val);
}
static inline void AB_stuff (int val)
{
A_stuff(val);
B_stuff(val);
}
#define X(opt, val) void func_##opt (int x) { SNIP(); opt##_stuff(x); }
FUNC_LIST
#undef X
int main()
{
#define X(opt, val) func_##opt(val),
FUNC_LIST
#undef X
printf("Done\n");
return 0;
}
就像原始代码一样,这很不可读,除了“X 宏”是用于避免代码重复的 icky 宏技巧的事实上的标准。
这会像 C++ 模板一样创建多个函数,因此也不理想。
推荐阅读
- c# - C# EFCORE 在 SQLITE 中使用两个主键(复合键)
- python - 尝试在 Django 中创建以下关系时出现 ValueError
- ffmpeg - 以 MPEG-dash 格式更改最大缓冲区长度
- mql4 - 使用 mql4 语言编码支持/阻力
- python - 在 Google Cloud App Engine 上部署 RAM 密集型应用程序?
- c# - 基于索引顺序合并行 U-SQL
- javascript - 为什么 .text() 和 .html() 不能与cheerio js 和 node-fetch 一起使用?
- docker - 如何使用在同一个docker文件中的docker文件中创建的可执行文件
- python - 散点图不访问 y 值数据(Python)
- azure - Azure Pipeline 中的 Shell 脚本中的 Curl 命令不起作用