gpt4 book ai didi

C 宏问题 -(x) vs (-x)

转载 作者:太空狗 更新时间:2023-10-29 16:25:43 26 4
gpt4 key购买 nike

我正在阅读教授的测验答案,其中一个问题是:

像宏这样的绝对值函数的正确实现是:

#define abs(x) ((x)<0 ? (-x) : (x))
#define abs(x) ((x)<0 ? -(x) : (x))

为什么第二个比第一个正确?

还有为什么要全部使用()。比如涉及什么规则?每个变量都需要一个()?谢谢。

最佳答案

额外的括号解决了各种相关问题。我将一一介绍:

尝试:int y = abs( a ) + 2

假设您使用:

#define abs(x)  (x<0)?-x:x
...
int y = abs( a ) + 2

扩展为 int y = (a<0)?-a:a+2 . +2仅绑定(bind)到错误结果。 2 只在 a 为正时才加,为负时不加。所以我们需要用括号括起来:

#define abs(x)  ( (x<0) ? -x : x )

尝试:int y = abs(a+b);

但是我们可能会得到 int y = abs(a+b)扩展为 int y = ( (a+b<0) ? -a+b : a+b) .如果 a + b 是负数,那么当他们为结果相加时 b 不会被否定。所以我们需要把 x-x括号内。

#define abs(x)  ( (x<0) ? -(x) : x )

尝试:int y = abs(a=b);

这应该是合法的(虽然不好),但它扩展到 int y = ( (a=b<0)?-(a=b):a=b );它试图将最后的 b 分配给三元组。这不应该编译。 (请注意,它在 C++ 中确实如此。我必须使用 gcc 而不是 g++ 来编译它,才能看到它无法编译并出现“赋值中的左值无效”错误。)

#define abs(x)  ( (x<0) ? -(x) : (x) )

尝试:int y = abs((a<b)?a:b);

扩展为 int y = ( ((a<b)?a:b<0) ? -((a<b)?a:b) : (a<b)?a:b ) , 将 <0 分组与 b,而不是预期的整个三元组。

#define abs(x)  ( ( (x) < 0) ? -(x) : (x) )

最后,x 的每个实例容易出现一些需要括号解决的分组问题。

常见问题:运算符优先级

所有这些的共同点是 operator precedence : 如果你在你的 abs(...) 中放置一个运算符优先级低于 where x 附近的调用在宏中使用,那么它将错误地绑定(bind)。例如,abs(a=b)将扩展为 a=b<0a=(b<0) 相同...这不是来电者的意思。

实现的“正确方法”abs

当然,无论如何这是实现 abs 的错误方法...如果您不想使用内置函数(您应该这样做,因为它们会针对您移植到的任何硬件进行优化),那么它应该是一个内联模板(如果使用 C++),原因与 Meyers,Sutter 时提到的相同。 , 等人讨论了重新实现 min 和 max 函数。 (其他答案也提到了:abs(x++) 会发生什么?)

在我的脑海中,一个合理的实现可能是:

template<typename T> inline const T abs(T const & x)
{
return ( x<0 ) ? -x : x;
}

这里可以省略括号,因为我们知道 x 是单个值,而不是宏的任意扩展。

更好的是,正如 Chris Lutz 在下面的评论中指出的那样,您可以使用模板特化来调用优化版本(abs、fabs、labs)并获得类型安全、对非内置类型的支持以及性能。

测试代码

#if 0
gcc $0 -g -ansi -std=c99 -o exe && ./exe
exit
#endif




#include <stdio.h>

#define abs1(x) (x<0)?-x:x
#define abs2(x) ((x<0)?-x:x)
#define abs3(x) ((x<0)?-(x):x)
#define abs4(x) ((x<0)?-(x):(x))
#define abs5(x) (((x)<0)?-(x):(x))


#define test(x) printf("//%30s=%d\n", #x, x);
#define testt(t,x) printf("//%15s%15s=%d\n", t, #x, x);

int main()
{
test(abs1( 1)+2)
test(abs1(-1)+2)
// abs1( 1)+2=3
// abs1(-1)+2=1

test(abs2( 1+2))
test(abs2(-1-2))
// abs2( 1+2)=3
// abs2(-1-2)=-1

int a,b;
//b = 1; testt("b= 1; ", abs3(a=b))
//b = -1; testt("b=-1; ", abs3(a=b))
// When compiled with -ansi -std=c99 options, this gives the errors:
//./so1a.c: In function 'main':
//./so1a.c:34: error: invalid lvalue in assignment
//./so1a.c:35: error: invalid lvalue in assignment

// Abs of the smaller of a and b. Should be one or two.
a=1; b=2; testt("a=1; b=2; ", abs4((a<b)?a:b))
a=2; b=1; testt("a=2; b=1; ", abs4((a<b)?a:b))
// abs4((a<b)?a:b)=-1
// abs4((a<b)?a:b)=1


test(abs5( 1)+2)
test(abs5(-1)+2)
test(abs5( 1+2))
test(abs5(-1-2))
b = 1; testt("b= 1; ", abs5(a=b))
b = -1; testt("b=-1; ", abs5(a=b))
a=1; b=2; testt("a=1; b=2; ", abs5((a<b)?a:b))
a=2; b=1; testt("a=2; b=1; ", abs5((a<b)?a:b))
}

输出

                    abs1( 1)+2=3
abs1(-1)+2=1
abs2( 1+2)=3
abs2(-1-2)=-1
a=1; b=2; abs4((a<b)?a:b)=-1
a=2; b=1; abs4((a<b)?a:b)=1
abs5( 1)+2=3
abs5(-1)+2=3
abs5( 1+2)=3
abs5(-1-2)=3
b= 1; abs5(a=b)=1
b=-1; abs5(a=b)=1
a=1; b=2; abs5((a<b)?a:b)=1
a=2; b=1; abs5((a<b)?a:b)=1

关于C 宏问题 -(x) vs (-x),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2025372/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com