C 可移植(主要是Linux和Windows)4字节提取/比较

C 可移植(主要是Linux和Windows)4字节提取/比较,c,types,portability,C,Types,Portability,大家好,C代码员 我先找了类似的问题,但没找到 如何以可移植的方式获取/比较4字节(当然没有memcpy/memcmp) 我从来没有学过C,正因为如此,我活生生地证明,如果不了解基本知识,一切都会变得一团糟。 无论如何,写单词(已经)不是说“从字母表开始”的时候 ulHashPattern = *(unsigned long *)(pbPattern); for (a=0; a < ASIZE; a++) bm_bc[a]=cbPattern; fo

大家好,C代码员

我先找了类似的问题,但没找到

如何以可移植的方式获取/比较4字节(当然没有memcpy/memcmp)

我从来没有学过C,正因为如此,我活生生地证明,如果不了解基本知识,一切都会变得一团糟。 无论如何,写单词(已经)不是说“从字母表开始”的时候

    ulHashPattern = *(unsigned long *)(pbPattern);
        for (a=0; a < ASIZE; a++) bm_bc[a]=cbPattern;
        for (j=0; j < cbPattern-1; j++) bm_bc[pbPattern[j]]=cbPattern-j-1;
        i=0;
        while (i <= cbTarget-cbPattern) {
            if ( *(unsigned long *)&pbTarget[i] == ulHashPattern ) {
2] 摘自MVS10.0stdint.h

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef _ULonglong uint64_t;
 #if defined(_STD_USING)
...
using _CSTD uint8_t; using _CSTD uint16_t;
using _CSTD uint32_t; using _CSTD uint64_t;
...
对于Microsoft C 32位,没有问题:

; 3401 :           if ( *(_CSTD uint32_t *)&pbTarget[i] == *(_CSTD uint32_t *)(pbPattern) )

  01360 8b 04 19     mov     eax, DWORD PTR [ecx+ebx]
  01363 8b 7c 24 14  mov     edi, DWORD PTR _pbPattern$GSCopy$[esp+1080]
  01367 3b 07        cmp     eax, DWORD PTR [edi]
  01369 75 2c        jne     SHORT $LN80@Railgun_Qu@6
但当64位是目标代码时,情况就是这样:

D:\_KAZE_Simplicius_Simplicissimus_Septupleton_r2-_strstr_SHORT-SHOWDOWN_r7>cl /Ox /Tcstrstr_SHORT-SHOWDOWN.c /Fastrstr_SHORT-SHOWDOWN /w /FAcs
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.30729.01 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

strstr_SHORT-SHOWDOWN.c
strstr_SHORT-SHOWDOWN.c(1925) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory

D:\_KAZE_Simplicius_Simplicissimus_Septupleton_r2-_strstr_SHORT-SHOWDOWN_r7>
Linux的stdint.h如何,它总是被呈现吗

我没有放弃并评论它:
/#include
,然后编译就可以了:

; 3401 :           if ( !memcmp(&pbTarget[i], &ulHashPattern, 4) ) 
  01766 49 63 c4     movsxd  rax, r12d
  01769 42 39 2c 10  cmp     DWORD PTR [rax+r10], ebp
  0176d 75 38        jne     SHORT $LN1@Railgun_Qu@6

; 3401 :           if ( *(unsigned long *)&pbTarget[i] == ulHashPattern ) 
  01766 49 63 c4     movsxd  rax, r12d
  01769 42 39 2c 10  cmp     DWORD PTR [rax+r10], ebp
  0176d 75 38        jne     SHORT $LN1@Railgun_Qu@6
这个“unsigned long*”让我很烦恼,因为gcc-m64将获取一个QWORD而不是DWORD,对吗

@神秘的
只是想展示微软CL 32位v16所做的三种不同的翻译:
1]

2]

3]

最初的目标是提取(分别使用单个mov指令*(uint32_t*)和pbTarget[i]),并比较4bytes与寄存器变量4bytes的长度,即一条指令中的一个RAM访问一个比较。 幸亏有了内联,我才设法将memcmp()的3次RAM访问(应用于指向4个或更多字节的pbPattern)减少到2次。 现在,如果我想在pbPattern的前4个字节上使用memcmp()(如图2所示),ulHashPattern不应该是register类型,而3]不需要这样的限制

; 3400 :           if ( !memcmp(&pbTarget[i], &ulHashPattern, 4) )
上面的行给出了一个错误(ulHashPattern定义为:register unsigned long ulHashPattern;):

是的,你是对的:memcmp()保存了这种情况(但有一个限制)-片段2]与片段3]相同。 显然,我倾向于不使用手动编码的函数,但我喜欢它


我仍然不完全满意编译器,我已经将ulHashPattern定义为一个寄存器变量,但每次都是从RAM加载的?!也许我错过了一些东西,但这一行(mov eax,DWORD PTR _ulHashPattern$[esp+1076])会降低性能——在我看来,这是一段难看的代码。

严格说来,你只能使用
char
。这是因为您使用以下类型的双关语:

*(unsigned long *)(pbPattern);
*(unsigned long *)&pbTarget[i]
char*
是此规则的唯一例外,因为您可以使用
char*
别名任何数据类型

如果您在GCC上显示警告,您的代码段应该会收到严格的别名警告。(好吧,MSVC不会警告严格的别名。)


我不能确切地告诉您在该代码段中要做什么,但这个想法仍然成立,您不应该使用
unsigned long
或任何其他数据类型来加载和比较不同类型的较大数据块

实际上,您确实应该使用
memcmp()
,因为这很简单,可以让您绕过将所有内容强制转换为
char*
的低效性

有什么原因不能使用
memcmp()



如果您同意违反严格别名,则可以使用
中定义的固定整数类型(如
uint32\u t
)。但是,请注意,它们是固定在位的#而不是字节的#上的。

查看uint64及其对应项,在stdint中定义。汉克斯·理查德·罗斯三世(Hanks Richard J.Ross III),我会(回家后)寻找对应项,可能是因为它们在stdint中。h会使它们便于携带,对吗?谢谢你的帮助,哈哈,如果你知道我生产了多少,他们应该叫我朋曼。我担心我的编码风格是如此违反(不仅仅是在严格的别名方面)。至于你的问题:memcmp()是毫无疑问的,因为我想要速度,事实上,这个4vs4比较是内联memcmp()的开始。同意,但在这种情况下,经过多次尝试和错误(以及许多基准测试),我想出了一个比memcmp更快的代码:啊,如果你已经(正确地)对它进行了基准测试,那就好了。当然有可能比编译器做得更好。尽管只需发出
memcpy()
通常更安全、可读性更强。看到我的答案了。还有,我的一个很大的障碍是:尽管我对开源操作系统和工具有着良好的感觉,但我仍然在使用Windows,因此我在Linux和GCC方面几乎没有经验,抱怨道。同样,我仍然使用Windows作为主要工具。但是当我需要的时候,我会双引导Linux。但是,是的,我从未见过任何Windows编译器生成严格的别名警告。所以我可以看到你是怎么进入这种情况的。尽管到目前为止,我唯一一次看到严格的别名冲突实际上导致了不希望的行为是在与内联程序集混合时。
; 3401 :           if ( *(uint32_t *)&pbTarget[i] == ulHashPattern )
  01350 8b 44 24 14  mov     eax, DWORD PTR _ulHashPattern$[esp+1076]
  01354 39 04 2a     cmp     DWORD PTR [edx+ebp], eax
  01357 75 2e        jne     SHORT $LN79@Railgun_Qu@6
; 3400 :           if ( !memcmp(&pbTarget[i], &ulHashPattern, 4) )
strstr_SHORT-SHOWDOWN.c(3400) : error C2103: '&' on register variable
*(unsigned long *)(pbPattern);
*(unsigned long *)&pbTarget[i]