Forum: Mikrocontroller und Digitale Elektronik uint8_t auf int16_t erweitern


von Wulf D. (holler)


Lesenswert?

Suche nach einem praktikablen c-Syntax, der Rechenfehler beim Erweitern 
von uint8_t auf int16_t bei unsigned Werten >127 vermeidet.

Weiß auch nicht, warum das gerade jetzt nicht klappt, das Beispiel:
1
//...
2
const uint8_t anzArray[] PROGMEM={64,76,84,92,98,104,111,120,132,161,190};
3
volatile int16_t z;
4
5
z = anzArray[i+1] - anzArray[i];
6
// oder auch
7
z = (int16_t)(anzArray[i+1]&0x00ff) - (int16_t)(anzArray[i]&0x00ff);

Letzteres liefert im Microchip Studio Watch
1
anzArray[i+1]    190    uint8_t{prog}@0x0028
2
anzArray[i]      161    uint8_t{prog}@0x0027
3
z               -131    int16_t{data}@0x0156 ([R28]+4)

Wie bekommt man ein mathematisch korrektes Ergebnis trotz 
Datentypen-Mix?

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Die Konvertierung ist nicht dein einziges Problem!
Siehe: https://www.nongnu.org/avr-libc/user-manual/pgmspace.html

Die Rechnung kann ich nicht prüfen, da ich KA habe was sie bewirken 
soll.

Wulf D. schrieb:
> mathematisch korrektes
Was soll es tun?

: Bearbeitet durch User
von Wulf D. (holler)


Lesenswert?

Ja, denke auch dass es am PROGMEM liegt, sonst wäre ich bereits früher 
drüber gestolpert.
Das erwartete Rechenergebnis wäre +29 statt -131, also 190-161=29.

: Bearbeitet durch User
von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Wulf D. schrieb:
> Ja, denke auch dass es am PROGMEM liegt, sonst wäre ich bereits früher
> drüber gestolpert.
> Das erwartete Rechenergebnis wäre +29 statt -131, also 190-161=29.

Wenn Du (Byte-)Daten mittels PROGMEM ablegst, musst Du auf diese mittels
pgm_read_byte() zugreifen.

Warum verwendest Du nicht __flash? Dann geht's auch ohne 
pgm_read_byte().

Grüßle,
Volker

: Bearbeitet durch User
von Wulf D. (holler)


Lesenswert?

Volker B. schrieb:

> Warum verwendest Du nicht __flash? Dann geht's auch ohne
> pgm_read_byte().

Herzlichen Dank, __flash löst das Problem!

von Wastl (hartundweichware)


Lesenswert?

Volker B. schrieb:
> Warum verwendest Du nicht __flash? Dann geht's auch ohne
> pgm_read_byte().

Kommt meiner dunklen Erinnerung nach darauf an welche GCC
Version man verwendet.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Wastl schrieb:
> welche GCC Version
Und in C++ leider auch nicht.

von Steve van de Grens (roehrmond)


Lesenswert?

> z = (int16_t)(anzArray[i+1]&0x00ff) - (int16_t)(anzArray[i]&0x00ff);

Wenn das Array im normalen RAM liegen würde... könnte diese Zeile so 
vereinfacht werden:

z = (int16_t)anzArray[i+1] - anzArray[i];

Der Teil &0x00ff kann entfallen, da er bei 8 Bit gar nichts bewirkt. Der 
rechte Teil des Ausdrucks muss nicht zu int16 konvertiert werden, da der 
linke Teil bereits ein int16 ist.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wastl schrieb:
> Volker B. schrieb:
>> Warum verwendest Du nicht __flash? Dann geht's auch ohne
>> pgm_read_byte().
>
> Kommt meiner dunklen Erinnerung nach darauf an welche GCC
> Version man verwendet.

Wird unterstützt ab GCC v4.7 (Release 2012).

https://gcc.gnu.org/gcc-4.7/changes.html#avr

