我可以缩短我重复使用的函数名称吗?
Can I shorten a function name I use repeatedly?
我有一个很长的公式,如下所示:
float a = sin(b)*cos(c)+sin(c+d)*sin(d)....
有没有办法在C语言中使用s
代替sin
来缩短公式,而不影响运行时间?
if I use define, does it affect runtime?
define
通过在编译时进行基于文本的替换来工作。如果您 #define s(x) sin(x)
那么 C 预处理器将在编译器有机会查看它之前将所有 s(x)
重写为 sin(x)
。
顺便说一句,这种低级文本修改正是 define 用于更复杂表达式的危险所在。例如,一个典型的陷阱是,如果您执行类似 #define times(x, y) x*y
的操作,则 times(1+1,2)
将重写为 1+1*2
,其计算结果为 3
而不是预期的 4
。对于更复杂的表达式,使用 inlineable functions 通常是个好主意。
对于sin
使用s
至少有三个选项:
使用预处理器宏:
#define s(x) (sin(x))
#define c(x) (cos(x))
float a = s(b)*c(c)+s(c+d)*c(d)....
#undef c
#undef s
请注意,#undef
会立即删除宏定义,以防止它们影响后续代码。此外,您应该了解预处理器宏替换的基础知识,注意 c(c)
中的第一个 c
将被扩展但第二个 c
不会扩展的事实,因为类函数宏c(x)
仅在 c
后跟 (
的情况下展开。
此解决方案对 运行 时间没有影响。
使用内联函数:
static inline double s(double x) { return sin(x); }
static inline double c(double x) { return cos(x); }
使用好的编译器,这对 运行 时间没有影响,因为编译器应该用直接调用 [=14] 替换对 s
或 c
的调用=]或cos
,结果与原代码相同。不幸的是,在这种情况下,c
函数将与您在示例代码中显示的 c
对象发生冲突。您将需要更改其中一个名称。
使用函数指针:
static double (* const s)(double) = sin;
static double (* const c)(double) = cos;
使用好的编译器,这对 运行 时间也没有影响,尽管我怀疑与以前的解决方案相比,使用此解决方案的编译器可能无法优化代码。同样,您的名称将与 c
冲突。请注意,使用函数指针会创建对 sin
和 cos
函数的直接调用,绕过 C 实现可能为它们定义的任何宏。 (允许 C 实现使用宏和函数来实现库函数,它们可能这样做是为了支持优化或某些特性。使用高质量的编译器,这通常是一个小问题;直接调用的优化仍然应该很好.)
不要这样做。
数学家们已经将三角函数缩写为 sin, cos, tan, sinh、cosh 和 tanh 很多很多年了。尽管数学家(像我一样)喜欢使用他们最喜欢的并且通常是特殊的符号,因此将任何论文都膨胀了好几页,但这些已经成为相当标准的。甚至 LaTeX 也有像 \sin
、\cos
和 \tan
.
这样的命令
日本人在 1970 年代发布科学计算器时使这些缩写不朽(shorthand 可以很容易地放在一个按钮上),C 标准库也采用了它们。
如果偏离这一点,那么您的代码会立即变得难以阅读。这对于数学代码尤其有害,因为您无法立即看到错误实现的影响。
但是如果你必须,那么一个简单的
static double(*const s)(double) = sin;
就够了。
我有一个很长的公式,如下所示:
float a = sin(b)*cos(c)+sin(c+d)*sin(d)....
有没有办法在C语言中使用s
代替sin
来缩短公式,而不影响运行时间?
if I use define, does it affect runtime?
define
通过在编译时进行基于文本的替换来工作。如果您 #define s(x) sin(x)
那么 C 预处理器将在编译器有机会查看它之前将所有 s(x)
重写为 sin(x)
。
顺便说一句,这种低级文本修改正是 define 用于更复杂表达式的危险所在。例如,一个典型的陷阱是,如果您执行类似 #define times(x, y) x*y
的操作,则 times(1+1,2)
将重写为 1+1*2
,其计算结果为 3
而不是预期的 4
。对于更复杂的表达式,使用 inlineable functions 通常是个好主意。
对于sin
使用s
至少有三个选项:
使用预处理器宏:
#define s(x) (sin(x))
#define c(x) (cos(x))
float a = s(b)*c(c)+s(c+d)*c(d)....
#undef c
#undef s
请注意,#undef
会立即删除宏定义,以防止它们影响后续代码。此外,您应该了解预处理器宏替换的基础知识,注意 c(c)
中的第一个 c
将被扩展但第二个 c
不会扩展的事实,因为类函数宏c(x)
仅在 c
后跟 (
的情况下展开。
此解决方案对 运行 时间没有影响。
使用内联函数:
static inline double s(double x) { return sin(x); }
static inline double c(double x) { return cos(x); }
使用好的编译器,这对 运行 时间没有影响,因为编译器应该用直接调用 [=14] 替换对 s
或 c
的调用=]或cos
,结果与原代码相同。不幸的是,在这种情况下,c
函数将与您在示例代码中显示的 c
对象发生冲突。您将需要更改其中一个名称。
使用函数指针:
static double (* const s)(double) = sin;
static double (* const c)(double) = cos;
使用好的编译器,这对 运行 时间也没有影响,尽管我怀疑与以前的解决方案相比,使用此解决方案的编译器可能无法优化代码。同样,您的名称将与 c
冲突。请注意,使用函数指针会创建对 sin
和 cos
函数的直接调用,绕过 C 实现可能为它们定义的任何宏。 (允许 C 实现使用宏和函数来实现库函数,它们可能这样做是为了支持优化或某些特性。使用高质量的编译器,这通常是一个小问题;直接调用的优化仍然应该很好.)
不要这样做。
数学家们已经将三角函数缩写为 sin, cos, tan, sinh、cosh 和 tanh 很多很多年了。尽管数学家(像我一样)喜欢使用他们最喜欢的并且通常是特殊的符号,因此将任何论文都膨胀了好几页,但这些已经成为相当标准的。甚至 LaTeX 也有像 \sin
、\cos
和 \tan
.
日本人在 1970 年代发布科学计算器时使这些缩写不朽(shorthand 可以很容易地放在一个按钮上),C 标准库也采用了它们。
如果偏离这一点,那么您的代码会立即变得难以阅读。这对于数学代码尤其有害,因为您无法立即看到错误实现的影响。
但是如果你必须,那么一个简单的
static double(*const s)(double) = sin;
就够了。