2014-09-11 14 views
6

Ich muss die Daten von 2 char (8 Bit lang) zu einem einzigen short (16 Bit lang) kopieren. Ich habe es auf zwei verschiedene Arten versucht, aber ich kann es nicht zum Laufen bringen.Convert char in short

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

Und der andere:

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

Sie können memcpy nicht auf diese Weise verwenden, da diese Dateitypen nicht automatisch getarnt werden können. Sie müssen über das src-Array iterieren und jeden Wert in kurze Werte umwandeln. – Westranger

+4

Sie müssen wissen, ob die Abkürzung als [Little-Endian oder Big-Endian] dargestellt wird (http://en.wikipedia.org/wiki/Endianess). – interjay

+1

Sie müssen die Endianess von pchar und pshort wissen. Wenn sie identisch sind, verwenden Sie 'memcpy ((void *) pshort, (const void *) pchar, sizeof (kurz));' –

Antwort

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; 
} 

dies wird die Aufgabe erledigen.

+3

Endianess ist hier kein Problem, zumindest wenn man annimmt, dass sich die Daten unter 'pchar' nicht ändern, abhängig von der Endanfälligkeit des Systems, was in Ihrem Beispiel nicht der Fall ist. – alk

+2

Wenn dies ein 16-Bit-System ist, werden Sie Probleme bekommen, wenn Sie eine vorzeichenbehaftete Zahl von 8 Bits verschieben. Das ruft undefiniertes Verhalten auf. Verwenden Sie nicht die schlampigen Standard-Integer-Typen beim Schreiben von Bit-Hacks! – Lundin

6

pchar Unter der Annahme ist ein Array, das Ihre 2 Zeichen enthält, wie etwa:

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

P. S. Diese Arbeit für wenig Endianess.

+2

Endianess ist hier kein Problem, zumindest wenn man annimmt, dass die Daten unter 'pchar' nicht funktionieren ändern sich je nach Endgültigkeit des Systems. – alk

5

Andere nicht erklären, warum Ihre Code nicht funktioniert, so dass ich einen schnellen Stich darauf werfen:

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

auf einen Zeiger Hinzufügen TYPE * p den Zeiger in Schritten von sizeof(TYPE) bewegt (also es zeigt auf das nächste Element, denken Sie daran, das ist nur definiert wenn innerhalb ein Array). Also während pchar + 1 korrekt ist, ist pshort + 1 nicht (wie es die nächste short adressiert).

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

Errr .... die rechte Seite ist in mehr als einer Hinsicht gebrochen. Erstens, *(pchar+1) ist ein char, und & 0xFF00 auf einem char wird immer 0 ergeben (weil ein char ist nur 8 Bits zu beginnen, zumindest auf heutigen Maschinen ...). Und dann verschiebst du diese 8 Bits nach rechts ...?

Und für den Fall waren Sie nicht bewusst zu sein, wenn Sie nicht 0x00FF auf der linken Seite benutzt hatte (*pchar auf die Breite des rechten Operanden zu fördern), aber (char -sized) 0xFF, die Ergebnis dieser Operation wäre immer noch vom Typ char, und das Verschieben dieser 8 Bits nach links macht auch keinen großen Sinn (da der Typ nicht magisch erweitert wird).


Ein anderer Weg, um dies zu realisieren noch nicht erwähnt ist die 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; 
    } 

Wenn Sie dies in einem größeren Kontext verwenden, die struct Polsterung in Acht nehmen.

+0

Die Union wird den Code endienessabhängig machen. Auf einem Big-Endian-System erhalten Sie das erwartete Ergebnis 0x0102, aber auf Little-Endian-Systemen erhalten Sie 0x0201. Und dann ist da tatsächlich die Polstergefahr. Also Union ist keine gute Idee, stattdessen bit shifts. – Lundin

+1

@Lundin: Abhängig von Ihren Bedürfnissen könnte das Endianess-abhängige Ergebnis tatsächlich das sein, wonach Sie suchen. ;-) Aber ich stimme zu, "Union" ist etwas zwielichtig. Ich habe es der Vollständigkeit halber aufgenommen. – DevSolar

+0

Warum möchten Sie absichtlich endianessabhängigen Code schreiben? Endianess ist eine 100% schlechte Sache, egal welches System. – Lundin

2

Verwenden Sie bei bitweisen Operationen robusten Code mit echten Ganzzahlen mit fester Größe und bekannter Signedness. Dadurch wird verhindert, dass Sie Fehler im Zusammenhang mit impliziten Typkonvertierungen schreiben, was zu unbeabsichtigter Signierung führt. Der Typ char ist besonders gefährlich, da er von der Implementierung definierte Signedness aufweist. Es sollte niemals zum Speichern von Nummern verwendet werden.

#include <stdint.h> 

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