Forum: Compiler & IDEs bytes und strings in einem char array mischen


von TheMason (Gast)


Lesenswert?

Hallo,

ich habe mal eine Frage bei der ich nicht weiß ob sie schonmal gestellt 
worden ist (die Suche hat jedenfalls nix ergeben).
Ich möchte in einem Byte-Array (unsigned char) Zahlenwerte sowie 
Zeichenketten mischen können. also sowas :

unsigned char data[] PROGMEM = { 23, 45, 23, "test", 12, 45, 87, 23, 0, 
0, 0, 0, "write", "bla bla bla", 0, 6, 4, 43, 43, };

geht das ?

ich kann keine strukturen definieren (können schon, aber nicht in dem 
zusammenhang), da ich einen reinen byte-stream zur compilezeit erzeugen 
möchte, der dann zur laufzeit abgearbeitet wird.
zur not würde es auch reichen (obwohl ich das unschön fände) wenn ich 
den string an anderer stelle definiere, und den zeiger auf diesen string 
(geteilt in hi und lo byte) im array einfüge. die zeigeroperation in dem 
byte-stream werde ich wahrscheinlich ohnehin benötigen, aber den text 
würde ich gerne so (dann natülich mit null-terminierung) in dem 
datenstrom unterbringen.

von Sven P. (Gast)


Lesenswert?

Nein, geht leider nicht. Deine String-Literale zerfallen in diesem 
Kontext zu Zeigern, d.h. im Vektor landet allenfalls ein Stück dieses 
Zeigers (auf char abgeschnitten).

von TheMason (Gast)


Lesenswert?

hab ich den wenigstens die möglichkeit aus dem zeiger zwei einzelne 
bytes zu machen die sich dann in dem byte-strom einfügen lassen oder 
lässt c das ebenfalls nicht zu ?!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

TheMason schrieb:
> Hallo,
>
> ich habe mal eine Frage bei der ich nicht weiß ob sie schonmal gestellt
> worden ist (die Suche hat jedenfalls nix ergeben).
> Ich möchte in einem Byte-Array (unsigned char) Zahlenwerte sowie
> Zeichenketten mischen können. also sowas :
>
> unsigned char data[] PROGMEM = { 23, 45, 23, "test", 12, 45, 87, 23, 0,
> 0, 0, 0, "write", "bla bla bla", 0, 6, 4, 43, 43, };
>
> geht das ?
>

Sowas?
1
#include <avr/pgmspace.h>
2
3
const char data[] PROGMEM = "\027\055\027" "Hallo" "\010\000\001\033";

Beachte, daß in dem Falle "Hallo" nicht von einer '\0' gefolgt wird, 
aber am Ende von data immer eine Null steht wie bei Strings üblich. 
Endet data mit "\000", denn wir auch danach ein '\0' eingefügt.

Wenn du "test" als null-terminierten String brauchst, kannst du data 
auch als Union definieren, die eine Struktur mit einem const char[] 
überlagern (vermeidet type-punning, oder als Struktur und dann casten).
1
#include <avr/pgmspace.h>
2
3
const char data[] PROGMEM = "\027\055\027" "Hallo" "\010\000\033";
4
5
const union
6
{
7
    struct
8
    {
9
        uint8_t a;
10
        uint8_t b;
11
        uint8_t c;
12
        char d[5];
13
        uint8_t e;
14
    } bytes;
15
    
16
    const unsigned char asCharArray[0];
17
} data2 PROGMEM =
18
{
19
    .bytes = 
20
    {
21
        .a = 23,
22
        .b = 45,
23
        .c = 23,
24
        .d = "test",
25
        .e = 12
26
    }
27
};
28
29
char foo (void)
30
{
31
    return pgm_read_byte (&data[5]) + pgm_read_byte (& data2.asCharArray[5]);
32
}

Oder oben hinter dem "Hallo" explizit ne Null einfügen.

Johann

von TheMason (Gast)


Lesenswert?

