C中如何判断保留标识符的数据类型

how to determine the data type of reserved identifier in C

我对在 C 中使用一些高级概念还比较陌生。我正在尝试理解使用 _>><< 的 API 中的代码.我理解 _ 用作保留标识符,>> 用于按位右移,<< 用于按位左移。

但我想知道的是我们如何知道 OFFSET_AND_ROUND2 接受什么数据类型参数?以及该函数如何以及为什么对偏移和舍入进行按位运算?最后,为什么我收到无效操作数错误?

请查找以下代码:

#include <stdio.h>
#define OFFSET_AND_ROUND2(_a, _b) (((_a)+(1<<((_b)-1))-((_a)<0?1:0))>>(_b))

int main()
{
    printf("Hello World\n\n");
    printf("%d", OFFSET_AND_ROUND2(3.87,2));
    return 0;
}

请在下面找到错误消息:

main.c:10:69: error: invalid operands to binary >> (have 'double' and 'int')


#define OFFSET_AND_ROUND2(_a, _b) (((_a)+(1<<((_b)-1))-((_a)<0?1:0))>>(_b))
                                                                     ^
main.c:15:18: note: in expansion of macro 'OFFSET_AND_ROUND2'
     printf("%d", OFFSET_AND_ROUND2(3.87,2));
                  ^

我期待更多地了解 C,谢谢!

使用宏时,预处理器获取宏的内容并替换每次出现的内容。 例如:

#define A 5
...
int a = A;

翻译成

int a = 5;

参数也一样:

#define A(_a) (_a+1)
...
int a = A(2);

被翻译成

int a = (2+1);

最后,使用哪种数据类型并不重要,只要它们支持所有需要的操作即可。 错误是因为你不能在 c++

中移动 floats/doubles

因为它的工作方式类似于搜索和替换,所以在必要时使用括号非常重要:

#define ADD(_a,_b) _a+_b
...
int a = ADD(5,4) * 3;

被翻译成

int a = 5+4 * 3 // = 5 + (4 * 3) = 17

而 (5+4)*3 = 27

But what I am wondering is how do we know what data type argument does OFFSET_AND_ROUND2 accepts?

这就是宏的问题之一。如果没有文档 明确告诉您输入和输出数据类型,然后您 查看宏是如何声明的。取决于您对 C 的了解以及 宏的复杂性,这很难猜测。这是最主要的原因之一 经验丰富的用户告诉经验最少的用户 "don't user macros".

在这种情况下,宏正在执行位操作和加减法。 结果类型将取决于输入的类型。如果 int 输入,结果将是 int.

关于错误:

main.c:10:69: error: invalid operands to binary >> (have 'double' and 'int')

此处 gcc 告诉您您已经为二进制右移 >> 运算符传递了 double。 您只能对整数类型进行右移和左移(charintlong,等等)。浮点数 (float, double) 都不允许 运营商的一面。

所以正确的调用应该是

printf("%d", OFFSET_AND_ROUND2(3,2));

如果你不知道移位是什么,左移位将位模式移动到 左边,用 0 填充 "new" 位。右移做同样的事情,但是从 正确的。假设您有一个值为 0x13 的字节(十进制为 19)

操作char x = 0x13; char y = x << 2将移位 变量向左太多次,结果会存入y.

  msb = most significant bit
  lsb = least significant bit

  msb                             lsb
  +---+---+---+---+---+---+---+---+
  | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 |    == 19 (decimal)
  +---+---+---+---+---+---+---+---+

  x << 2

  msb                             lsb
  +---+---+---+---+---+---+---+---+
  | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |    == 76 (decimal)
  +---+---+---+---+---+---+---+---+