我正在尝试使用以下公式制作一个宏:(a^2/(a+b))*b
,我想确保没有除以零。
#define SUM_A( x, y ) if( x == 0 || y == 0) { 0 } else { ( ( ( x * x ) / ( ( x ) + ( y ) ) ) * ( y ) )}
然后我在main中调用宏:
float a = 40, b = 10, result;
result = SUM_A(a, b);
printf("%f", result);
我尝试在if函数周围使用括号,但我在if语句之前一直遇到语法错误。我也尝试过使用return,但我在某处读到你不应该在define中使用它。
答案 0 :(得分:21)
您不能使用if语句,因为#define
由预处理器解释,输出将是
result=if( x == 0 || y == 0) { 0 } else { ( ( ( x * x ) / ( ( x ) + ( y ) ) ) * ( y ) )}
这是错误的语法。
但另一种方法是使用三元运算符。将您的定义更改为
#define SUM_A( x, y ) ((x) == 0 || (y) == 0 ? 0 : ( ( ( (x) * (x) ) / ( ( x ) + ( y ) ) ) * ( y ) ))
请记住始终将您的定义放在括号之间,以避免在替换时出现语法错误。
答案 1 :(得分:6)
if
引入了一个陈述,而不是一个表达。使用“三元”(条件)运算符:
#define SUM_A(x, y) (((x) == 0 || (y) == 0)? 0: ((((x) * (x)) / ((x) + (y))) * (y)))
或者,将其设为inline
函数:
inline float sum_a(float x, float y)
{
if (x == 0 || y == 0)
return 0;
else
return ((x * x) / (x + y)) * y;
}
这避免了对x
和/或y
进行多次评估的问题,并且更具可读性,但它确实修复了x
和y
的类型。您也可以删除inline
并让编译器决定是否值得内联此函数(inline
不保证它将执行内联)。
答案 2 :(得分:4)
从技术上讲,可以在if
中使用#define
语句(但不是您期望的方式)。由于#define
只是文本替换,因此您必须非常小心如何扩展它。我发现这个有用......
#define SUM_A(x, y) \
({ \
double answer; \
if ((x) == 0 || (y) == 0) \
answer = 0; \
else \
answer = ((double)((x)*(x)) / ((x)+(y))) * (y); \
(answer); \
})
// Typecasting to double necessary, since int/int == int in C
这应该会为您提供您正在寻找的结果,并且没有理由不能将其扩展为包含多个else if
(尽管其他答案也是如此)指出,使用三元运算符可能更容易。)
答案 3 :(得分:1)
问题是if
语句不是表达式,并且不返回值。此外,在这种情况下没有充分的理由使用宏。实际上,它可能会导致非常严重的性能问题(取决于您作为宏参数传递的内容)。你应该使用一个函数。
答案 4 :(得分:1)
您的宏存在多个问题:
它会扩展为语句,因此您无法将其用作表达式
参数在扩展中没有正确括号:使用除变量名或常量之外的任何内容调用此宏都会产生问题。
多次计算参数:如果调用带有副作用的宏,例如SUM_A(a(), b())
或SUM_A(*p++, 2)
,副作用将多次出现。
要避免所有这些问题,请使用可能定义为static inline
的函数来帮助编译器优化更多(这是可选的,现代编译器会自动执行此操作):
static inline int SUM_A(float x, float y) {
if (x == 0 || y == 0)
return 0;
else
return x * x / (x + y) * y;
}
注意:
答案 5 :(得分:0)
是的,您可以在宏中使用if语句。您需要正确格式化。这是一个例子:
#define MY_FUNCTION( x ) if( x ) { PRINT("TRUE"); } else { PRINT("FALSE"); }
答案 6 :(得分:0)
我使用具有一定条件的宏,并且确实有合法用途。
我有一些本质上是斑点的结构,一切都只是一个uint8_t流。
为了使内部结构更具可读性,我有条件宏。
示例...
#define MAX_NODES 10
#define _CVAL16(x)(((x) <= 127) ? (x) : ((((x) & 127) | 0x80) ), ((x) >> 7)) // 1 or 2 bytes emitted <= 127 = 1 otherwise 2
现在可以在数组内使用宏了...
uint8_t arr_cvals[] = { _CVAL16(MAX_NODES), _CVAL16(345) };
在数组中发出三个字节,第一个宏发出1,第二个宏发出2。这是在编译时评估的,只是使代码更具可读性。
我也有...例如...
#define _VAL16(x) ((x) & 255), (((x) >> 8) & 255)
对于最初的问题...也许这个人想将结果与常量一起使用,但实际上还是要归结到使用它的位置和方式。
#define SUM_A(x, y) (!(x) || !(y)) ? 0 : ((x) * (x) / ((x) + (y)) * (y))
float arr_f[] = { SUM_A(0.5f, 0.55f), SUM_A(0.0f, -1.0f), SUM_A(1.0f, 0.0f) };
在运行时可以拥有...
float x;
float y;
float res = SUM_A(x,y); // note ; on the end
我有一个程序来创建字体,这些字体被包含在C程序的代码中,并且大多数值都被包裹在宏中,这些宏将32位值分成4个字节,浮点为4个字节,等等。
答案 7 :(得分:0)
您可以将条件语句转换为简单表达式。条件评估为@SuppressWarnings("unchecked")
ArrayList<Map<String, Object>> items = (ArrayList<Map<String, Object>>) value;
或0
1
根据您的具体情况
// pseudo-code
// if (<something>) { 0; } else { 42; }
// if (!<something>) { 42; } else { 0; }
// !<something> * 42;