WP8.1中C++的winodws運行時組件位移操做的差別

  最近學習WP8.1應用開發,想把C語言的SM3國密算法移植到手機app中。因爲把C語言的代碼轉換成C#代碼工做量較大,所以只能用winodws運行時組件來實現。算法

  SM3國密算法是一種HASH算法,具體詳情請自行百度。windows

  結果測試發現手機上SM3算法計算出來的結果和電腦上運行的結果不一樣!通過我一點點調試發現是位移操做惹的禍,代碼中有以下宏定義:app

#define  SHL(x,n) (((x) & 0xFFFFFFFF) << n)
#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))

   第一行的宏定義當n大於32時,手機運算結果與電腦不一樣;第二行的宏定義當32-n小於0時,手機運算結果與電腦不一樣。函數

  爲了更好地測試,我決定建一個乾淨的測試環境。首先新建一個C#語言的空白的windows phone應用項目,在xaml中放一個textblock和2個按鈕學習

<Grid>
        <StackPanel>
            <TextBlock x:Name="txbResult"/>
            <Button x:Name="btnCSharpLeft" Content="C#位移" Click="btnCSharpLeft_Click"></Button>
            <Button x:Name="btnCLeft" Content="C左位移" Click="btnCLeft_Click"></Button>
        </StackPanel>
    </Grid>

再實現按鈕點擊事件測試

private void btnCSharpLeft_Click(object sender, RoutedEventArgs e)
        {
            txbResult.Text += "C#位移\n";
            for (int i = 0; i < 96; i += 8)
            {
                string str = "0x12345678<<" + i.ToString() + "=" + (0x12345678 << i).ToString("X");
                txbResult.Text += str.PadRight(40) + "0x12345678>>" + i.ToString() + "=" + (0x12345678 >> i).ToString("X") + "\n";
            }
        }

        private void btnCLeft_Click(object sender, RoutedEventArgs e)
        {
            txbResult.Text += "C位移\n";
            Class1 c = new Class1();
            for (int i = 0; i < 96; i += 8)
            {
                string str = "0x12345678<<" + i.ToString() + "=" + c.Func2(0x12345678, i).ToString("X");
                txbResult.Text += str.PadRight(40) + "0x12345678>>" + i.ToString() + "=" + c.Func1(0x12345678, i).ToString("X") + "\n";
            }
        }

接着新建一個C++語言的windows運行時組件,對外提供兩個函數,用以實現左位移和右位移spa

unsigned int Class1::Func1(unsigned int n, int b)
{
    return n >> b;
}

unsigned int Class1::Func2(unsigned int n, int b)
{
    return n << b;
}

而後連上手機進行測試,個人手機是nokia920,公司測試部的測試機,先拿來用用,吼吼!
調試

  能夠看到C#的位移在超過32時是對32取模的,也就是說位移33位至關於位移1位,而手機上運行結果測試超過32位都是0!code

爲了肯定是否C++語言的位移都是這麼處理的,我再新建一個WIN32的控制檯項目來測試blog

#include "stdio.h"

int main()
{
    printf("C左移\n");
    for (int i = 0; i < 96; i += 8)
    {
        printf("0x12345678<<%d = %x\n",i,0x12345678 << i);
    }
    printf("C右移\n");
    for (int i = 0; i < 96; i += 8)
    {
        printf("0x12345678>>%d = %x\n", i, 0x12345678 >> i);
    }
    return 0;
}

運行結果以下

能夠看到和C#的結果是同樣的。說明只有C++的windows運行時組件中才會有不一樣的結果。

同理我再測試位移負數位,好比 0x12345678>>-2,在C#和C++的WIN32程序中位移-2位至關於位移30位,而在C++的windows運行時組件中則結果是0。

結論:爲了兼容性,位移時要對32取模,好比1>>n要寫成1>>(n%32),這樣在不一樣的平臺中也能獲得相同的結果。

相關文章
相關標籤/搜索