Allerdings wird es nicht in C unterstützt sondern nur mit GNU-C; mit 
-std=c99 funktioniert es also nicht.

von Wulf D. (holler)


Lesenswert?

Steve van de Grens schrieb:
> Wenn das Array im normalen RAM liegen würde... könnte diese Zeile so
> vereinfacht werden:
> z = (int16_t)anzArray[i+1] - anzArray[i];

Ja, hatte ich zuerst so codiert, ein cast auf int16. Ist so wieder drin, 
nur halt mit dem __flash in der Definition des Arrays.

Wahrscheinlich wäre pgm_read_byte() portabler, weiß gar nicht genau das 
der __flash Präfix bewirkt.

War ein älterer Code wo die Anzeige manchmal Unsinn anzeigte und wollte 
der Sache nun auf den Grund gehen. Seltsam, dass es trotz des 
fehlerhaften Zugriffs überhaupt einigermaßen funktionierte.

Wegen der gcc-Version: im MAP-File fand ich dies: gcc/avr/5.4.0

Gruß Wulf

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Wulf D. schrieb:
> Seltsam, dass es trotz des
> fehlerhaften Zugriffs überhaupt einigermaßen funktionierte.

Den Effekt kenne ich.
Da ist es dann die Optimierung, welche das richtige Verhalten 
vortäuscht.

von Oliver S. (oliverso)


Lesenswert?

Wulf D. schrieb:
> Wahrscheinlich wäre pgm_read_byte() portabler

Wohin könnte das denn eventuell mal irgendwann portiert werden?

Oliver

von Wulf D. (holler)


Lesenswert?

Oliver S. schrieb:
> Wulf D. schrieb:
>> Wahrscheinlich wäre pgm_read_byte() portabler
>
> Wohin könnte das denn eventuell mal irgendwann portiert werden?
>
> Oliver

Na ja, auf eine andere Toolchain mit anderem Compiler, wenn man den Code 
in ein paar Jahren nochmal anfassen würde.

von Ralf G. (ralg)


Lesenswert?

Volker B. schrieb:
> Wenn Du (Byte-)Daten mittels PROGMEM ablegst, musst Du auf diese mittels
> pgm_read_byte() zugreifen.

Wulf D. schrieb:
> Seltsam, dass es trotz des
> fehlerhaften Zugriffs überhaupt einigermaßen funktionierte.

@TO:
Denkfehler.
Die Variablenüberwachung sieht anhand des Codes, dass Daten aus dem 
Flash angezeigt werden sollen.

Das übersetzte Programm zieht sich die Werte aus dem RAM: Sie mal nach, 
was 'Wert aus Adresse 0x28' minus 'Wert aus Adresse 0x27' ergibt...

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Einfach beide Operanden nach uint16_t casten, dann stimmt das Ergebnis.

von Bruno V. (bruno_v)


Lesenswert?

Wulf D. schrieb:
> Seltsam, dass es trotz des
> fehlerhaften Zugriffs überhaupt einigermaßen funktionierte.

die -131 sind m.E. nicht mit signed/unsigned erklärlich.

von Oliver S. (oliverso)


Lesenswert?

Wulf D. schrieb:
> Na ja, auf eine andere Toolchain mit anderem Compiler, wenn man den Code
> in ein paar Jahren nochmal anfassen würde.

Als da wäre?

Für einen anderen (neueren) gcc passts immer, und für alle anderen 
existierenden AVR-Compiler musst du die Flash-Zugriffe eh umschreiben, 
weil sowohl PROGMEN als auch _flash gcc-spezifisch sind. Für andere 
Prozessoren gilt das dann sowieso.
Ist aber auch völlig egal, denn du wirst das eh niemals irgendwo hin 
portieren.

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wulf D. schrieb:
> Oliver S. schrieb:
>> Wulf D. schrieb:
>>> Wahrscheinlich wäre pgm_read_byte() portabler
>>
>> Wohin könnte das denn eventuell mal irgendwann portiert werden?
>>
>> Oliver
>
> Na ja, auf eine andere Toolchain mit anderem Compiler, wenn man den Code
> in ein paar Jahren nochmal anfassen würde.

Am einfachsten und portabelsten geht das mit __flash, weil das im 
Gegensatz zu PROGMEM kein Attribute sondern ein Qualifier ist.  Zu 
Beispiel so:
1
#ifndef __FLASH
2
#define __flash /* empty */
3
#endif

Damit hättest du das Programm dann auf Reduced Tiny wie ATtiny portiert, 
wo es keine Named Address-Spaces gibt. (Auf den Reduced Tiny braucht's 
eh kein PROGMEM oder Flash, weil .rodata ins Flash allokiert ist, und 
nicht ins RAM wie bei den meisten anderen AVRs).

von P. S. (namnyef)


Lesenswert?

Steve van de Grens schrieb:
>> z = (int16_t)(anzArray[i+1]&0x00ff) - (int16_t)(anzArray[i]&0x00ff);
>
> Wenn das Array im normalen RAM liegen würde... könnte diese Zeile so
> vereinfacht werden:
>
> z = (int16_t)anzArray[i+1] - anzArray[i];
>
> Der Teil &0x00ff kann entfallen, da er bei 8 Bit gar nichts bewirkt. Der
> rechte Teil des Ausdrucks muss nicht zu int16 konvertiert werden, da der
> linke Teil bereits ein int16 ist.

Noch nicht einmal dieser Cast ist nötig, da die Operanden sowieso 
implizit zu "int" konvertiert werden ("integer promotion").

von Klaus H. (klummel69)


Lesenswert?

P. S. schrieb:
> Noch nicht einmal dieser Cast ist nötig, da die Operanden sowieso
> implizit zu "int" konvertiert werden ("integer promotion").

Jepp. Wobei nur bei avr ein int einem int16_t entspricht.
Bei 32Bit CPUs wäre es ein int32_t. Aber da eh nicht portiert wird, 
wurst.

von Wulf D. (holler)


Lesenswert?

Ralf G. schrieb:
> Wulf D. schrieb:
>> Seltsam, dass es trotz des
>> fehlerhaften Zugriffs überhaupt einigermaßen funktionierte.
>
> @TO:
> Denkfehler.
> Die Variablenüberwachung sieht anhand des Codes, dass Daten aus dem
> Flash angezeigt werden sollen.
>
> Das übersetzte Programm zieht sich die Werte aus dem RAM: Sie mal nach,
> was 'Wert aus Adresse 0x28' minus 'Wert aus Adresse 0x27' ergibt...

Das liefert auch nicht diese Differenz.
Im unterem RAM ab 0x0060,data ist alles auf default 0x00. Es wird nur 
wenig SRAM benutzt.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Wulf D. schrieb:
> Das liefert auch nicht diese Differenz.

Der Optimizer spielt dir (manchmal) Streiche!

von Bruno V. (bruno_v)


Lesenswert?

Wulf D. schrieb:
> Im unterem RAM ab 0x0060,data ist alles auf default 0x00

Also konkret: RAM an Adresse 0x28 und 0x29 ist 0?

Alternativ lade anzArray[i] in eine uint8 und in eine uint16 variable 
(am Besten volatile) und lass die dann ausgeben.

Am Ende gibt es irgendwo einen nachvollziehbaren Fehler. Und der hat 
nichts mit Überlauf zu tun.

von M. K. (sylaina)


Lesenswert?

Wulf D. schrieb:
> Wie bekommt man ein mathematisch korrektes Ergebnis trotz

Indem du z.B. die PROGMEM-Methoden zum Lesen der Daten aus dem 
Flashspeicher verwendest. Mit

Wulf D. schrieb:
> z = (int16_t)(anzArray[i+1]&0x00ff) - (int16_t)(anzArray[i]&0x00ff);

