2014-09-11 246 views
6

我需要將數據從2 char(8位長)複製到單個short(16位長)。我嘗試了兩種不同的方式,但無法實現。將char轉換爲short

void char2short(char* pchar, short* pshort) 
{ 
    memcpy(pshort , pchar + 1 , 1); 
    memcpy(pshort + 1, pchar , 1); 
} 

而另外一個:

void char2short(char* pchar, short* pshort) 
{ 
    short aux; 
    aux = ((*pchar & 0x00FF) << 8) | ((*(pchar+1) & 0xFF00) >> 8); 
    *pshort = aux; 
} 
+0

您不能以這種方式使用memcpy,因爲ist無法自動轉換這些數據類型。您需要迭代src數組並將每個值都簡寫爲 – Westranger 2014-09-11 12:25:57

+4

您需要知道該短文是否表示爲[little-endian或big-endian](http://en.wikipedia.org/wiki/Endianness)。 – interjay 2014-09-11 12:27:10

+1

您需要知道pchar和pshort的字節順序。如果它們相同,則使用'memcpy((void *)pshort,(const void *)pchar,sizeof(short));' – 2014-09-11 12:38:35

回答

9
#include <stdio.h> 


void char2short(unsigned char* pchar, unsigned short* pshort) 
{ 
    *pshort = (pchar[0] << 8) | pchar[1]; 
} 

int main() 
{ 
    unsigned char test[2]; 
    unsigned short result = 0; 

    test[0] = 0xAB; 
    test[1] = 0xCD; 
    char2short(test, &result); 
    printf("%#X\n",result); 
    return 0; 
} 

這會完成這項工作。

+3

Endianess在這裏不是問題,至少當假定'pchar'下的數據不會因系統的永久性而改變時(在你的例子中情況並非如此)。 – alk 2014-09-11 12:46:25

+2

如果這是一個16位系統,當將有符號數字8位左移時會出現問題。這會調用未定義的行爲。在寫入黑客時不要使用草率的默認整數類型! – Lundin 2014-09-11 13:57:08

6

假設pchar是包含2個字符數組,怎麼樣:

*pshort = (uint16_t)(((unsigned int)pchar[0]) | 
        (((unsigned int)pchar[1])<<8)); 

附:這項工作只是小小的內容。

+2

Endianess在這裏不是問題,至少在假設'pchar'下的數據不根據系統的永久性而變化。 – alk 2014-09-11 12:49:32

5

其他沒有解釋爲什麼代碼沒有工作,所以我要在這一個快速刺:

memcpy(pshort , pchar + 1 , 1); 
memcpy(pshort + 1, pchar , 1); 

添加到TYPE * psizeof(TYPE)增量移動指針的指針(所以它確實指向下一個元素,請記住這只是定義的如果裏面的一個數組)。所以雖然pchar + 1是正確的,pshort + 1不是(因爲它正在處理下一個short)。

aux = ((*pchar & 0x00FF) << 8) | ((*(pchar+1) & 0xFF00) >> 8); 

錯誤......右手側被打破的方式不止一個。首先,*(pchar+1)char,& 0xFF00char將始終產生0(因爲一個char是隻有8位開始,至少在當代機器...)。然後你將這8位移到右邊......?

而且,如果您不知道它,如果您沒有在左側使用0x00FF(將*pchar提升到右側操作數的寬度),但是(char大小)0xFF,該操作的結果仍然是char類型,並且將8位向左移動也沒有多大意義(因爲該類型不會被神奇地擴展)。


另一種方式去了解這個尚未提及的是union

#include <stdio.h> 

struct chars_t 
{ 
    // could also go for char[2] here, 
    // whichever makes more sense semantically... 
    char first; 
    char second; 
}; 

union combo_t 
{ 
     // elements of a union share the memory, i.e. 
     // reside at the same address, not consecutive ones 
     short shrt; 
     struct chars_t chrs; 
}; 

int main() 
{ 
    union combo_t x; 
    x.chrs.first = 0x01; 
    x.chrs.second = 0x02; 
    printf("%x", x.shrt); 
    return 0; 
    } 

如果你在更大的範圍內使用此,謹防結構的填充。

+0

聯盟將使代碼依賴性。在一個大的endian系統上,你會得到預期的結果0x0102,但是在little endian系統上,你會得到0x0201。然後確實存在填充危險。所以工會不是一個好主意,而是使用位移。 – Lundin 2014-09-11 14:00:21

+1

@Lundin:根據您的需要,依賴於結果的結果可能實際上就是您要查找的結果。 ;-)但我同意,'工會'有點狡猾。爲了完整起見,我將它包含在內。 – DevSolar 2014-09-11 14:04:41

+0

爲什麼你會故意要寫符號相關的代碼?無論系統如何,Endianess都是一件壞事。 – Lundin 2014-09-11 14:05:52

2

在進行按位運算時,請使用帶有已知符號的實數固定大小整數的可靠代碼。這會阻止您編寫與隱式類型轉換相關的錯誤,從而導致意想不到的簽名。 char類型特別危險,因爲它具有實現定義的簽名。它不應該用於存儲數字。

#include <stdint.h> 

void char2short(const uint8_t* pchar, uint16_t* pshort) 
{ 
    *pshort = ((uint16_t)pchar[0] << 8) | (uint16_t)pchar[1]; 
}