www.mikrocontroller.net

Forum: Compiler & IDEs Problem mit void*


Autor: Hengst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gemeinde,

ich schreibe eine art parser wobei ich jetzt auf ein problem gestoßen 
bin.

ich habe 8 & 16 bit breite variablen (arrays) und will diese als 1. 
pointer ausgeben.

stark vereinfachtes beispiel:

char i[10];
short z[3];
..

//initialisierung der arrays
//ein paar defines
..

void* var(char vartype, char element)
{
switch(vartype)
{
case INT_: return *i[element];
break;
case SHORT_: return *z[element];
break;
default; return null;
break;
}
}

void main()
{
//ne ganze menge inits und so
var(INT_,0) = 12;
var(SHORT_,12)=0;
}

aber das funtioniert so leider nicht :(
kann mir da jemand helfen?

danke schonmal :)

Autor: Werner B. (werner-b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abgesehen von der Unsinnigkeit des Beispiels ...
Ich würde es mal mit dem Adressoperator versuchen und in main die 
gelieferten Pointer dereferenzieren.
...
case INT_: return &i[element];
break;
case SHORT_: return &z[element];
break;
default; return NULL;
break;
...


...
*((int *)(var(INT_,0))) = 12;
*((short *)(var(SHORT_,12))) = 0;
...
P.S: Mit AVR-GCC/WinAVR ist sizeof(int) == sizeof(short) und darum die 
Unterscheidung eine rein akademische Angelegenheit.

EDIT: PPS. Ähh i ist char[], aber case INT_: return &i[element]; ???

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ziemlich unschön das Ganze. Aber so müsste es technisch gehen:

char i[10];
short z[3];

//initialisierung der arrays
//ein paar defines

void* var(char vartype, char element)
{
  switch(vartype)
  {
    // Adresse (&) ermitteln, dann diese als Zeiger zurückgeben
    case INT_:   return &i[element];
                 break;
    case SHORT_: return &z[element];
                 break;
    default;     return NULL;
                 break;
  }
}

void main()
{
  // Rückgabewert (= void * zeiger) in Datentyp Zeiger casten 
  // und dann Inhalt (*) zuweisen
  *((char *)var(INT_,0)) = 12;
  *((short *) var(SHORT_,12)) = 0; // Knallt, 12 ausserhalb der Arraygrösse von z (3)!
}


EDIT: Werner war schneller

Autor: Hengst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke werner, aber dein ansatz funktioniert nicht, wenn ich einen wert 
zuweisen möchte :(

\main.c:: In function `main':
\main.c:264: warning: dereferencing `void *' pointer
\main.c:264: error: invalid use of void expression

Autor: Werner B. (werner-b)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hengst wrote:
> danke werner, aber dein ansatz funktioniert nicht, wenn ich einen wert
> zuweisen möchte :(
>
> \main.c:: In function `main':
> \main.c:264: warning: dereferencing `void *' pointer
> \main.c:264: error: invalid use of void expression

Sorry, ich habe auf den ersten Blick nicht alle Fehler gesehen. Ist im 
Edit korrigiert (hoffentlich alle ;-))
EDIT nautürlich nicht. Stefan hat noch einen mehr gefunden :-/

Autor: Hengst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja ich habe es jetzt so weit das es geht...
also mit 8bit variablen... aber bei "unsigned short" geht es nicht :(
hast du da eine idee?

Autor: Hengst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bei einem "unsigned short" passiert dies:

\main.c:159: warning: comparison is always true due to limited range of 
data type
\main.c:159: warning: use of cast expressions as lvalues is deprecated
\main.c:159: error: invalid lvalue in increment

aus der meldung werde ich nicht ganz schlau :(

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Hengst (Gast)
> aber bei "unsigned short" geht es nicht...
Das unsigned short taucht jetzt zum 1. mal auf...
Ja, da kann man nicht mal raten :-(
Wie sieht denn diese problembehaftete Zeil 159 aus?
Idealerweise würdest du nicht nur die Frage stellen, sondern auch eine 
Möglichkeit zur Beantwortung liefern, indem du (wenigstens) diese Zeile 
mitpostest. Besser noch das ganze Programm.


BTW:
char i[10];

void* var(char vartype, char element)
{
  switch(vartype)
  {
    case INT_:   return &i[element];
:
Was verwendest du für einen Prozessor, wo ein char = int ist?
Ich habe ein wenig den Eindruck, dass du etwas Einfaches einfach 
kompliziert lösen willst. Beschreib doch eher mal die Aufgabe, 
vielleicht kommen dann andere (und bessere) Lösungsvorschläge  ;-)

Autor: Hengst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe mein problem weiter lokalisiert, weiß jetzt aber nicht, wie ich 
es umgehen kann.

ich habe eine große anzahl von #definitin für jede menge kleine aufgaben
uint8_t reg;
uint8_t a[10];
uint16_t b[10];

#define load(val) reg=val;
#define free(val) val=0;
#define fill(val) val=0xff;
#define adce(val) if(val < 300) val++;else val=0; //nur für 16b vars!!!
...
jetzt greife ich auf diese wie oben schon besprochen zu.

#define u8   0
#define u16  1

void* VAR(uint8_t var_type, uint8_t var)
{
    switch(var_type)
    {
        case u8: return &a[var];
                    break;
        case u16: return &b[var];
                    break;
        default: return NULL;
                    break;
    }
}
das funktioniert auch ohne probleme.
aber wenn ich sie wie folgend aufrufe...

#define LOAD   1
#define ADCE   2
void PARSER(uint8_t func, uint8_t var_type, uint8_t var)
{
    switch(func)
    {
        case LOAD:    load(*((uint8_t*)VAR(var_type,var)));
                      break;
        case ADCE:    adce(*((uint16_t*)VAR(var_type,var)));
                      break;
        default:      break;
    }
}
...bricht der comiler bei "adce(*((uint16_t*)VAR(var_type,var)));" ab 
mit den meldungen
warning: use of cast expressions as lvalues is deprecated
error: invalid lvalue in increment

es muss irgendetwas mit #define zu tun haben... scheinbar kann ich nur 
8bit variablen übergeben. habe ich damit recht? kann ich das umgehen?

compiler: gcc 3.4.5 mingw

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define load(val) reg=val;
#define free(val) val=0;
#define fill(val) val=0xff;
#define adce(val) if(val < 300) val++;else val=0; //nur für 16b vars!!!

Grundregel bei #defines: Alles Klammern, was man klammern kann!
Versuch mal:
...
#define adce(val) if((val) < 300) (val)++;else (val)=0;
usw.

Defines erzeugen immer nur Textersetzungen, und nehmen auf den Inhalt 
keine Rücksicht. Beispiel was ohne klammerung der Parameter passiert:
#define MALZWEI(x) x*2

int a=MALZWEI(5); // == 10, korrekt
int b=MALZWEI(4+1); // == 6, weil das Makro zu 4+1*2 expandiert wird.

Autor: Hengst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ernst,

wenn du eine atraktive frau in meinem alter wärst, würde ich dich jetzt 
küssen!!

genau das wars :)

Autor: Trohl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Finde ich sehr anständig, dass ihn jetzt nicht küsst. =)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.