@johann

die möglichkeit die bytes per \ in einen string einzufügen hatte ich 
total vergessen. danke fürs nochmal-dran-erinnern ;-)
ich habs zwar zwischenzeitlich was anders gelöst (habe einfach 
text-indizes definiert, die dann als byte in dem datenstrom stehen) aber 
ich halte mir die möglichkeit mal im hinterkopf.

die idee mit den strukturen würde auch gehen, aber ich würd ganz gerne 
meinen byte-stream per präprozessor generieren (und dann über defines 
die einzelnen bytes mit werten besetzen), von daher scheidet die 
möglichkeit aus.

aber da vllt nochmal die frage zu der geschichte mit dem zeiger 
aufspalten. geht das überhaupt ? sprich das ich einen zeiger in high und 
low-byte aufspalten kann und diesen im bytestream einfügen kann ? ich 
meine letztenendes ist es ja nur ein platzhalter der erst nach dem 
linken eintragen werden kann, aber eigentlich sollte das doch nicht so 
schwierig sein ...

ich meine selbst wenn das nicht geht würde, könnte ich mir immer noch 
ein pointer-array deklarieren und dann per byte index im bytestream 
darauf zurückgreifen, aber es wäre schon komfortabler.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

TheMason schrieb:

> aber da vllt nochmal die frage zu der geschichte mit dem zeiger
> aufspalten. geht das überhaupt ? sprich das ich einen zeiger in high und
> low-byte aufspalten kann und diesen im bytestream einfügen kann ? ich
> meine letztenendes ist es ja nur ein platzhalter der erst nach dem
> linken eintragen werden kann, aber eigentlich sollte das doch nicht so
> schwierig sein ...

In C sehe ich die Möglichkeit nur mittels Komposit.

Aber warum denn nicht sowas?
1
#include <avr/pgmspace.h>
2
3
#define STRINGIFY(X) #X
4
#define WERT1 STRINGIFY(42)
5
#define SIZE STRINGIFY(12)
6
#define TEXT "test"
7
8
extern int i;
9
10
#define CR "\n"
11
asm (
12
".global data" CR
13
"   .section  .progmem.data,\"a\",@progbits" CR
14
"   .type  data, @object" CR
15
"   .size  data, " SIZE CR
16
"data:" CR
17
"   .byte 0x23-3" CR
18
"   .string  \"" TEXT "\"" CR
19
"   .byte " WERT1 CR
20
"   .word i" CR
21
);
22
23
extern const char data[];
24
25
char foo (void)
26
{
27
    return pgm_read_byte (& data[5]);
28
}

Oder gleich ein Assembler-Modul, das ist lesbarer und kein Hexenwerk.

Auch dort kannst du den C-Präprozessor verwenden, Dateien includen und 
hast eine mächtige Makro-Maschinerie von gas. Ausserdem spart's die 
lästigen ".

Mich dünkt aber, du wählst irgendwie den falschen Ansatz.

Johann

von Sven P. (Gast)


Lesenswert?

TheMason schrieb:
> aber da vllt nochmal die frage zu der geschichte mit dem zeiger
> aufspalten. geht das überhaupt ? sprich das ich einen zeiger in high und
> low-byte aufspalten kann und diesen im bytestream einfügen kann ? ich
> meine letztenendes ist es ja nur ein platzhalter der erst nach dem
> linken eintragen werden kann, aber eigentlich sollte das doch nicht so
> schwierig sein ...

