Forum: PC-Programmierung C# Übergabe Char-Array sizeof wird ein Byte größer


von Marcel L. (superhans)


Lesenswert?

Hallo zusammen,

ich hab vorhin aus versehen meinen Ursprungs Beitrag verändert. Sorry 
dafür also hier nochmal die Frage:

Warum gibt mir der Sizeof Operator einmal 2 Byte zurück wenn ich ihn 
über die Funktion Aufrufe und einmal 1 Byte wenn ich Ihn aus der 
Hauptfunktion aufrufe:
1
void loop() {
2
  uint8_t WERT      [] = {0x05},
3
   Serial.println(sizeof(WERT));
4
   SendRemoteCommand(&WERT[0]);
5
}
6
void SendRemoteCommand(uint8_t *cmdValue) {
7
8
   Serial.println(sizeof(cmdValue));
9
}

: Bearbeitet durch User
von Guuuast (Gast)


Lesenswert?

was ist denn daran c#

von Tom (Gast)


Lesenswert?

Marcel L. schrieb:
> Übergebe ich WERT aber an
> eine Funktion

Du übergibst die Adresse von WERT

Marcel L. schrieb:
> Diese gibt die Anzahl der
> verwendeten Bytes für eine Variable

Und diese Variable cmdValue ist ein uint8_t*, also ein Pointer auf ein 
uint8_t.

von jois3 (Gast)


Lesenswert?

Hi,

sizeof(cmdValue) gibt Dir die Größe des Pointers zurück. Das wirst Du 
wohl nicht haben wollen. Du willst die Größe des Arrays - die aber kennt 
die Funktion an der Stelle nicht.
Mit C# übrigens hat das nix zu tun - das ist quasi nur C.

Was Du wahrscheinlich haben willst: Eine Übergabe der Größe als weiterer 
Parameter an die Funktion, oder aber (wenn schon C#) managed Strukturen 
benutzen, wie z.B. List<> (so was kannst Du dann auch ggf. in ByteArrays 
wandeln, sie bieten vorher halt den kompletten Komfort von C#).

Kommt halt drauf an, wie das am besten passt.

Gruß,

jois3

von Marcel L. (superhans)


Lesenswert?

Tom schrieb:
> Und diese Variable cmdValue ist ein uint8_t*, also ein Pointer auf ein
> uint8_t.

Aber ich Übergebe ja auch:
1
 SendRemoteCommand(&WERT[0])
Das ist doch äquivalent zu
1
 SendRemoteCommand(WERT)
 wenn ich die Funktion
1
  void SendRemoteCommand(uint8_t cmdValue[])
 so definiere oder nicht?
Wenn ich ein Array Übergebe habe ich ja automatisch call-by-reference 
und übergebe die Anfangsadresse des ersten Elementes.

jois3 schrieb:
> Was Du wahrscheinlich haben willst: Eine Übergabe der Größe als weiterer
> Parameter an die Funktion, oder aber (wenn schon C#) managed Strukturen
> benutzen, wie z.B. List<> (so was kannst Du dann auch ggf. in ByteArrays
> wandeln, sie bieten vorher halt den kompletten Komfort von C#).

Habs mit dem weiteren Parameter auspobiert. Funktioniert prima. Danke.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Marcel L. schrieb:
> Tom schrieb:
>> Und diese Variable cmdValue ist ein uint8_t*, also ein Pointer auf ein
>> uint8_t.
>
> Aber ich Übergebe ja auch:
1
 SendRemoteCommand(&WERT[0])

Ja.
Und was macht der kleine & da?
Er sorgt dafür, dass die Adresse von dem Teil rechts von ihm genommen 
und übergeben wird.
D.h. hier wird eine Speicheradresse an die Funktion übergeben. Die 
Funktion kriegt diese Adresse und speichert sie in ihrer lokalen 
Variablen, die dann eine Pointervariable sein muss. Denn genau darum 
geht es ja: Pointervariablen sind Variablen, in denen Adressen 
gespeichert werden.

> Das ist doch äquivalent zu
1
 SendRemoteCommand(WERT)

Yep. Weil bei Arrays automatisch und immer der Name des Arrays für die 
Adresse zum ersten Element des Arrays steht.

> wenn ich die
> Funktion
1
  void SendRemoteCommand(uint8_t cmdValue[])
 so
> definiere oder nicht?

Nö.
HIer definierst du was anderes.
Hier definierst du, dass die Funktion EINEN uint8_t bekommt. Also 1 
Zahenwert. Zb 25 oder 8 oder auch die 0x05, die du in deinem Array 
gespeichert hast. Der FUnktion ist es ja wurscht, wo dieser WErt 
herkommt, sie will nur den Wert haben.
1
  int i = 8;
2
  uint8_t Value[] = { 0x05 );
3
4
  SendRemoteCommand( 25 );
5
  SendRemoteCommand( i );
6
  SendRemoteCommand( 8 * i );
7
  SendRemoteCommand( Value[0] );

Im letzten Fall wurde beim Aufruf explizit gesagt, dass der Wert, der an 
die FUnktion zu übergeben ist, so bestimmt werden soll, indem im Array 
'Value' der Wert des Elements mit dem Index 0 bestimmt werden soll. 
Dieser dort abgespeicherte Wert ist 0x05 und genau der wird dann auch an 
die Funktion übereben.

Aber: Dazu musste die Funktion auch so definiert sein, dass sie einen 
derartigen Wert (einen uint8_t) übernimmt.
In diesem Beispiel ist das gut so.

Aber hier, in deinem Eröffnungsposting, war das ja eine ganz andere 
Funktion. Die sah so aus
1
void SendRemoteCommand(uint8_t * cmdValue)
diese Funktion übernimmt nicht einen uint8_t Wert.
Diese Funktion (beachte den *) übernimmt die Speicheradresse, an der der 
uint8_t zu finden ist.
D.h. du sagst beim Aufruf dann nicht mehr: Liebe Funktion, der Wert mit 
dem du arbeiten sollst ist 28.
Sondern du musst beim Aufruf sagen: Liebe Funktion, den uint8_t mit dem 
du arbeiten sollst, der findet sich im SPeicher dort und dort.
1
  int i = 28;
2
3
  SendRemoteCommand( &i );

und das ist aber was ganz anderes. Die Funktion kriegt nicht mehr die 28 
direkt in der Argumentschnittstelle. Sondern sie kriegt einen Verweis 
(die Adresse) in den Speicher, an der sie die 28 finden kann.

> Wenn ich ein Array Übergebe habe ich ja automatisch call-by-reference
> und übergebe die Anfangsadresse des ersten Elementes.

Technisch gesehen gibt es in C kein Call-By-Reference. Alle Argumente 
werden immer so übergeben, dass die Funktion eine Kopie des übergebenen 
Wertes bekommt. Man kann das natürlich benutzen um der FUnktion eine 
Speicheradresse zu übergeben, mit der sie arbeiten kann. Das simuliert 
in einem gewissen Sinne einen Call-By-Reference, aber im eigentlichen 
Sinne ist es keiner.

: Bearbeitet durch User
von Marcel L. (superhans)


Lesenswert?

Danke nochmal für die ausführliche Erklärung Karl-Heinz. Diese Zeiger 
Geschichten verfolgen mich schon ewig. Aber so langsam komm ich dahinter 
glaube ich.

von Karl H. (kbuchegg)


Lesenswert?

Marcel L. schrieb:
> Danke nochmal für die ausführliche Erklärung Karl-Heinz. Diese Zeiger
> Geschichten verfolgen mich schon ewig.

Ist doch ganz einfach.
Anstatt das du deinem Kumpel sagst "Die Anzahl an Tussis auf der Party 
ist 25", sagst du ihm: "Du kannst die Anzahl der Tussis rausfinden, 
indem du im Postkasten 12 nachsiehst. Dort findest du einen Zettel auf 
dem steht sie"

Die 12 sind die Adresse unter der die Information zu finden ist.
Wenn sich dein Kumpel diese 12 auf einen Zettel aufschreibt, dann hat er 
sich eine Pointer-Variable gebaut. Er muss sich nur merken, das nicht 
die 12 die gesuchte Information ist, sondern das es sich dabei um den 
Hinweis handelt, wo er nachsehen muss um die Information zu finden.

von Bitflüsterer (Gast)


Lesenswert?

Karl Heinz schrieb:
> Marcel L. schrieb:
>> Tom schrieb:
...
>> wenn ich die
>> Funktion
1
  void SendRemoteCommand(uint8_t cmdValue[])
 so
>> definiere oder nicht?
>
> Nö.
> HIer definierst du was anderes.
> Hier definierst du, dass die Funktion EINEN uint8_t bekommt. Also 1
> Zahenwert. Zb 25 oder 8 oder auch die 0x05, die du in deinem Array
> gespeichert hast.

Ups. Das kommt mir vor wie ein überlesenes "[]".

von Karl H. (kbuchegg)


Lesenswert?

Bitflüsterer schrieb:
> Karl Heinz schrieb:
>> Marcel L. schrieb:
>>> Tom schrieb:
> ...
>>> wenn ich die
>>> Funktion
1
  void SendRemoteCommand(uint8_t cmdValue[])
 so
>>> definiere oder nicht?
>>
>> Nö.
>> HIer definierst du was anderes.
>> Hier definierst du, dass die Funktion EINEN uint8_t bekommt. Also 1
>> Zahenwert. Zb 25 oder 8 oder auch die 0x05, die du in deinem Array
>> gespeichert hast.
>
> Ups. Das kommt mir vor wie ein überlesenes "[]".

Asche auf mein Haupt.
Das hab ich tatsächlich überlesen.
(Wohl auch, weil ich diese Notation nicht leiden kann. Sie suggeriert 
etwas, das nicht da ist)

von Marcel L. (superhans)


Lesenswert?

Karl Heinz schrieb:
> Die 12 sind die Adresse unter der die Information zu finden ist.
> Wenn sich dein Kumpel diese 12 auf einen Zettel aufschreibt, dann hat er
> sich eine Pointer-Variable gebaut. Er muss sich nur merken, das nicht
> die 12 die gesuchte Information ist, sondern das es sich dabei um den
> Hinweis handelt, wo er nachsehen muss um die Information zu finden.

Ja soweit verstehe ich das schon, allerdings kann ichs dann oft im 
Quellcode nicht anwenden.


Passt vielleich nicht in den Thread aber eine kleine weitere Frage. Gibt 
es eine Möglichkeit die Anzahl der in einem seriellen Empfangpuffer 
liegenden Bytes auszugeben. Oder müste ich die Bytes erst mit Read() 
auslesen und dann die Anzahl der Bytes bestimmen?

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.