首先看了像我这样的类似问题我找不到.
如何以便携方式获取/比较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 ) {
上面的片段在windows 32bit编译器上必须工作.我的愿望是所有这样的4vs4比较,以便在64位windows和linux下工作.
很多时候我需要2,4,8个字节的传输,在上面的例子中,我需要从一些pbTarget偏移中明确地需要4个字节.这里有一个实际的问题:我应该使用什么类型而不是unsigned long? (我猜有些接近UINT16,UINT32,UINT64会这样做).换句话说,为了代表2,8个字节我需要3种类型,总是独立于环境.
我相信这个基本问题会带来很多麻烦,所以应该澄清一下.
2012年1月16日的附加组件:
@Richard J. Ross III
我很困惑!由于我不知道linux是否使用1]或2],即在linux中定义了_STD_USING,
换句话说哪个组是可移植的类型uint8_t,…,uint64_t或_CSTD uint8_t,_ CSTD uint64_t?
1] MVS 10.0 stdint.h的摘录
typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned int uint32_t;typedef _ulonglong uint64_t;
2] MVS 10.0 stdint.h的摘录
#if defined(_STD_USING)...using _CSTD uint8_t; using _CSTD uint16_t;using _CSTD uint32_t; using _CSTD uint64_t;...
使用Microsoft C 32bit,没有问题:
; 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 /FAcsMicrosoft (R) C/C++ Optimizing Compiler Version 15.00.30729.01 for x64copyright (C) Microsoft Corporation. All rights reserved.strstr_SHORT-SHOWDOWN.cstrstr_SHORT-SHOWDOWN.c(1925) : Fatal error C1083: Cannot open include file: 'stdint.h': No such file or directoryD:\_KAZE_Simplicius_Simplicissimus_Septupleton_r2-_strstr_SHORT-SHOWDOWN_r7>
linux的stdint.h如何呈现?
我没有放弃并评论它:// #include< stdint.h>,然后编译就行了:
; 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,ebp 0176d 75 38 jne SHORT $LN1@Railgun_Qu@6
这个’unsigned long *’让我烦恼,因为gcc -m64会获取QWORD而不是DWORD,对吧?
@mysticial
只想展示Microsoft CL 32bit v16完成的三种不同翻译:
1]
; 3400 : if ( !memcmp(&pbTarget[i],pbPattern,4) ) 01360 8b 04 19 mov eax,DWORD PTR [edi] 01369 75 2c jne SHORT $LN84@Railgun_Qu@6
2]
; 3400 : if ( !memcmp(&pbTarget[i],4) ) 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 $LN83@Railgun_Qu@6
3]
; 3401 : if ( *(uint32_t *)&pbTarget[i] == ulHashPattern ) 01350 8b 44 24 14 mov eax,eax 01357 75 2e jne SHORT $LN79@Railgun_Qu@6
最初的目标是提取(分别使用单个mov指令*(uint32_t *)& pbTarget [i])并将4字节与长度为4字节的寄存器变量进行比较,即一个RAM访问单个指令中的一个比较.
Nastily我只设法将memcmp()的3个RAM访问(在pbPattern上应用,指向4个或更多字节)减少到2,谢天谢地.
现在,如果我想在pbPattern的前4个字节上使用memcmp()(如2),ulHashPattern应该不是类型寄存器,而3]不需要这样的限制.
; 3400 : if ( !memcmp(&pbTarget[i],4) )
上面的行给出了一个错误(ulHashPattern定义为:register unsigned long ulHashPattern;):
strstr_SHORT-SHOWDOWN.c(3400) : error C2103: '&' on register variable
是的,你是对的:memcmp()保存情况(但有一个限制) – 片段2]与3]我的脏样式相同.
显然我倾向于在手动编码时不使用函数已成为过去,但我喜欢它.
我仍然不满意编译器,我已经将ulHashPattern定义为寄存器变量,但每次都从RAM加载?!也许我会错过一些东西但是这个(mov eax,DWORD PTR _ulHashPattern $[esp 1076])行会降低性能 – 在我看来这是一个丑陋的代码.
解决方法 要严格迂腐,你可以使用的唯一类型是char.这是因为你是 violating strict-aliasing以下类型双关语:*(unsigned long *)(pbPattern);*(unsigned long *)&pbTarget[i]
char *是此规则的唯一例外,因为您可以使用char *为任何数据类型设置别名.
如果您在GCC上发出警告,您应该使用代码段获得严格别名警告. (AFAIK,MSVC没有警告严格别名.)
我不能完全确定你在该代码片段中想要做什么,但是这个想法仍然存在,你不应该使用无符号长整数或任何其他数据类型来加载和比较不同的大块数据类型.
在所有现实中,你真的应该使用memcmp(),因为它是直截了当的,并且可以让你绕过将一切强制降为char *的低效率.
有没有理由你不能使用memcmp()?
如果您违反严格别名,则可以使用< stdint.h>中定义的固定整数类型(例如uint32_t).但是,请注意这些是固定在#位而不是字节数.
总结以上是内存溢出为你收集整理的便携式(主要是Linux和Windows)4字节提取/比较全部内容,希望文章能够帮你解决便携式(主要是Linux和Windows)4字节提取/比较所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)