C - 函数参数和 "<<"运算符

标签 c function operators constants

我很抱歉标题不够具体,但我不知道它是怎么称呼的。这是我的问题:在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/

相关文章:

c - 在C中如何将函数作为参数传递?

function - 为什么 'fputc' 使用 INT 作为参数而不是 CHAR?

java - && 和 || while循环中的问题

使用 fork() 进行 C 系统编程

c - 如何将 R 字符 vector 转换为 C 字符指针?

c - int *a[5] 是一个包含 5 个指针的数组还是一个指向大小为 5 的数组的指针?

Javascript 函数未链接到下一个函数

c - 函数名称前的星号是什么意思?

c++ - 预减运算符

Conio.h 无法在代码块中工作(对 .. 的 undefined reference )