liest du nämlich nur aus, was an den entsprechenden Addressen im RAM 
steht, du holst dir hier gar keine Daten aus dem Flash ab und deshalb 
stimmt auch die Rechnung nicht mit dem Erwartungswert überein.
Im Gegensatz zu dir holt sich das Microchip Studio Watch die Daten 
richtig aus dem Flash ab.
Das richtige Ergebnis müsstest du erhalten indem du
1
z = (int16_t)pgm_read_byte(&anzArray[i+1]) - (int16_t)pgm_read_byte[&anzArray[i]);

rechnest.

von Wulf D. (holler)


Lesenswert?

M. K. schrieb:
> Wulf D. schrieb:
>> Wie bekommt man ein mathematisch korrektes Ergebnis trotz
>
> Indem du z.B. die PROGMEM-Methoden zum Lesen der Daten aus dem
> Flashspeicher verwendest.
> ...
>
1
z = (int16_t)pgm_read_byte(&anzArray[i+1]) - 
2
> (int16_t)pgm_read_byte[&anzArray[i]);

Ja richtig, der Vorschlag kam schon von Volker ganz oben im 4. Post, mit 
einer Alternative der __flash-Definition des Array. Beides funktioniert 
in dem Fall korrekt.
Die Diskussion ging jetzt hier noch darum, was der Code eigentlich für 
Daten im Fehlerfall verarbeitet.

Bruno V. schrieb:
> Wulf D. schrieb:
>> Im unterem RAM ab 0x0060,data ist alles auf default 0x00
>
> Also konkret: RAM an Adresse 0x28 und 0x29 ist 0?
>
> Alternativ lade anzArray[i] in eine uint8 und in eine uint16 variable
> (am Besten volatile) und lass die dann ausgeben.

Ja, im SRAM steht fast nur 0x0. Habe deinen Vorschlag getestet:
1
volatile anz_uint8_i, anz_uint8_i1;
2
volatile anz_uint16_i, anz_uint16_i1;
3
anz_uint8_i=anzArray[i];
4
anz_uint16_i=anzArray[i];
5
anz_uint8_i1=anzArray[i+1];
6
anz_uint16_i1=anzArray[i+1];
7
8
z=anzArray[i+1]-anzArray[i];

Der Watch vom Debugger:
1
  anzArray[i]     161   uint8_t{prog}@0x0027
2
  anzArray[i+1]   190   uint8_t{prog}@0x0028
3
  z              -131   int16_t{data}@0x014e ([R28]+4)
4
5
  anz_uint8_i     177   int{data}@0x0152 ([R28]+8)
6
  anz_uint16_i    177   int{data}@0x0156 ([R28]+12)
7
  anz_uint8_i1    48    int{data}@0x0154 ([R28]+10)
8
  anz_uint16_i1   48    int{data}@0x0158 ([R28]+14)

Das SRAM fängt bei Adresse 0x60 beim ATTiny45 an:
1
data 0x0060  09 00 06 00 25 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....%................
2
data 0x0075  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 00 3a 00  .................ÿ.:.
3
data 0x008A  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  .....................
4
data 0x009F  00 00 00 00 00 00 00 00 00 00 04 00 02 00 00 00 00 00 00 00 00  .....................

Aus dem SRAM kommen die Daten nicht, jedenfalls nicht aus der vermuteten 
Stelle.
Da das eigentliche Problem gelöst ist, sollte man den Thread beenden.

P.S.: Vielleicht aus den Registern, wenn da ab Adr.0x27 b1 30 stehen 
würde, aber da steht b3 30. Vielleicht wird beim Lesen etwas verbogen.
1
data 0x0000  12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b3 06 4a  ....................J
2
data 0x0015  04 00 00 7d ff 01 00 4a 01 27 00 00 00 00 00 40 bc fd b3 30 30  ...}ÿ..J.'.....@.ý.00
3
data 0x002A  00 00 00 00 00 00 00 00 00 00 00 10 39 03 10 00 00 00 00 4d 0b  ............9......M.

