青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

longshanks

  C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
  14 Posts :: 0 Stories :: 214 Comments :: 0 Trackbacks

常用鏈接

留言簿(10)

我參與的團(tuán)隊(duì)

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

三只小豬
莫華楓

    小時(shí)候聽說過三只小豬的故事,隱約記得故事是講三只小豬用不同方法造房子,對(duì)抗老狼。這些天做軟件,遇到一個(gè)無比簡單的問題,但在三種不同的語言中,卻有著截然不同的解法。

    最近,冷不丁地接到公司下派的一個(gè)緊急任務(wù),做手持POS和PC程序之間交換數(shù)據(jù)的程序。各種各樣的麻煩中,有一個(gè)小得不起眼的問題,POS機(jī)中數(shù)據(jù)的字 節(jié)序和PC相反。這可不算是什么啊。沒錯(cuò),是在太簡單了。盡管如此,還是引發(fā)了一場(chǎng)爭(zhēng)論。做POS程序的,希望PC程序做轉(zhuǎn)換。做PC程序的,希望POS 程序做轉(zhuǎn)換。(誰都想少做點(diǎn),對(duì)吧;))。最終,作為和事佬的我,為了維護(hù)和諧的氛圍,攬下了這件事。當(dāng)然,到底在那里做,還是要決定的。最終選擇在PC 上,畢竟PC上調(diào)試起來容易。(天煞的,這個(gè)POS機(jī)沒有debug,也沒有模擬器,顯示屏還沒我手機(jī)的大,做起來著實(shí)費(fèi)事)。
    其實(shí),我的本意是想在POS上做這個(gè)轉(zhuǎn)換。因?yàn)镻OS用的是C(一個(gè)不知什么年代的gcc),可以直接操作字節(jié)。基本的代碼看起來差不多應(yīng)該是這樣:
        unsigned long InvData(unsigned long val, int n) {
            unsigned long t=val, res=0;
            for(; n >0; n--)
            {
                res = res << 8;
                res |= (unsigned char)t;
                t = t >> 8;
            }
            return res;
        }
    n是數(shù)據(jù)類型的字節(jié)長度。這里使用了最長的無符號(hào)整數(shù)類型。這是核心轉(zhuǎn)換函數(shù),各種類型的轉(zhuǎn)換函數(shù)都可以從中派生:
        long InvDataLong(long val) {
            return (long)InvData((unsigned long)val, sizeof(val));
        }
        short InvDataShort(short val) {
            return (short)InvData((unsigned short)val, sizeof(val));
        }
        ...
    最后,有一個(gè)比較特殊的地方,float。float的編碼不同于整型,如果直接用(unsigned long)強(qiáng)制類型轉(zhuǎn)換,只會(huì)把float數(shù)值的整數(shù)部分賦予參數(shù),得不到正確的結(jié)果。正確的做法,應(yīng)當(dāng)是把float占用的四個(gè)字節(jié)直接映射成一個(gè) unsigned long:
        float InvDataFloat(float val) {
            float val=InvData(*(unsigned long*)(&val), sizeof(val));
            return *(float*)(&val);
        }
    通過將float變量的地址強(qiáng)制轉(zhuǎn)換成unsigned long*類型,然后再dereference成unsigned long類型。當(dāng)然還有其他辦法,比如memcpy,這里就不多說了。至于double類型,為了簡化問題,這里將其忽略。如果有64位的整型,那么 double可以采用類似的解法。否則,就必須寫專門的處理函數(shù)。
    當(dāng)然,最終我還是使用C#寫這個(gè)轉(zhuǎn)換。相比之下,C#的轉(zhuǎn)換代碼顯得更具現(xiàn)代風(fēng)味。基本算法還是一樣:
        public static ulong DataInv(ulong val, int n)
        {
            ulong v1_ = val, v2_ = 0;

            for (; n > 0; n--)
            {
                v2_ <<= 8;
                v2_ |= (byte)v1_;
                v1_ >>= 8;
            }

            return v2_;
        }
    對(duì)于習(xí)慣于C/C++的同學(xué)們注意了,long/ulong在C#中不是4字節(jié),而是8字節(jié)。也就是C/C++中的longlong。以這個(gè)函數(shù)為基礎(chǔ),其它整數(shù)類型的字節(jié)序轉(zhuǎn)換也就有了:
        public static ulong DataInv(ulong val)
        {
            return DataInv(val, sizeof(ulong));
        }

        public static uint DataInv(uint val)
        {
            return (uint)DataInv((ulong)val, sizeof(uint));
        }

        public static int DataInv(int val)
        {
            return (int)DataInv((uint)val);
        }
        ...
    然而,面對(duì)float,出現(xiàn)了麻煩。在C#中,沒有指針,無法象C那樣將float展開成ulong。(unsafe代碼可以執(zhí)行這類操作,但這不是C#嫡親的特性,并且是違背C#設(shè)計(jì)理念的。這里不做考慮)。C#提供了另一種風(fēng)格的操作:
        public static float DataInv(float val)
        {
            float res_ = 0;

            byte[] buf_ = BitConverter.GetBytes(val);
            byte t = 0;

            t = buf_[0];
            buf_[0] = buf_[3];
            buf_[3] = t;

            t = buf_[1];
            buf_[1] = buf_[2];
            buf_[2] = t;

            res_ = BitConverter.ToSingle(buf_, 0);

            return res_;
        }
    這個(gè)做法盡管有些累贅,但道理上很簡單:把float變量轉(zhuǎn)換成一個(gè)字節(jié)流,然后把相應(yīng)的位置對(duì)調(diào),就獲得了字節(jié)反序的float。相比C的float轉(zhuǎn) 換,C#明顯不夠簡練。原因很簡單,C#根本不是用來干這個(gè)的。C是一種非常底層的語言,它的內(nèi)存模型是完全直觀的,與硬件系統(tǒng)相對(duì)應(yīng)的。因而,對(duì)于這種 與機(jī)器相關(guān)的操作,當(dāng)然也顯得游刃有余。而C#定位于高層開發(fā)的高級(jí)語言,底層的內(nèi)存模型是被屏蔽的,程序員無需知道和關(guān)心。
    不過,C#的代碼卻擁有它的優(yōu)勢(shì)。只需看一眼這些函數(shù)的使用代碼,便不言自明了:
        //C代碼
        int x=234;
        float y=789.89;
        short z=332;
        x=InvDataInt(x);
        y=InvDataFloat(y);
        z=InvDataShort(z);

        //C#代碼
        int x=234;
        float y=789.89;
        short z=332;
        x=DataInv(x);
        y=DataInv(y);
        z=DataInv(z);
    在C代碼中,對(duì)于不同的類型,需要使用不同命名的函數(shù)。而在C#代碼中,則只需使用DataInv這樣一個(gè)函數(shù)名。至于屆時(shí)選用那個(gè)版本的函數(shù),編譯器會(huì) 根據(jù)實(shí)際的類型自動(dòng)匹配。C#運(yùn)用函數(shù)重載這個(gè)特性,使得調(diào)用代碼可以采用統(tǒng)一的形式。即便是數(shù)據(jù)的類型有所變化,也無需對(duì)調(diào)用代碼做任何修改。(這在我 的開發(fā)過程中的得到了驗(yàn)證,傳輸數(shù)據(jù)的成員類型曾經(jīng)發(fā)生變化,我也只是修改了數(shù)據(jù)結(jié)構(gòu)的定義,便將問題搞定)。這一點(diǎn),在C中是無法做到的。
    歸結(jié)起來,C由于側(cè)重于底層,在數(shù)據(jù)轉(zhuǎn)換方便的靈活性,使得轉(zhuǎn)換代碼的構(gòu)建更加容易。而C#則得益于函數(shù)重載,在轉(zhuǎn)換代碼使用方面,有獨(dú)到的優(yōu)勢(shì)。
    迄今為止,三只小豬中,還只有兩只出現(xiàn)。下面就要第三只出場(chǎng)了。
    作為C++的粉絲,我會(huì)自然而然地想到使用C++來實(shí)現(xiàn)這個(gè)轉(zhuǎn)換功能。于是便有了如下的代碼:
       unsigned long InvData(unsigned long val, int n) {
            unsigned long t=val, res=0;
            for(; n >0; n--)
            {
                res = res << 8;
                res |= (unsigned char)t;
                t = t >> 8;
            }
        }
        long InvData(long val) {
            return (long)InvData((unsigned long)val, sizeof(val));
        }
        short InvData(short val) {
            return (short)InvData((unsigned short)val, sizeof(val));
        }
        ...
        float InvData(float val) {
            float val=InvData(*(unsigned long*)(&val), sizeof(val));
            return *(float*)(&val);
        }
    這些代碼就好象是C和C#代碼的雜交后代。既有C的底層操作,也有C#的函數(shù)重載,兼有兩者的優(yōu)點(diǎn)。
    不過,還能做得更好:
        template<typename T>
        T InvData(T val) {
            T t=val, res=0;
            int n=sizeof(T);
            for(; n >0; n--)
            {
                res = res << 8;
                res |= (unsigned char)t;
                t = t >> 8;
            }
            return (T)res;
        }
    這樣,就把所有的整型都一網(wǎng)打盡了,僅用一個(gè)函數(shù)模板,便完成了原先諸多函數(shù)所做的工作。而float版本的函數(shù)則保持不變,作為InvData()的一個(gè)重載。按照C++的函數(shù)模板-重載規(guī)則,float版的函數(shù)重載將被優(yōu)先使用。

    好了,三只小豬的故事講完了。前兩只小豬各有優(yōu)點(diǎn),也各有缺點(diǎn)。而第三只小豬則雜合和前兩者的優(yōu)點(diǎn),并且具有更大的進(jìn)步。盡管第三只小豬存在各種各樣的缺陷,但畢竟它的眾多特性為我們帶來了很多效率和方便,這些還是應(yīng)當(dāng)值得肯定的。

