Forum: Compiler & IDEs const struct = "not constant"


von Marvin (Gast)


Lesenswert?

Hi,

Habe ein paar andere Forenbeiträge gefunden, die spiegeln aber nicht 
mein Problem wieder:

Das hier klappt:

static const __flash char strHund[]  = "Hund";
static const __flash char strKatze[] = "Katze";
static const __flash char strMaus[]  = "Maus";

const __flash char * const __flash array[] =
{
  strHund, strKatze, strMaus
};

Das hier nicht:

struct sSensor
{
  const uint16_t press;
  const uint16_t release;
  const uint16_t dpress;
};

const __flash struct sSensor sensor1 = {0,0,0};
const __flash struct sSensor sensor2 = {1,1,1};
const __flash struct sSensor sensor3 = {2,2,2};


struct  sSensor sensors[SENSORS] = {sensor1};

Der Compiler meckert: sensors1 ist nicht konstant...
Hab schon gefühlt alle static/const/__flash durchprobiert...nix

Geht das überhaupt ?

Gruß Marvin

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin schrieb:
> Geht das überhaupt ?

Nein, denn C kennt keine Konstanten, und C++ kennt kein __flash.

von Mark B. (markbrandis)


Lesenswert?

Jörg Wunsch schrieb:
> Marvin schrieb:
>> Geht das überhaupt ?
>
> Nein, denn C kennt keine Konstanten

Ähem.
1
const unsigned int sinn_des_lebens = 42;
ist doch einwandfreies C.

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

Man könnte wohl, wenn man wollte, etwas in der Art machen:

1
#include <stdint.h>
2
#include <stdio.h>
3
4
typedef struct
5
{
6
    const uint16_t* sensor_data;
7
} sSensor;
8
9
typedef struct
10
{
11
    const sSensor* sensor;
12
} container_t;
13
14
const container_t container =
15
{
16
    (const sSensor[]) {
17
        { (const uint16_t[]) { 0, 0, 0 } },
18
        { (const uint16_t[]) { 1, 1, 1 } },
19
        { (const uint16_t[]) { 2, 2, 2 } }
20
    }
21
};
22
23
int main()
24
{
25
    uint8_t i;
26
    const uint16_t* data_pointer = container.sensor->sensor_data;
27
28
    for (i = 0; i < 9; i++)
29
    {
30
        printf("Inhalt von container[%d]: %d\n", i, *data_pointer);
31
        data_pointer++;
32
    }
33
34
    return 0;
35
}

von Rolf M. (rmagnus)


Lesenswert?

Mark Brandis schrieb:
> Jörg Wunsch schrieb:
>> Marvin schrieb:
>>> Geht das überhaupt ?
>>
>> Nein, denn C kennt keine Konstanten
>
> Ähem.
> const unsigned int sinn_des_lebens = 42;
> ist doch einwandfreies C.

Klar ist es das. Nur ist "sinn_des_lebens" hier keine Konstante, auch 
wenn da "const" davor steht. Deshalb eben dieser Fehler:

Marvin schrieb:
> const __flash struct sSensor sensor1 = {0,0,0};
[...]
> struct  sSensor sensors[SENSORS] = {sensor1};
[...]
> Der Compiler meckert: sensors1 ist nicht konstant...

Der Initialisierer für sensors muss eine Konstante sein, aber sensor1 
ist keine Konstante.

von Marvin (Gast)


Lesenswert?

Hi,

Warum ist aber bei den Zeichenketten strHund dann eine Konstante?

Bei char* gehts, aber bei ner struct nicht?

Gruss

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Marvin schrieb:
> Warum ist aber bei den Zeichenketten strHund dann eine Konstante?

strHund ist keine Konstante.

Aber man darf diese (nicht veränderbare) Variable gemäß der C-Syntax
mit einer Zeichenkette initialisieren, genauso, wie man sie auch
als
1
static const __flash char strHund[] = {
2
  'H', 'u', 'n', 'd', '\0'
3
};

initialisieren dürfte.

Dass strHund dennoch als Initialisierer für ein Feld von Zeigern
taugt, ist ebenfalls in der C-Syntax festgeschrieben.  Auch wenn
strHund selbst formal eine Variable ist, so ist ihre Adresse (die
dort ja benutzt wird) dennoch eine Konstante, die spätestens durch
den Linker auflösbar ist und eingesetzt werden kann.

: Bearbeitet durch Moderator
von Marvin (Gast)


Lesenswert?

Hi,

Aber ist es nicht egal ob ich jetzt:

static const __flash char strHund[]  = "Hund";

oder

static const __flash struct sSensor sensor1 = {0,0,0};

benutze ?

In beiden Fällen wird doch eine nicht veränderbare Variable mit 
konstanter Größe und fester Adresse initialisiert.
Für den Compiler/Linker müßte das equivalent sein ?

Aber das hier geht:
const __flash char * const __flash array[] ={ strHund };

Das hier nicht:

const __flash struct  sSensor * const __flash sensors[] = { sensor1 };
oder
const __flash struct  sSensor const __flash sensors[] = { sensor1 };

Und ich verstehe nicht, wieso...mach ich vielleicht syntaktisch mit der 
struct was falsch ?

Wenn es so ist, dass ein char strHund[] = ... als Initialisierer für ein 
Feld von Zeigern taugt, aber struct sSensor  sensor1 = ... nicht, ist 
das gut zu wissen.

Verstehen muss ich das aber nicht, da bei struct sSensor sensor1 = ... 
genauso alles bekannt sein müßte, wie beim Hund.

Gruß Marvin

von Rolf Magnus (Gast)


