Forum: Mikrocontroller und Digitale Elektronik 16Bit Wert aus 8Bit Array


von Rene K. (xdraconix)


Lesenswert?

Frage: da ja ein Feld in einem Array bloß auf eine Speicheradresse 
zeigt. Kann man den beim Auslesen mit einem 2 Byte großen Wert 
"weiterlesen"? Also wie folgt:

1
uint16_t u_value    = 0x1337;
2
uint8_t  c_array[5] = {0x13,0x37,0x15,0x16,0x17}; 
3
4
5
if(c_array[0] == u_value)
6
{
7
    //true
8
}
9
else
10
{ 
11
    //false
12
}

Was passiert in diesem Fall bei einer Zuweisung?

1
uint16_t u_value    = 0x1337;
2
uint8_t  c_array[5] = {0x00,0x00,0x00,0x00,0x00}; 
3
4
c_array[0] = u_value;

von Nop (Gast)


Lesenswert?

Rene K. schrieb:

> Frage: da ja ein Feld in einem Array bloß auf eine Speicheradresse
> zeigt. Kann man den beim Auslesen mit einem 2 Byte großen Wert
> "weiterlesen"?

Nein, nicht ohne Weiteres.

> if(c_array[0] == u_value)

Wird immer "false" sein.

> Was passiert in diesem Fall bei einer Zuweisung?

u_value wird nach uint8_t gecastet, unter Bitverlust, und dann 
zugewiesen. Also die untersten 8 Bits, wenn ich das richtig sehe.

Man kann da auch nichts mit Pointercasting reißen, weil das Aliasing 
wäre und nach C-Standard nicht definiert. Allenfalls mit ner Union wäre 
da was zu machen.

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

if((uint16_t)(c_array[0] | c_array[0+1]<<8 ) == u_value) {

....

von Rene K. (xdraconix)


Lesenswert?

Alles klar, danke :-D Naja, bevor da ich da mit Unions "rumspiele" 
(Wobei da auch das Problem der Zuweisung ja weiterhin besteht) - 
Bitschubse (TM) ich mir dann halt einfach [0]..[1] in eine uint16 
zusammen und vergleiche das so oder Bitreiße (TM) es dann wieder zu 
einzelnen Bytes auseinander. :-)

Danke für deine Aufklärung.



EDIT:

Dennis H. schrieb:
> if((uint16_t)(c_array[0] | c_array[0+1]<<8 ) == u_value) {
>
> ....

Ja genau so :-D

von Nop (Gast)


Lesenswert?

Das geht auch, allerdings solltest Du Dir dann Gedanken über korrekte 
Endianess machen.

von Nop (Gast)


Lesenswert?

Nop schrieb:

> korrekte Endianess

Wobei das bei der Union natürlich auch nicht anders wäre.

von Rene K. (xdraconix)


Lesenswert?

Nop schrieb:
> Das geht auch, allerdings solltest Du Dir dann Gedanken über korrekte
> Endianess machen.

Das Projekt ist nur für eine Architektur gedacht. Kann ich 
vernachlässigen. Aber danke für den Hinweis.

EDIT:

Nen Union (wo das ich eigentlich nicht nutzen will) dafür sähe dann so 
aus oder:
1
typedef union
2
{
3
     uint8_t c_array[5];
4
5
     uint16_t u_First16 : 2;
6
     uint16_t u_Secon16 : 2;
7
     uint8_t  u_Lastone : 1;
8
} un_value;
9
10
11
// Kann ich das Union auch "offen" lassen? Oder gibt das Speicherprobleme?
12
13
typedef union
14
{
15
     uint8_t c_array[5];
16
     uint16_t u_First16 : 2;
17
18
} un_value;

von Nop (Gast)


Lesenswert?

ich würd die zweite Komponente der Union mit nem struct aus zwei uint16 
und einem uint8 machen.

von Nop (Gast)


Lesenswert?

Etwa so:
1
struct uintwise {
2
  uint16_t uint_0;
3
  uint16_t uint_1;
4
  uint8_t trailbyte;
5
};
6
7
typedef union {
8
  struct uintwise uints;
9
  uint8_t c_array[5];
10
} T_ENTRY_5_BYTES;

von Dirk B. (dirkb2)


Lesenswert?

Es gibt immer noch memcpy aus der Standard Library.

von A. S. (Gast)


Lesenswert?

im Embedded-Bereich sollte man sich für den direktn Zugriff mit anderer 
Bitbreite entsprechende Routinen bereithalten. Verschiedene Arten sind 
möglich, ich gebe mal Beispiele für den 16-Bit-Zugriff (Word). 
Entscheide Dich  für eine Art, die in Deinem Projekt am sinnvollsten ist 
und implementiere sie dann für alle benötigten Breiten als Inline oder 
als #define
1
/* direkter Zugriff auf angegebene Adresse */
2
uint16 word_access1(void *p) 
3
{
4
    return *((uint16 *)p);
5
}
6
/* mit offs = 0: Byte 0,1; offs=1: Byte 2,3 */
7
uint16 word_access2(void *p, int offs)
8
{
9
    return *(((uint16 *)p)+offs);
10
}
11
/* angabe der Variable im Makro, nicht die Adresse! */
12
#define word_access3(a) (*(((uint16 *)&(a)))
13
14
/* in Deinem Beispiel */
15
uint16_t u_value    = 0x1337;
16
uint8_t  c_array[5] = {0x13,0x37,0x15,0x16,0x17}; 
17
18
if(u_value == word_access1(c_array))     ..
19
if(u_value == word_access1(&c_array[0])) ..
20
if(u_value == word_access2(c_array, 0)   ..
21
if(u_value == word_access3(c_array[0])   ..

Mit dem Makro kannst Du an der Adresse mit 16 Bit lesen und schreiben!
1
word_access3(c_array[0]) = 0xdead; /* ueberschreibt c_array[0] und [1] */

Wenn Du es nicht willst, caste auf (const uint16 *).

von Peter II (Gast)


Lesenswert?

Rene K. schrieb:
> Dennis H. schrieb:
>> if((uint16_t)(c_array[0] | c_array[0+1]<<8 ) == u_value) {
>>
>> ....
>
> Ja genau so :-D

wobei der cast nicht notwenig ist. es wird immer mit 16bit gerechnet.
1
if((c_array[0] | c_array[0+1]<<8 ) == u_value) {

von Waldo (Gast)


Lesenswert?

union {
uint_8 i8[2];
uint_16 i16;
} buffer;

buffer.i8[0] = c_array[0];
buffer.i8[1] = c_array[1];

if(buffer.i16 == u_value)
{
    //true
}
else
{
    //false
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.