An sich geht das schon, C definiert, dass ein Zeiger mit einer 
(unbekannten, d.h. frei vom Compiler/... festzulegenden) 
Abbildungsfunktion in eine Ganzzahl gewandelt werden kann und zurück.
Es ist aber wimre auch nicht festgelegt, wie breit diese Ganzzahl dann 
sein soll. Bitte im Standard nachlesen!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sven P. schrieb:
> TheMason schrieb:
>> aber da vllt nochmal die frage zu der geschichte mit dem zeiger
>> aufspalten. geht das überhaupt ? sprich das ich einen zeiger in high und
>> low-byte aufspalten kann und diesen im bytestream einfügen kann ? ich
>> meine letztenendes ist es ja nur ein platzhalter der erst nach dem
>> linken eintragen werden kann, aber eigentlich sollte das doch nicht so
>> schwierig sein ...
>
> An sich geht das schon, C definiert, dass ein Zeiger mit einer
> (unbekannten, d.h. frei vom Compiler/... festzulegenden)
> Abbildungsfunktion in eine Ganzzahl gewandelt werden kann und zurück.
> Es ist aber wimre auch nicht festgelegt, wie breit diese Ganzzahl dann
> sein soll. Bitte im Standard nachlesen!

Ich sehe aber nicht, wie man so ein Zeiger in den Vytestream 
reinbekommen könnte in C. Es müssen ja passende Relocs erzeugt werden, 
die der Linker dann auflöst. Die Werte von Symbolen sind einem 
C-Compiler ja nicht bekannt.

Johann

von TheMason (Gast)


Lesenswert?

@johann

>Oder gleich ein Assembler-Modul, das ist lesbarer und kein Hexenwerk.

>Auch dort kannst du den C-Präprozessor verwenden, Dateien includen und
>hast eine mächtige Makro-Maschinerie von gas. Ausserdem spart's die
>lästigen ".

>Mich dünkt aber, du wählst irgendwie den falschen Ansatz.

die idee mit dem assembler modul werde ich evtl weiter verfolgen. habe 
das problem aber zwischenzeitlich anders gelöst.
es geht sich dabei um folgendes :

ich bin dabei eine gui zu programmieren. um die sache platzsparend zu 
machen verwende ich einen bytestream. das erste byte gibt den befehl an, 
und danach folgen roh-daten die je nach befehl interpretiert werden. ich 
habe befehle für pixel setzen, vertikale/horizontale linie und eben 
text-ausgabe.
nun wäre es bei der text ausgabe eben schön gewesen den text 
(nullterminiert) direkt in den bytestrom einzufügen. das ich das wohl 
nur mit einem assembler-modul machen kann lässt wohl nicht vermeiden. um 
mir die sache in c dennoch (über einen umweg) zu lösen, definiere ich 
die texte an anderer stelle und arbeite nur noch mit indizes. hat den 
vorteil das ich wiederkehrende texte nur über 1 byte darstellen kann und 
nicht jeweils immer den kompletten text im bytestrom habe. nachteil ist 
halt der das ich texte die nur einmal benötigt werden etwas mehr platz 
brauchen (um genau zu sein jeweils 2 byte, ein zeiger halt). ein 
weiterer nachteil (wobei es sich bei genauerer betrachtung eigentlich 
nicht vermeiden lässt) wäre wenn ich die befehle aus dem ram ausführen 
möchte (dynamisch) und die texte nicht im flash definiert sind, wobei 
das da wahrscheinlich nicht wirklich zum tragen kommt, da ich die texte 
dann eh von außen (z.b. uart) geliefert bekomme und dann eben nicht in c 
fest kompiliert vorliegen haben muß, und ich so den text direkt im 
byte-daten-strom unterbringen kann (da dieser byte-strom dann ja von 
außen kommt). ich hoffe ich hab das nicht zu umständlich erklärt ;-)
die geschichte mit dem pointer-im-byte-stream hab ich verworfen da es in 
dem zusammenhang keinen sinn machte. ich wollte mir die möglichkeit 
offenhalten z.b. zeiger auf kurvenzüge, bitmaps zu ermöglichen, wobei 
ich bei verwendung des flashs auch den weg über indizes (und 
dahinterliegende zeigertabellen) nutzen kann und damit eben auch eine 
wiederverwendungsmöglichkeit habe. beim ram funktioniert das mit den 
zeigern allerdings dann nicht.

trotzdem danke nochmal für die mühe.

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.