附:第三只小豬的其他手段:
1、強(qiáng)制轉(zhuǎn)換成字符串?dāng)?shù)組
template<typename T>
T InvData1(T v) {
    unsigned char* pVal1=(unsigned char*)(&v)
        , *pVal2=pVal1+sizeof(T)-1, t;
    while(pVal2-pVal1>1)
    {
        t=*pVal2;
        *pVal2=*pVal1;
        *pVal1=t;
        pVal1++;
        pVal2--;
    }
    return v;
}
2、使用標(biāo)準(zhǔn)庫,blog上有人留言建議的
template<typename T>
T InvData(T v) {
    unsigned char* pVal=(unsigned char*)(&v);
    size_t n=sizeof(T);
    std::reverse(pVal, pVal+n, pVal);
}
3、使用traits
template<size_t n> struct SameSizeInt;
template<> struct SameSizeInt<1> { typedef unsigned char Type; };
template<> struct SameSizeInt<2> { typedef unsigned short Type; };
template<> struct SameSizeInt<4> { typedef unsigned long Type; };
template<> struct SameSizeInt<8> { typedef unsigned longlong Type; };

template<typename T>
T InvData(T v) {
    size_t n=sizeof(T);
    typedef SameSizeInt<sizeof(T)>::Type NewT;
    NewT v1=*(NewT*)(&v), v2=0;
    for(; n >0; n--)
    {
        v2= v2<< 8;
        v2|= (unsigned char)v1;
        v1 = v1 >> 8;
    }
    return *(T*)(&v2);
}

甚至可以使用tmp去掉其中的循環(huán)。在C++中,這類任務(wù)的實(shí)現(xiàn)方法,完全看程序員的想象力了。:)
posted on 2008-09-18 19:25 longshanks 閱讀(1960) 評(píng)論(3)  編輯 收藏 引用

Feedback

# re: 三只小豬[未登錄] 2008-09-19 08:06 FongLuo
還有第四只小豬(適合C/C++):
將需要轉(zhuǎn)換的數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為BYTE數(shù)組,再進(jìn)行數(shù)組的頭尾交換(反轉(zhuǎn),STL中有現(xiàn)成的算法),只要數(shù)組長度/2次交換就可以完成了。  回復(fù)  更多評(píng)論
  

# re: 三只小豬 2008-09-19 09:19 Louix
unsigned int target;
unsigned int result = ( target << 16 ) | ( target >> 16 );
result = ( ( result & 0xFF00FF00 ) >> 8 ) | ( ( result & 0x00FF00FF ) << 8 );

好處就是沒有循環(huán)的跳轉(zhuǎn),會(huì)更快一些。  回復(fù)  更多評(píng)論
  

# re: 三只小豬 2010-01-14 19:17 EvieOn
One, who knows something about <a href="http://www.essaysprofessors.com/custom-writing.html">custom writing</a> should value your supreme release. I do think that the <a href="http://www.essaysprofessors.com/buy-a-paper.html">buy a paper</a> service could utilize it for the essay assignment blogs.   回復(fù)  更多評(píng)論
  


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品另类一区| 校园春色国产精品| 欧美一二三区精品| 亚洲尤物精选| 亚洲免费影视| 午夜日韩电影| 久久中文精品| 91久久精品日日躁夜夜躁欧美| 男人插女人欧美| 亚洲国产视频直播| 99re这里只有精品6| 一区二区欧美精品| 午夜在线a亚洲v天堂网2018| 久久亚洲精品欧美| 欧美精选午夜久久久乱码6080| 欧美日韩综合网| 国产综合久久久久久| 亚洲黄色成人久久久| 亚洲午夜国产成人av电影男同| 西西裸体人体做爰大胆久久久| 久久综合九九| 在线亚洲精品福利网址导航| 欧美自拍偷拍| 国产精品magnet| 黄页网站一区| 亚洲小说欧美另类社区| 久久亚洲国产成人| 亚洲精品一区久久久久久| 亚洲欧美日韩在线播放| 嫩草影视亚洲| 国产日韩欧美黄色| 亚洲深爱激情| 欧美激情中文字幕乱码免费| 亚洲永久免费视频| 蜜臀av国产精品久久久久| 国产精品大全| 亚洲精品一区二区三区蜜桃久| 午夜一区二区三区在线观看| 最新国产成人在线观看| 香蕉久久夜色精品| 欧美日韩午夜视频在线观看| 伊人精品久久久久7777| 亚洲私人影院在线观看| 久久九九免费| 欧美日韩亚洲一区二区三区在线观看| 国产日韩av一区二区| 一本综合精品| 蜜桃av噜噜一区| 小嫩嫩精品导航| 国产精品国产三级国产普通话蜜臀 | 亚洲一级在线| 亚洲第一福利视频| 欧美中文字幕精品| 国产日韩精品一区观看 | 欧美日韩视频| 91久久国产综合久久蜜月精品 | 久久激五月天综合精品| 一区二区三区四区国产| 欧美激情黄色片| 亚洲国产成人精品女人久久久| 久久这里有精品15一区二区三区| 亚洲一区二区三区在线| 欧美日韩国产影片| 一区二区免费看| 99re66热这里只有精品3直播| 欧美精品videossex性护士| 亚洲国产成人av| 蜜臀a∨国产成人精品| 欧美在线综合视频| 一区二区自拍| 欧美国产大片| 欧美成人精品福利| 99视频+国产日韩欧美| 亚洲人成网站999久久久综合| 欧美精品在线观看| 一本色道久久综合亚洲精品按摩| 亚洲精品久久7777| 国产精品va在线播放| 午夜欧美电影在线观看| 欧美中文字幕视频在线观看| 国产婷婷97碰碰久久人人蜜臀| 欧美有码在线观看视频| 久久精品99无色码中文字幕| 精品51国产黑色丝袜高跟鞋| 欧美1区2区| 欧美日韩国产电影| 性视频1819p久久| 久久久久免费视频| 99re6这里只有精品视频在线观看| 99热在这里有精品免费| 国产日韩欧美另类| 亚洲欧美日韩成人| 亚洲精品自在在线观看| 亚洲日本中文| 国产精品久久久对白| 久久久精品国产99久久精品芒果| 久久九九久精品国产免费直播 | 狠狠色丁香婷婷综合影院| 欧美成人免费全部观看天天性色| 欧美—级高清免费播放| 羞羞漫画18久久大片| 噜噜噜91成人网| 午夜精品美女久久久久av福利| 久久九九免费| 欧美亚洲一区二区在线| 免费成人毛片| 欧美一区二区三区四区高清| 牛牛国产精品| 欧美一区二区在线看| 免费观看成人| 久久精品日产第一区二区三区 | 黄色精品网站| 在线一区二区日韩| 91久久精品国产91性色| 亚洲女女女同性video| 亚洲精品国产精品国产自| 亚洲影音一区| 亚洲综合视频在线| 欧美高清不卡在线| 久久亚洲欧美国产精品乐播| 欧美午夜不卡视频| 91久久中文| 亚洲精品国产系列| 久久久久一区二区三区四区| 午夜精品久久久久影视| 欧美日韩一区高清| 亚洲高清在线| 亚洲精品之草原avav久久| 久久精品一区二区| 久久久午夜电影| 国产视频久久久久久久| 亚洲一区久久| 午夜激情久久久| 国产精品chinese| 一级日韩一区在线观看| 亚洲最新中文字幕| 欧美激情视频在线播放| 欧美国产日韩一区二区三区| 激情综合在线| 久久精品一本| 欧美高清视频一二三区| 亚洲国产欧美国产综合一区| 久久亚洲私人国产精品va媚药| 久久人人97超碰国产公开结果 | 亚洲一区国产| 欧美午夜精品久久久久免费视| 日韩午夜三级在线| 亚洲自拍偷拍福利| 国产女优一区| 久久国产66| 嫩草伊人久久精品少妇av杨幂| 在线看片第一页欧美| 欧美成人一区二区在线| 亚洲激情一区二区三区| 欧美成人一区二免费视频软件| 欧美成人激情视频| 日韩一级裸体免费视频| 欧美日精品一区视频| 亚洲天堂免费观看| 欧美在线不卡视频| 在线电影国产精品| 欧美国产日韩一二三区| 99精品久久免费看蜜臀剧情介绍| 亚洲一区二区三区在线看| 国产精品羞羞答答| 亚洲综合电影| 欧美成人嫩草网站| 亚洲午夜久久久| 国产一区二区丝袜高跟鞋图片| 久久久久久网址| 91久久极品少妇xxxxⅹ软件| 一区二区电影免费观看| 国产精品一区在线观看| 久久久久中文| 一区二区av在线| 另类春色校园亚洲| 中文网丁香综合网| 国内精品久久久久影院 日本资源| 欧美gay视频激情| 亚洲一区二区三区精品在线| 男女精品网站| 欧美一区二区日韩一区二区| 亚洲高清av| 国产老女人精品毛片久久| 麻豆精品视频在线| 亚欧成人精品| 一区二区免费在线观看| 免费看精品久久片| 亚洲欧美日韩天堂| 亚洲另类春色国产| 极品裸体白嫩激情啪啪国产精品| 欧美日韩综合另类| 免费不卡在线视频| 久久精品国产99国产精品澳门| 一区二区福利| 91久久精品一区| 欧美激情精品久久久久久变态| 久久成人这里只有精品| 亚洲在线中文字幕| 99精品视频免费观看视频|