我很抱歉标题不够具体,但我不知道它是怎么称呼的。这是我的问题:在this代码片段,有这样定义的常量:
#define WS_NONE 0
#define WS_RECURSIVE (1 << 0)
#define WS_DEFAULT WS_RECURSIVE
#define WS_FOLLOWLINK (1 << 1) /* follow symlinks */
#define WS_DOTFILES (1 << 2) /* per unix convention, .file is hidden */
#define WS_MATCHDIRS (1 << 3) /* if pattern is used on dir names too */
并且有一个这样定义的函数:
int walk_recur(char *dname, regex_t *reg, int spec)
他将常量(WS_DEFAULT 和 WS_MATCHDIRS)发送到使用“|”的函数:
walk_dir(".", ".\\.c$", WS_DEFAULT|WS_MATCHDIRS);
他是这样使用参数的:
if ((spec & WS_RECURSIVE))
walk_recur(fn, reg, spec);
if (!(spec & WS_MATCHDIRS)) continue;
如果 WS_RECURSIVE 传递给函数,第一个 if 语句将为真。我不明白 << 运算符如何工作以及 (spec & WS_RECURSIVE) 语句如何返回 true。他怎么能用“|”发送不同的常量呢?他可以使用“spec”值,该值必须等于传递的常量,这怎么可能?
抱歉我的英语不好。
最佳答案
将单个整数值视为单个位的集合是一种非常常见的习惯用法。 C 不直接支持位数组,因此我们使用按位运算符来设置和清除位。
<<
运算符是左移运算符。例如:
1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
1 << n
对于任何非负 n
(在范围内)是 2 的幂。整数值中的每一位代表 2 的幂。任何整数值都可以被视为 唯一 2 的幂和。
|
是按位或运算符;它用于将多个 1 位值(1 的幂)组合成一个整数值:
(1 << 0) | (1 << 3) == 1 | 8
1 | 8 == 9
这里我们将位零(表示值 1
)和位三(表示值 8
)组合成一个值 9
. (在这种情况下,我们可以使用 +
而不是 |
,但通常使用 |
可以避免多次给出 2 的某个幂时出现问题。)
现在我们可以使用位与运算符测试是否设置了一个位&
:
int n = (1<<0) | (1<<3);
if (n & (1<<3)) {
printf("Bit 3 is set\n");
}
else {
printf("Bit 3 is not set\n");
}
现在我们可以定义宏了,这样我们就不用写1<<0
了。和 1<<3
到处都是:
#define WS_RECURSIVE (1 << 0)
...
#define WS_MATCHDIRS (1 << 3)
int n = WS_RECURSIVE | WS_MATCHDIRS;
// n == 9
if (n & WS_RECURSIVE) {
// the WS_RECURSIVE bit is set
}
if (!(n&WS_MATCHDIRS) {
// the WS_MATCHDIRS bit is *not* set
}
您还可以定义宏来简化设置和测试位(SET_BIT()
、IS_SET()
等),但大多数 C 程序员不会费心这样做。位值的符号名称对于代码的可读性很重要,但是一旦您理解了按位运算符的工作原理,更重要的是了解了设置、清除和测试位的常用习语是如何编写的,原始运算符就足够可读了。
通常使用无符号整数类型比有符号整数类型更好;在某些情况下,带符号类型的按位运算符的行为可能很棘手。
关于C - 函数参数和 "<<"运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24898536/