Forum: Mikrocontroller und Digitale Elektronik "char" is incompatible with parameter of type char *restrict


von Peter (Gast)


Lesenswert?

Hallo,

folgendes Problem
ich rufe mehrere Funktion auf die in cText1 einen Text schreiben sollen, 
dazu übergebe ich die Pointer an die nächste Funktion.
Leider bringt mir mein Compiler folgende Meldung
error:  #167: argument of type "char" is incompatible with parameter of 
type "char *restrict"

char cText[20];
vDISP_Visu_Z1(cText1, iAx);


void vDISP_Visu_Z1 (char *pcStr, int iAx){
   vDisp_Visu_Z1Std(&pcStr, iAx);
}

void vDisp_Visu_Z1Std(char **ppcStr, int iAx){
   snprintf(**ppcStr, sizeof(20)-1,"text");
}


Habe das Beispiel etwas zusammengekürzt.
Ich kann es kompilieren wenn ich snprintf(*ppcStr, sizeof(20)-1,"text") 
schreibe aber das Funktioniert natürlich nicht weil er dann ja in pcStr 
zeigt und nicht in cText.

Jemand eine Idee wo mein Fehler liegt?

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


Lesenswert?

Gib mal bitte ein vollständig compilierbares Beispiel.  So, wie es
da steht, ist es einfach nur wirr.

von Steffen R. (steffen_rose)


Lesenswert?

Peter schrieb:
> void vDisp_Visu_Z1Std(char **ppcStr, int iAx){
>    snprintf(**ppcStr, sizeof(20)-1,"text");
> }

ppcStr zweimal dereferenziert ergibt char.

von Peter (Gast)


Lesenswert?

dann versuch ich es nochmal mit der Formatierung vielleicht ist es so 
etwas übersichtlicher. Entschuldigung

1
int main (void) {
2
char cText[20];
3
   vDISP_Visu_Z1(cText1);
4
}
5
6
void vDISP_Visu_Z1 (char *pcStr){
7
   vDisp_Visu_Z1Std(&pcStr);
8
}
9
10
void vDisp_Visu_Z1Std(char **ppcStr){
11
   snprintf(**ppcStr, sizeof(20)-1,"text");
12
}

schreibe ich
1
int main (void) {
2
char cText[20];
3
   vDISP_Visu_Z1(cText1);
4
}
5
6
void vDISP_Visu_Z1 (char *pcStr){
7
   vDisp_Visu_Z1Std(&pcStr);
8
}
9
10
void vDisp_Visu_Z1Std(char **ppcStr){
11
   snprintf(*ppcStr, sizeof(20)-1,"text");
12
}

geht das Kompilieren aber im Debugger habe ich dann folgendes Problem 
das er mir in cText nur 2 Zeichen schreibt also "te".

von Εrnst B. (ernst)


Lesenswert?

Was ist "sizeof(20)" ?
1? oder 2? oder 4==sizeof(int)?

Mit -1 wird dann 3 draus. snprintf reserviert noch ein Null-Byte zum 
String-Terminieren, also: "te" ist korrekt.

von Peter (Gast)


Lesenswert?

blöd geschrieben gebe ich zu. dahinter steckt ein define

also
1
#define LINE_LENGTH 20
2
sizeof(LINE_LENGTH)

von Εrnst B. (ernst)


Lesenswert?

Peter schrieb:
> blöd geschrieben gebe ich zu. dahinter steckt ein define
>
> also
> #define LINE_LENGTH 20
> sizeof(LINE_LENGTH)

aber sizeof(20) ist nicht dasselbe wie 20.
"sizeof" gibt an, wieviel bytes der Datentyp im Speicher belegt.
"20" ist ein integer, der braucht auf deiner Hardware 4 Bytes.
also sizeof(LINE_LENGTH) == 4.
Du willst das sizeof an der Stelle also eher weglassen.

oder ganz verschwurbelt:
sizeof(char[LINE_LENGTH]).
Da wird klar, dass dich die Byte-Größe eines Strings von max. 
LINE_LENGTH Zeichen interressiert.

von Peter (Gast)


Lesenswert?

glaube das Problem gefunden zu haben

woran es liegt muss ich noch suchen

folgender Code geht
1
int main (void) {
2
char cText[20];
3
   vDISP_Visu_Z1(cText1);
4
}
5
6
void vDISP_Visu_Z1 (char *pcStr){
7
   vDisp_Visu_Z1Std(&pcStr);
8
}
9
10
void vDisp_Visu_Z1Std(char **ppcStr){
11
   snprintf(*ppcStr, (LINE_LENGTH-1),"text");
12
}

Warum mir da das sizeof reingerutscht ist keine Ahnung aber manchmal 
wird man wohl einfach Blind wenn man zu lange auf das gleiche Problem 
schaut. Danke für eure kleine wenn auch entscheidende Hilfe. :)

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


Lesenswert?

Peter schrieb:
> woran es liegt muss ich noch suchen

Schrieb Steffen Rose doch schon weiter oben.

von Peter II (Gast)


Lesenswert?

warum überhaupt zeiger auf zeiger?
1
void vDisp_Visu_Z1Std(char **ppcStr){

reicht kein
1
void vDisp_Visu_Z1Std(char *ppcStr){

von Εrnst B. (ernst)


Lesenswert?

Peter II schrieb:
> reicht kein
> void vDisp_Visu_Z1Std(char *ppcStr){

dann muss aber das hier:
Peter schrieb:
> vDisp_Visu_Z1Std(&pcStr);
auch angepasst werden.

Keine Ahnung was da noch an Code aussenrum ist, aber so herausgerissen 
schaut das aus wie:

"Pointer nicht verstanden, deshalb je nach Compiler-Fehlermeldung 
großzügig '&' oder '*' in den Sourcecode gewürfelt" ...

von Fritz G. (fritzg)


Lesenswert?

Εrnst B✶ schrieb:
> "Pointer nicht verstanden, deshalb je nach Compiler-Fehlermeldung
> großzügig '&' oder '*' in den Sourcecode gewürfelt" ...

Das nennt man Test Driven Development.

von asdfasd (Gast)


Lesenswert?

> > "Pointer nicht verstanden, deshalb je nach Compiler-Fehlermeldung
> > großzügig '&' oder '*' in den Sourcecode gewürfelt" ...

> Das nennt man Test Driven Development.

LOL - den merk ich mir ;-)

von Peter (Gast)


Lesenswert?

schön das man hier so nett empfangen wird. ...

Warum pointer to pointer? weil ich nicht allzu viele sprintf einbauen 
will/kann da dies zyklisch aufgerufen wird und deswegen es 
Laufzeitprobleme geben kann. Außerdem gibt es einige Unterfunktion damit 
die Übersichtlichkeit im Programm bestehen bleibt.

zu:
"Keine Ahnung was da noch an Code aussenrum ist, aber so herausgerissen
schaut das aus wie:

"Pointer nicht verstanden, deshalb je nach Compiler-Fehlermeldung
großzügig '&' oder '*' in den Sourcecode gewürfelt" ..."


Es ist meine erste Anwendung wo ich pointer to pointer benutze, ja. 
Vorher habe ich immer versucht so etwas zu vermeiden. Und ja ganz fest 
sitzt es noch nicht. Fand deine Aussage trotzdem nicht allzu toll, hoffe 
das nicht jeder der ein Problem hat hier so empfangen wird.

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Warum pointer to pointer? weil ich nicht allzu viele sprintf einbauen
> will/kann da dies zyklisch aufgerufen wird und deswegen es
> Laufzeitprobleme geben kann. Außerdem gibt es einige Unterfunktion damit
> die Übersichtlichkeit im Programm bestehen bleibt.
1
vDISP_Visu_Z1 (char *pcStr){

ist doch auch eine Unterfunktion und diese kommt ohne Pointer auf 
Pointer aus. Warum glaubst du das das bei der anderen Funktion nicht 
geht?

von Peter (Gast)


Lesenswert?

in vDISP_Visu_Z1 (char *pcStr)
gibt es jedoch noch ein switch der unterschiedliche Unterfunktion 
aufruft. An diese Unterfunktionen übergebe ich dann nur den Pointer. 
siehe Code.
1
void vDISP_Visu_Z1 (char *pcStr, teDISP_VisuTyp eVisuTyp){
2
3
   switch (eVisuTyp) {
4
      default: 
5
         vDisp_Visu_Z1Std(&pcStr, iAx);
6
         break;
7
      case 1:
8
         vDISP_Visu_Z1Spez(&pcStr, iAx);
9
         break;
10
   }
11
}

Da ich so wenig sprintf wie möglich benutzen will schien mir die 
Variante mit dem pointer to pointer als sinnvollste Variante. Da ich ja 
sonst das ganze in einer Zwischenvariable speichern müsste.

von Steffen R. (steffen_rose)


Lesenswert?

Peter schrieb:
> in vDISP_Visu_Z1 (char *pcStr)
> gibt es jedoch noch ein switch der unterschiedliche Unterfunktion
> aufruft. An diese Unterfunktionen übergebe ich dann nur den Pointer.
> siehe Code.
1
void vDISP_Visu_Z1 (char *pcStr, teDISP_VisuTyp eVisuTyp){
2
3
    switch (eVisuTyp) {
4
       default:
5
          vDisp_Visu_Z1Std(pcStr, iAx);
6
          break;
7
       case 1:
8
          vDISP_Visu_Z1Spez(pcStr, iAx);
9
          break;
10
    }
11
 }

> Da ich so wenig sprintf wie möglich benutzen will schien mir die
> Variante mit dem pointer to pointer als sinnvollste Variante. Da ich ja
> sonst das ganze in einer Zwischenvariable speichern müsste.
1
void vDisp_Visu_Z1Std(char *ppcStr){
2
   snprintf(ppcStr, LINE_LENGTH-1),"text");
3
}

Hier wird der Pointer einfach nur durchgereicht.

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


Lesenswert?

Peter schrieb:
> Da ich so wenig sprintf wie möglich benutzen will schien mir die
> Variante mit dem pointer to pointer als sinnvollste Variante.

Auch wenn das oben etwas, naja, direkt geschrieben worden ist, das
passt schon: Pointer nicht verstanden.

Einen Zeiger auf einen Zeiger brauchst du nur, wenn du den Zeiger
selbst verändern willst.  Das willst du aber gar nicht, denn dein
Zeiger kann die ganze Zeit auf das zeigen, was da von oben als
Adresse (eines Arrays natürlich) durchgereicht worden ist.

Eine Anwendug für Zeiger auf Zeiger wäre es, wenn die gerufene
Funktion selbst (bspw. via malloc()) Speicher alloziert, dessen Adresse
sie in einer Variablen des Aufrufers hinterlegen muss:
1
int foo(char **p) {
2
  char *tmp = malloc(42);
3
  if (tmp == NULL)
4
    return -1;
5
  *p = tmp;
6
  return 0;
7
}
8
9
...
10
   char *myptr;
11
   if (foo(&myptr) == 0) {
12
     // tuwas mit myptr
13
     free(myptr);
14
   }

von Peter (Gast)


Lesenswert?

Steffen Rose schrieb:
> Hier wird der Pointer einfach nur durchgereicht.

schönere Variante. Gefällt mir besser. Danke
Ich sehe ich hab noch etwas Lernbedarf was Pointer angeht. ;)

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Da ich so wenig sprintf wie möglich benutzen will

Warum das? ob es einmal oder 10mal im code steht, ändert fast nichts an 
der größe vom binary.

von Peter (Gast)


Lesenswert?

Peter II schrieb:
> Warum das? ob es einmal oder 10mal im code steht, ändert fast nichts an
> der größe vom binary.


printf wirkt blockierend auf die serielle Schnittstelle. Da eine 
dynamische Anwendung (Regler) läuft kann somit die Ausgabe nicht immer 
bedient werden. Der Regler wird unruhig.

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> printf wirkt blockierend auf die serielle Schnittstelle. Da eine
> dynamische Anwendung (Regler) läuft kann somit die Ausgabe nicht immer
> bedient werden. Der Regler wird unruhig.

es ging um sprintf, das blockiert nichts.

von Rolf Magnus (Gast)


Lesenswert?

Peter schrieb:
> Da ich so wenig sprintf wie möglich benutzen will schien mir die
> Variante mit dem pointer to pointer als sinnvollste Variante.

Was hat sprintf denn damit zu tun?

> Da ich ja sonst das ganze in einer Zwischenvariable speichern müsste.

Warum?

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


Lesenswert?

Btw., ist die ungarische Notation bei euch durch irgendwen
vorgeschrieben?

Die Bezeichner, die du da produzierst, sehen ja schon fast wie C++
name mangling aus. ;-)  In der Mikrocontrollerwelt habe ich sonst noch
keinen erlebt, der freiwillig ungarische Notation nehmen würde.
(Selbst in der PC-Welt ist sie ja nun nicht gerade unumstritten.)

von Rolf Magnus (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> In der Mikrocontrollerwelt habe ich sonst noch
> keinen erlebt, der freiwillig ungarische Notation nehmen würde.

Wohlgemerkt falsche ungarische Notation.

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.