Lesenswert?

Marvin schrieb:
> Aber ist es nicht egal ob ich jetzt:
>
> static const __flash char strHund[]  = "Hund";
>
> oder
>
> static const __flash struct sSensor sensor1 = {0,0,0};
>
> benutze ?
>
> In beiden Fällen wird doch eine nicht veränderbare Variable mit
> konstanter Größe und fester Adresse initialisiert.

Die Adresse ist eine Konstante, sie wird aber nur bei strHund auch 
benutzt. Bei sensor1 dagegen wird der Inhalt verwendet, und der ist 
keine Konstante.

Marvin schrieb:
> const __flash char * const __flash array[] =
> {
>   strHund, strKatze, strMaus
> };

ist nur eine verkürzte Schreibweise für:
1
const __flash char * const __flash array[] =
2
{
3
  &strHund[0], &strKatze[0], &strMaus[0]
4
};

Hier kommt die Sonderrolle von Arrays zum Tragen, die sich implizit in 
einen Zeiger auf das erste Element konvertieren lassen, und dieser 
Zeiger wird hier genutzt.
Bei sensor1 dagegen ist keine Adresse involviert.

> Aber das hier geht:
> const __flash char * const __flash array[] ={ strHund };
>
> Das hier nicht:
>
> const __flash struct  sSensor * const __flash sensors[] = { sensor1 };
> oder
> const __flash struct  sSensor const __flash sensors[] = { sensor1 };

Das würde aber gehen:
1
const __flash struct  sSensor * const __flash sensors[] = { &sensor1 };

Denn erst dann benutzt du auch tatsächlich die Adresse und nicht den 
Wert von sensor1.

> Wenn es so ist, dass ein char strHund[] = ... als Initialisierer für ein
> Feld von Zeigern taugt, aber struct sSensor  sensor1 = ... nicht, ist
> das gut zu wissen.

Die taugen beide, wenn du auch bei beiden die Adresse nutzt, um jeweils 
ein Array aus Zeigern zu initialisieren.

von Marvin (Gast)


Lesenswert?

Hi Rolf,

Vielen Dank für Deine Hilfe. Die Lösung meines Problems war also das 
"&".

Das strHund ein Pointer auf das erste Zeichen des Strings ist, wußte 
ich.
strHund = &strHund[0] und auch gleich &strHund hoffe ich ?

Das aber sensor1 kein Pointer ist, wußte ich nicht. Habe das bisher aber 
immer automatisch mit "&" gemacht (nur in diesem Fall wegen dem Beispiel 
mit dem Hund nicht).
Auch wenn ich es zuvor immer richtig gemacht habe, dachte ich doch, 
dass: sensor1 = &sensor1 = &sensor1.press

Wieso ist sensor1 keine Adresse ? Ich hab jetzt gerade einen Knoten im 
Kopf...

Gruß Marvin

von Coder (Gast)


Lesenswert?

Unabhängig vom geschilderten Problem, sollte man sich daran errinnern, 
dass "const" keine Konstante deklariert. Im Quellkode wird dem Compiler 
mitgeteilt, dass auf die Variable nur-lesend zugegriffen werden soll. 
Ist der Optimierer aktiviert, kann eine const variable intern zu einer 
Konstanten wegoptimiert werden.

von Rolf Magnus (Gast)


Lesenswert?

Marvin schrieb:
> Das strHund ein Pointer auf das erste Zeichen des Strings ist, wußte
> ich.

strHund ist kein Pointer, sondern ein Array. Aber bei der Benutzung 
von Arrays können diese fast (aber nur fast) in allen Situationen wie 
Zeiger auf das erste Element behandelt werden. Den Unterschied zwischen 
Zeiger und Array nicht zu verstehen, ist aber ein typische 
Anfängerfehler in C, da das leider nicht sehr intuitiv gelöst ist.

> strHund = &strHund[0] und auch gleich &strHund hoffe ich ?

Nein. Die Adresse wird die selbe sein, aber der Typ ist natürlich 
anders. &strHund[0] ergibt einen Zeiger auf einen char. &strHund dagegen 
einen Zeiger auf ein Array aus char.

> Das aber sensor1 kein Pointer ist, wußte ich nicht.

sensor1 ist ein struct sSensor. Warum sollte das ein Zeiger sein?

> Habe das bisher aber immer automatisch mit "&" gemacht (nur in diesem
> Fall wegen dem Beispiel mit dem Hund nicht).

& ist in diesem Fall der Adress-Operator. Er gibt dir die Adresse des 
Objekts, das rechts davon steht. Diese kannst du in einen Zeiger 
schreiben.

> Auch wenn ich es zuvor immer richtig gemacht habe, dachte ich doch,
> dass: sensor1 = &sensor1 = &sensor1.press

Nein.

> Wieso ist sensor1 keine Adresse ?

Wieso sollte es? Gegenfrage:
1
int i = 5;
Wieso ist i keine Adresse?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wenn dich hässliche Makros nicht stören kannst das Pferd auch von hinten 
aufzäumen:
1
typedef struct
2
{
3
  int a, b, c;
4
} sensor_t;
5
6
const __flash sensor_t sensors[] =
7
{
8
    { 1, 2, 3 },
9
    { 4, 5, 6 },
10
    { 7, 8, 9 },
11
};
12
13
#define sensor0 (sensors[0])
14
#define sensor1 (sensors[1])
15
#define sensor2 (sensors[2])
16
17
int main (int argc, char *argv[])
18
{
19
    return sensor0.a + sensor2.b + sensors[sensor1.c + argc].c;
20
}

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.