: Bearbeitet durch User
von Bruno V. (bruno_v)


Lesenswert?

Wulf D. schrieb:
> Da das eigentliche Problem gelöst ist, sollte man den Thread beenden.

Ja. Aber kein Grund, diesen konstruktiven Thread zu sperren. Selbst in 
einem Jahr wird jemand "Lösungen" zum "Überlauf" präsentieren. Doch: 
Beide Gleichungen für z im Ausgangspost sind korrekt, für jeden 
C-Compiler (zumindest für 8-Bit-Bytes, evt. auch für 9-Bit-Bytes).

von Ralf G. (ralg)


Lesenswert?

Wulf D. schrieb:
> P.S.: Vielleicht aus den Registern, wenn da ab Adr.0x27 b1 30 stehen
> würde, aber da steht b3 30. Vielleicht wird beim Lesen etwas verbogen.
1
0x30 - 0xb3 = ...
2
3
    0000 0000 0011 0000
4
  - 0000 0000 1011 0011
5
-----------------------
6
    1111 1111 0111 1101
7
8
  = -131

Passt doch!?

: Bearbeitet durch User
von Wulf D. (holler)


Lesenswert?

Ja stimmt passt, hatte mich verrechnet. Damit wäre das auch geklärt.
Gruß Wulf

von Oliver S. (oliverso)


Lesenswert?

Arduino F. schrieb:
> Der Optimizer spielt dir (manchmal) Streiche!

Nö, der stößt einen nur im Falle eines Falles mit der Nase auf 
fehlerhaften Code.

Oliver

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Oliver S. schrieb:
> Nö, der stößt einen nur im Falle eines Falles mit der Nase auf
> fehlerhaften Code.

Die Optimierung lässt hier falschen/kaputten Code so aussehen, als würde 
er funktionieren.
Das war ein Teil der Fragen hier, warum der falsche Code auch mal 
funktioniert.
Das ist eben die Optimierung, die einem eben hier genau diesen Streich 
spielt.

von Bruno V. (bruno_v)


Lesenswert?

Arduino F. schrieb:
> Das ist eben die Optimierung, die einem eben hier genau diesen Streich
> spielt.

Der C-Code zeigt auf falschen Speicher. Der Code ist ansonsten richtig, 
egal ob optimiert oder nicht.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Bruno V. schrieb:
> Der C-Code zeigt auf falschen Speicher.
Das weiß ich doch!
Nichts anderes sage ich.

Dank Optimierung kommt trotzdem das richtige Ergebnis, obwohl der 
Zugriff falsch ist.

: Bearbeitet durch User
von Steve van de Grens (roehrmond)


Lesenswert?

Arduino F. schrieb:
> Dank Optimierung kommt trotzdem das richtige Ergebnis, obwohl der
> Zugriff falsch ist.

Eher durch Zufall. Der Optimizer hat nichts verschleiert oder repariert.

von Oliver S. (oliverso)


Lesenswert?

Wenn der Compiler den Wert von i kennt, dann rechnet der aus den 
konstanten Werten des Arrays bei eingeschalteter Optimierung das 
Ergebnis gleich selber aus. Der „falsche“ Speicherzugriff findet dann 
gar nicht statt. Zufall ist das dann nicht.

Ob der i kennen kann, ist aus dem Code oben nicht zu erkennen.

Oliver

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Arduino F. schrieb:
> Die Optimierung lässt hier falschen/kaputten Code so aussehen, als würde
> er funktionieren.
> Das war ein Teil der Fragen hier, warum der falsche Code auch mal
> funktioniert.

Das hat aber nicht unbedingt was mit Optimierung zu tun.

Ganz allgemein hat man die äquivalenten Implikationen

1) Code funktioniert nicht => Programm[*] ist nicht korrekt

2) Programm[*] ist korrekt => Code funktioniert

wobei [*] auch Transformatoren wie Compiler, Assembler, Linker etc. 
beinhaltet sowie Microcode/Silizium.  Oft wird aber angenommen es sei 
auch

3) Code funktioniert => Programm korrekt

gültig, was idR nicht der Fall ist.

So kann man zum Beispiel aus bestandenen Tests idR nicht 
schlussfolgern, das Programm sei korrekt, ganz egal ob nun Optimierungen 
aktiv sind oder nicht.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Johann L. schrieb:
> Das hat aber nicht unbedingt was mit Optimierung zu tun.
Das ein- und ausschalten der Optimierung bringt es ans Licht, dass der 
Code kaputt ist.

Genau das hat die Optimierung damit zu tun.
Nicht mehr und nicht weniger.

von Rbx (rcx)


Lesenswert?

Wulf D. schrieb:
> Wie bekommt man ein mathematisch korrektes Ergebnis trotz
> Datentypen-Mix?

Mach es in Assembler. Hilft übrigens auch, einfachen Code sinnvoller zu 
strukturieren ;)

von Gerhard H. (hauptmann)


Lesenswert?

Rbx schrieb:
> Mach es in Assembler.

Das Thema schreit ja schon danach.
Welcher Wust künstlicher Probleme.

von Ralf G. (ralg)


Lesenswert?

Arduino F. schrieb:
> Die Optimierung lässt hier falschen/kaputten Code so aussehen, als würde
> er funktionieren.
> Das war ein Teil der Fragen hier, warum der falsche Code auch mal
> funktioniert.
> Das ist eben die Optimierung, die einem eben hier genau diesen Streich
> spielt.

Ob ohne oder mit Optimierung spielt überhaupt keine Rolle.*) Das 
Ergebnis ist immer gleich. (Ohne Optimierung kann man vielleicht im 
Simulator ein paar mehr Variablen überprüfen, die sonst in Registern 
gehalten werden (AVR-Studio) oder 'wegoptimiert' wurden und somit im 
Watch-Fenster nicht angezeigt werden können.)

Hier: Das Programm macht genau das, was programmiert wurde! Einen 
Zugriff auf den RAM. Will man auf den Flash zugreifen, muss 
'pgm_read_XXXX' verwendet werden. (bzw. '__flash' ... C, gcc)

*) ja, es gibt ein seltene Ausnahmen...

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Ralf G. schrieb:
> Ob ohne oder mit Optimierung spielt überhaupt keine Rolle.
Bei dem Eingangsproblem, und ähnlichen, spielt das schon eine Rolle

Durch die Optimierung wird der Logische Fehler verdeckt.
Das ist der Streich, der einem da die Optimierung spielt.

Hier vereinfacht:
1
const int a PROGMEM {4};
2
const int b PROGMEM {5};
3
4
5
void setup() 
6
{
7
  Serial.begin(9600);
8
  Serial.println(a+b); 
9
}
10
11
void loop() 
12
{
13
14
}

Mit -Os kommt, trotz falschem Zugriff auf die Konstanten, eine 9. 
Reproduzierbar.
Was mit -O0 (oder wenn man die Konstanten volatile macht) kommt, ist 
nicht wirklich vorhersehbar.

Das gilt genauso für die .eeprom Section

Ralf G. schrieb:
> Hier: Das Programm macht genau das, was programmiert wurde! Einen
> Zugriff auf den RAM.
Eben nicht!
Mit -Os tut es das eben nicht, oder nicht unbedingt.
Mit -O0 greift es ins RAM und liefert sicherlich unerwünschtes.

> Will man auf den Flash zugreifen, muss
> 'pgm_read_XXXX' verwendet werden. (bzw. '__flash' ... C, gcc)
Das musst du mir nicht erklären!

: Bearbeitet durch User
von Bruno V. (bruno_v)


Lesenswert?

Arduino F. schrieb:
> Mit -Os kommt, trotz falschem Zugriff auf die Konstanten, eine 9.

