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
。
您只能对整数类型进行右移和左移(char
、int
、
long
,等等)。浮点数 (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)
+---+---+---+---+---+---+---+---+
我对在 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
。
您只能对整数类型进行右移和左移(char
、int
、
long
,等等)。浮点数 (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)
+---+---+---+---+---+---+---+---+