#定义从 C 到 C# 的转换
这是 C 代码吗:
/* LERP(a,b,c) = linear interpolation macro, is 'a' when c == 0.0 and 'b' when c == 1.0 */
#define LERP(a,b,c) (((b) - (a)) * (c) + (a))
http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_T。 html
等于这个 C# 代码吗?
private static double LERP(double a, double b, double c) { return (((b) - (a)) * (c) + (a)); }
?
Is this C code:
/* LERP(a,b,c) = linear interpolation macro, is 'a' when c == 0.0 and 'b' when c == 1.0 */
#define LERP(a,b,c) (((b) - (a)) * (c) + (a))
http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_T.html
Equals this C# code?
private static double LERP(double a, double b, double c) { return (((b) - (a)) * (c) + (a)); }
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不。
考虑以下内容:
LERP(x++,1,2);
C 代码还可能具有将 x 增加两次的副作用 [如 @phresnel 所述,它是未定义的],而 C# 代码则完美定义,并且只会增加 x 一次。
结果也可能不同,因为第一个
a
和第二个[在宏中]可能具有不同的值,因为第一个值可能会增加。no.
consider the following:
LERP(x++,1,2);
The c code might also have a side effect of increasing x twice [it is undefined as mentioned by @phresnel], while the c# code is perfectly defined, and will increase x only once.
the result also might be different, since the first
a
and the second one [in the macro] might have a different value, since it might have increased in the first one.不。C 变体具有
#define
-macros 的所有缺陷。提醒:潜在的性能浪费
想象一下
调用中的纯函数调用 >#define
-macro:该行扩展为:
现在,您的教师功能的两次调用的运行时间可能增加了一倍,而以前只有一次。
如果你嵌套你的 lerping,这肯定会变得更糟,例如在某些图形编程情况下很常见:
扩展为:
扩展为(为了可读性而调整格式):
而干净版本在计算上不超过:
或
所以在二维设置中
fac()
fac()
随着您添加的每个维度,情况会呈指数级恶化。有时甚至会看到五维柏林噪声(3d 体积 + 时间 + 连续种子),某些表达式被计算了 31 次,而不是一次!:
可以还可以通过调用
cpp
查看预处理代码(请注意之前probe()
的单一出现)。再次,完整源代码 在这里。
潜在的未定义行为
您可以将邪恶的东西放入其中:
它扩展为
C1 中的未定义行为(顺便说一句,在 C++ 中)。
a
可能会增加两次,或者可能会增加一次,或者可能会抛出异常,显示Debug-Runtime-Exception: Invoked Undefined Behaviour
,或者编译器是智能的足以拒绝该代码,或者其他什么。未定义的行为来自以下事实:C99 标准(以及 C++2003)不允许在到达下一个 序列点。
ID 污染和感染
(如果您将 C# 转换为宏变体,这会更相关。)
#define
-macro-name 会污染并感染从定义点到单元结尾或其未定义的整个翻译单元。更多...
一节已经暗示了这一点:C99 (ISO/IEC 9899:TC2),J.2,“未定义的行为”:
在两个序列点之间,对象被修改更多不止一次,或被修改并读取先前的值,而不是确定要存储的值(6.5)。
No. The C variant comes with all the deficiencies of
#define
-macros. Reminder:Potential Waste of Performance
Imagine a pure function call in an invokation of the
#define
-macro:That line expands to:
Now you have potentially doubled the runtime for two invokations of your faculty function that was perviously just one.
This surely gets worse if you nest your lerping, as is for instance common in some graphics programming situations:
Expanding to:
Expanding to (formatting tweaked for readability):
Whereas the clean version does computationally not more than:
or
So in a two dimensional setup
fac()
fac()
It gets exponentially worse with every dimension you'd add. Even five-dimensional Perlin Noise is sometimes seen (3d volume + time + continous seed), for which some expressions are evaluated freaking 31 times, instead of just once!:
You can also see the preprocessed code by invoking
cpp
(note the single appearance ofprobe()
before).Again, full source is here.
Potential Undefined Behaviour
You can put evil stuff into it:
which expands to
which is undefined behaviour in C¹ (and in C++, btw).
a
might be increased twice, or it might be increased once, or an exception might be thrown that saysDebug-Runtime-Exception: Invoked Undefined Behaviour
, or the compiler is smart enough to reject that code, or whatever.The undefined behaviour comes from the fact that the C99-standard (and C++2003, too) does not allow a value to be modified multiple times before reaching the next Sequence Point.
ID pollution and infection
(This is more relevant if you'd convert the C# into the macro variant.)
The
#define
-macro-name pollutes and infects the whole unit of translation from the point of definition to either the end-of-unit or its undefinition.More ...
¹: C99 (ISO/IEC 9899:TC2), J.2, "Undefined Behaviour":
Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored (6.5).
从技术上讲,不,它们并不相等。 C 宏可以采用任何类型:
int
、float
、byte
等。您的 C# 版本只能处理 double,而无需显式强制转换。您需要根据其他类型的需要添加重载。
Technically, no they are not equal. The C macro can take any type:
int
,float
,byte
, etc.Your C# version can only handle double, without explicit casts. You'd need to add overloads as needed for other types.
基本上是等价的,是的。您还可以去掉一些括号:
It's basically equivalent, yes. You can also get rid of some parentheses:
要获得 C 语言中的内容,您可以使用:
但我同意阿米特。这可能与您在 C 中的情况相同(但仅适用于 double,不适用于其他类型),但它可能不是您真正想要的..(使用委托,您可以将 'i++' 设置为 a,而不仅仅是 i++ 的结果)
To get what you had in C you may use:
But I agree with amit. This might be the same you had in C (but solely for double not for other types) still it might not be what you really want.. (with delegate you could set 'i++' as a, not only result of i++)
是的,但是你可以写得更简单:
Yes, but you can write it more simple: