Forum: Compiler & IDEs const prog_char Zeiger


von Marco (Gast)


Lesenswert?

Hallo,
wahrscheinlich stehe ich gerade nur auf dem Schlauch, aber folgender 
Code wirft meinen Compiler aus der Bahn:

flashStrings.h
1
//! Displays a constant string from flash memory on the lcd
2
void displayProgString(const prog_char* string);

flashStrings.c
1
#include <avr/pgmspace.h>
2
#include "lcd.h"
3
4
void displayProgString(const prog_char* string)
5
{
6
  unsigned char i = 0;
7
  for (i = 0; i < 32; i++)
8
  {
9
    char c = (char) pgm_read_byte (string);
10
    if ('\0' != c )
11
    {
12
      lcd_write_char(c);
13
    }
14
    else
15
    {
16
      i = 32;
17
    }
18
    string++; 
19
  }
20
}

Die Fehlermeldung lautet

../flashStrings.c:2: warning: type defaults to 'int' in declaration of 
'prog_char'
../flashStrings.c:2: error: expected ';', ',' or ')' before '*' token

Es macht auch keinen Unterschied, ob ich die pgmspace.h früher include 
(dort ist prog_char deklariert). Das wundert mich alles, weil ich es im 
Prinzip von 
http://www.roboternetz.de/wissen/index.php/Avr-gcc#String_im_Flash_belassen 
abgeschrieben habe.

Wahrscheinlich habe ich mich nur unendlich dumm angestellt...

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,
du musst in der header-datei auch den datentyp von prog_char 
deklarierbar machen.
aber ich sehe grade, dass du die gar nicht einbindest. irgendwie scheint 
dein beispiel nicht ganz vollständig zu sein.
bye kosmo

von Karl H. (kbuchegg)


Lesenswert?

Machs so
1
void displayProgString(const char* string)

Simpel und einfach.
Möglicherweise hatte prog_char mal eine andere Funktion,
aber so wie die tyepdefs im pgmspace.h liegen, ist prog_char
an dieser Stelle sowieso keine gute Idee.

PS: Deine Schleife in der Funktion ist etwas unübersichtlich.
Wenn die Idee sein soll
   Gib einen String aus, aber nicht mehr als 32 Zeichen
dann schreib das auch so ('Say what you mean')
1
   i = 0;
2
3
   c = (char) pgm_read_byte (string);
4
   while( c != '\0' && i < 32 ) {
5
     lcd_write_char( c );
6
     string++;
7
     i++;
8
     c = (char) pgm_read_byte (string);
9
   }
So hast du die Endbedingung der Schleife an einer Stelle beisammen
und nicht quer über die ganze Schleife verstreut.

Wenn dein C gut ist, dann machst du das so:
1
   i = 0;
2
3
   while( ( c = (char) pgm_read_byte (string)) != '\0' && i < 32 ) {
4
     lcd_write_char( c );
5
     string++;
6
     i++;
7
   }

oder (wenn dein C 'noch besser' ist) so:
1
   i = 0;
2
3
   while( ( c = (char) pgm_read_byte (string++)) != '\0' && i++ < 32 ) {
4
     lcd_write_char( c );
5
   }

Selbst das hier:
1
  for (i = 0; i < 32; i++)
2
  {
3
    char c = (char) pgm_read_byte (string);
4
    if ( c == '\0' )
5
      break;
6
7
    lcd_write_char(c);
8
    string++; 
9
  }

wäre noch besser, da man sich nicht fragen muss, warum in der
Schleife dem i der magische Wert 32 zugewiesen wird.

von Marco (Gast)


Lesenswert?

> Machs so
>
> void displayProgString(const char* string)
>
> Simpel und einfach.

Tut es leider nicht, weil "const char*" ins SRAM gelegt wird. prog_char 
wird von avr gcc zur Verfügung gestellt, um Daten in den Flashspeicher 
auszulagern, die sich nicht mehr ändern. Ich würde gerne auf 
plattformabhängige Casting-Experimente verzichten.

> du musst in der header-datei auch den datentyp von prog_char
> deklarierbar machen.

say what? Wenn du meinst

flashStrings.h
1
#include <avr/pgmspace.h>
2
//! Displays a constant string from flash memory on the lcd
3
void displayProgString(const prog_char* string);

wäre besser, muss ich dich leider enttäuschen, das war mein erster 
Versuch...

Aber ich sehe grade, dass die flashString.h nicht in flashString.c 
included wird... sehr peinlich! Scheint auch den Compiler für's erste zu 
befrieden... Sorry folks, ich habe ja mit eigener Dummheit gerechnet!

Danke für die Denkhilfen!

von Karl H. (kbuchegg)


Lesenswert?

Marco wrote:
>> Machs so
>>
>> void displayProgString(const char* string)
>>
>> Simpel und einfach.
>
> Tut es leider nicht, weil "const char*" ins SRAM gelegt wird.

Quatsch.
Der gcc unterscheidet bei einem Pointer nicht ob der jetzt
ins SRAM zeigt oder in den Flash. Für den gcc ist Pointer gleich
Pointer.
Und nichts anderes bekommt die Funktion übergeben.

Das dein Pointer ins Flash zeigt, wird dadurch berücksichtigt,
dass du nicht einfach einen *string machst um an die einzelnen
Zeichen zu kommen, sondern du die Funktion pgm_read_byte benutzt.

Der Datentyp prog_char an dieser Stelle hat höchstens dokumentarischen
Wert um dem Programmierer mitzuteilen, dass der erwartete Pointer ein
Pointer in den Flash sein muss.

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.