OK, so betrachtet hast Du Recht: Der Code definiert eine Gleichsetzung, 
die in HW nicht gegeben ist, die der C-Compiler aber wegoptimieren 
darf.

Wenn ich (fälschlicherweise und ohne volatile) beschreibe, dass x @ 
0x100 konstant 5 ist, liest er ohne Optimierung bei y=x was da wirklich 
steht. Mit Optimierung setzt er y=5 direkt, ohne zu lesen.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Bruno V. schrieb:
> OK, so betrachtet hast Du Recht:
Ich danke dir für die Zustimmung.

Bruno V. schrieb:
> aber wegoptimieren darf.
Darf, nicht darf...
Naja.

Ich sehe das eher so:
Der Compiler und seine Optimierungsstrategien haben (offensichtlich) 
keine/wenig Ahnung von den Speicher Sections, melden darum auch keinen 
Fehler. Haben keine Chance.

Die Section Attribute werden vom Compiler einfach nur an den Linker 
übergeben, welcher dann die Daten in den Sections verteilt und die 
Adressen in den generierten Code einträgt.

Ob man sagt "es hat keine andere Chance", oder "der darf das", hilft in 
der Praxis nicht wirklich weiter.

Gerade auch in Verbindung mit Schleifen kann einen der Effekt/Streich 
überraschen.
Programm läuft gut und scheinbar richtig (mit -Os).
Nur eine Schleifeniteration hinzugefügt, und es kommt nur noch Müll 
raus.

von Bruno V. (bruno_v)


Lesenswert?

Arduino F. schrieb:
> Ob man sagt ... "der darf das", hilft in der Praxis nicht wirklich weiter.

Da bin ich anderer Meinung. C ist in vielen Bereichen genau definiert. 
Und wenn ich explizit sage, dass eine Variable immer (konstant) 5 ist, 
dann "darf" der Compiler das berücksichtigen, muss es aber nicht.

Sie es anders rum: Wenn der Compiler sich nicht auf meine Angaben 
verlassen kann, worauf dann?

Der Klassiker ist sicher das fehlende volatile eines flags oder eines 
Schleifenzählers. Hier darf der Compiler annehmen, dass es nicht 
volatile ist.

von Oliver S. (oliverso)


Lesenswert?

Arduino F. schrieb:
> Der Compiler und seine Optimierungsstrategien haben (offensichtlich)
> keine/wenig Ahnung von den Speicher Sections, melden darum auch keinen
> Fehler. Haben keine Chance.

Das ist ja jetzt nichts neues. Das Konzept der verschiedenen 
Speichertypen kennt C nicht, und damit kennt das auch der Compiler 
nicht.

Was nichts daran ändert, daß ein fehlerhafte Programm fehlerhaft ist, 
auch wenn es anscheinend die erwarteten Ergebnisse liefert.

Oliver

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Bruno V. schrieb:
> Wenn der Compiler sich nicht auf meine Angaben
> verlassen kann, worauf dann?
Menschen machen Fehler, übersehen was, vergessen was.
Das dürfte der Grund dafür sein, dass den Compilern über die Jahre 
beigebracht wurde immer mehr von diesen Problemstellen zu erkennen und 
Meldungen zu werfen.

Diese Meldungen sind durchaus hilfreich um (potentielle) Fehler 
auszubügeln.
Hier kommt leider keine Meldung!
Das ist schade.

In C weniger Problem, da man die Alternative __flash hat.
Aber in C++ mit seinem PROGMEM kann einem das schon auf die Füße fallen, 
bzw. als Falle Jahrelang in häufig wiederverwendeten Programmteilen 
schlummern.

von Ralf G. (ralg)


Lesenswert?

Arduino F. schrieb:
> Aber in C++ mit seinem PROGMEM kann einem das schon auf die Füße fallen,
> bzw. als Falle Jahrelang in häufig wiederverwendeten Programmteilen
> schlummern.

Diese Konstanten alle in einer Klasse privat 'verstecken'?

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.