检测32位或64位中一个字节的ascii字符

检测32位或64位中一个字节的ascii字符,c,null,bit-manipulation,byte,ascii,C,Null,Bit Manipulation,Byte,Ascii,当我想用C编写一个更快的strlen时(比逐字节检查的要快),我发现了这个宏: #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) 此宏读取4个字节,并在找到至少一个NUL字节时返回(1)。 否则返回(0) 我想知道是否可以使用相同的技术来查找ascii表的任何字符(我不喜欢使用逐字节循环) 我尝试了很多组合,我能做的最好的是: // in this example I wanted to find a

当我想用C编写一个更快的strlen时(比逐字节检查的要快),我发现了这个宏:

#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
此宏读取4个字节,并在找到至少一个NUL字节时返回(1)。 否则返回(0)

我想知道是否可以使用相同的技术来查找ascii表的任何字符(我不喜欢使用逐字节循环)

我尝试了很多组合,我能做的最好的是:

// in this example I wanted to find a '#'

int32_t detectsharp(int32_t c) {
    c = ~(c - 0x24242424) & ~c;
    return ((c - 0x01010101) & ~c & 0x80808080);
}

但它不适用于
0x2222222
)或类似于
0x24212121
$!
)的东西。

它可以检测任何字符,如果您以前将其与int进行异或运算

#define DETECTCHAR(x,c) (DETECTNULL((x) ^ ((c)*0x01010101l) ))

乘法将字符分配到int的4个字节中,异或清除字符所在的字节。

但是,如果使用
0x2323
对int进行异或,然后再次尝试检测零字节,则应该可以工作。这应该能检测到尖锐的声音。与所有其他字符类似。您应该使用
uint32\u t
而不是
int32\u t
。请注意,SIMD比这样的技巧快得多。看见您最好将此工作留给标准库,如果可能,标准库将使用SIMD。您可能希望将
c
转换为
(unsigned char)(c)
,以避免在默认为
char
签名的平台上出现负字符问题。另外,
l
后缀是可选的,并且在
l
时可读性更好。