Forum: Compiler & IDEs Problem mit void*


von Hengst (Gast)


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:
1
char i[10];
2
short z[3];
3
..
4
5
//initialisierung der arrays
6
//ein paar defines
7
..
8
9
void* var(char vartype, char element)
10
{
11
switch(vartype)
12
{
13
case INT_: return *i[element];
14
break;
15
case SHORT_: return *z[element];
16
break;
17
default; return null;
18
break;
19
}
20
}
21
22
void main()
23
{
24
//ne ganze menge inits und so
25
var(INT_,0) = 12;
26
var(SHORT_,12)=0;
27
}

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

danke schonmal :)

von Werner B. (werner-b)


Lesenswert?

Abgesehen von der Unsinnigkeit des Beispiels ...
Ich würde es mal mit dem Adressoperator versuchen und in main die 
gelieferten Pointer dereferenzieren.
1
...
2
case INT_: return &i[element];
3
break;
4
case SHORT_: return &z[element];
5
break;
6
default; return NULL;
7
break;
8
...
9
10
11
...
12
*((int *)(var(INT_,0))) = 12;
13
*((short *)(var(SHORT_,12))) = 0;
14
...
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]; ???

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ziemlich unschön das Ganze. Aber so müsste es technisch gehen:
1
char i[10];
2
short z[3];
3
4
//initialisierung der arrays
5
//ein paar defines
6
7
void* var(char vartype, char element)
8
{
9
  switch(vartype)
10
  {
11
    // Adresse (&) ermitteln, dann diese als Zeiger zurückgeben
12
    case INT_:   return &i[element];
13
                 break;
14
    case SHORT_: return &z[element];
15
                 break;
16
    default;     return NULL;
17
                 break;
18
  }
19
}
20
21
void main()
22
{
23
  // Rückgabewert (= void * zeiger) in Datentyp Zeiger casten 
24
  // und dann Inhalt (*) zuweisen
25
  *((char *)var(INT_,0)) = 12;
26
  *((short *) var(SHORT_,12)) = 0; // Knallt, 12 ausserhalb der Arraygrösse von z (3)!
27
}

EDIT: Werner war schneller

von Hengst (Gast)


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

von Werner B. (werner-b)


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 :-/

von Hengst (Gast)


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?

von Hengst (Gast)


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 :(

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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:
1
char i[10];
2
3
void* var(char vartype, char element)
4
{
5
  switch(vartype)
6
  {
7
    case INT_:   return &i[element];
8
:
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  ;-)

von Hengst (Gast)


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
1
uint8_t reg;
2
uint8_t a[10];
3
uint16_t b[10];
4
5
#define load(val) reg=val;
6
#define free(val) val=0;
7
#define fill(val) val=0xff;
8
#define adce(val) if(val < 300) val++;else val=0; //nur für 16b vars!!!
9
...
jetzt greife ich auf diese wie oben schon besprochen zu.
1
#define u8   0
2
#define u16  1
3
4
void* VAR(uint8_t var_type, uint8_t var)
5
{
6
    switch(var_type)
7
    {
8
        case u8: return &a[var];
9
                    break;
10
        case u16: return &b[var];
11
                    break;
12
        default: return NULL;
13
                    break;
14
    }
15
}
das funktioniert auch ohne probleme.
aber wenn ich sie wie folgend aufrufe...
1
#define LOAD   1
2
#define ADCE   2
3
void PARSER(uint8_t func, uint8_t var_type, uint8_t var)
4
{
5
    switch(func)
6
    {
7
        case LOAD:    load(*((uint8_t*)VAR(var_type,var)));
8
                      break;
9
        case ADCE:    adce(*((uint16_t*)VAR(var_type,var)));
10
                      break;
11
        default:      break;
12
    }
13
}
...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

von Εrnst B. (ernst)


Lesenswert?

1
#define load(val) reg=val;
2
#define free(val) val=0;
3
#define fill(val) val=0xff;
4
#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:
1
...
2
#define adce(val) if((val) < 300) (val)++;else (val)=0;
3
usw.

Defines erzeugen immer nur Textersetzungen, und nehmen auf den Inhalt 
keine Rücksicht. Beispiel was ohne klammerung der Parameter passiert:
1
#define MALZWEI(x) x*2
2
3
int a=MALZWEI(5); // == 10, korrekt
4
int b=MALZWEI(4+1); // == 6, weil das Makro zu 4+1*2 expandiert wird.

von Hengst (Gast)


Lesenswert?

ernst,

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

genau das wars :)

von Trohl (Gast)


Lesenswert?

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

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.