便携式(主要是Linux和Windows)4字节提取/比较
嗨,所有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 ) { 上面的片段在Windows 32bit编译器上必须工作.我的愿望是所有这样的4vs4比较,以便在64位Windows和Linux下工作. 我相信这个基本问题会带来很多麻烦,所以应该澄清一下. 2012年1月16日的附加组件: @Richard J. Ross III 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 /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< 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 ; 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访问单个指令中的一个比较. ; 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).但是,请注意这些是固定在#位而不是字节数. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |