Forum: Compiler & IDEs sizeof Frage


von flyingwolf (Gast)


Lesenswert?

Warum liefert sizeof(sendstring) den Wert 2?

sowohl bei:
void can_send_mg (char sendstring[8], long msid, int m_box)
{
AnzZeichen=sizeof(sendstring);
...

als auch bei:
void can_send_mg (char *sendstring, long msid, int m_box)
{
AnzZeichen=sizeof(sendstring);
...


can_send_mg ("TestMB01", 8192 + Controller_ID,14);

von OldBug (Gast)


Lesenswert?

>void can_send_mg (char sendstring[8], long msid, int m_box)

AFAIK ist es nicht möglich, so Speicher für ein Array zu reservieren!
Überlege mal, wie ein Prototyp einer solchen Funktion aussehen würde
und was Du (genau genommen) dieser Funktion in jedem Fall übergeben
müsstest. Das 'char sendstring[8]' wird hier wohl auf 'char
sendstring[]' reduziert, was 'char *sendstring', und damit einem
Pointer, entspricht. Ein Pointer des Typs 'char *' benötigt zwei
Bytes Platz im RAM.
Es ist übrigens Grundsätzlich schlecht array 'by Value' übergeben zu
wollen. Besser ist es, die Daten des Arrays 'by reference' zu
übergeben und nötigenfalls zu kopieren, wobei das Kopieren relativ
Zeitinsiv sein dürfte.

von Daniel (Gast)


Lesenswert?

@ flyingwolf

Das problem ist einfach, dass Du mit sizeof(sendstring) immer die Größe
der Variable "sendstring" im Speicher bestimmst. Diese Variable ist
aber ein Zeiger auf den Anfang Deines definierten Arrays. Zeiger
wiederum sind bei dem von Dir verwendeten Compiler anscheinend 16 bit
(2 byte) lang.

Wenn Du wirklich die Länge eines Strings bestimmen willst, dann geht
afaik nur bei 0-terminierten Strings, sprich welche, bei denen das
letzte Zeichen 0x00 ist. Macht man dann so :

uint8_t ui8StringLength;
for (ui8StringLength=0; sendstring[ui8StringLength];
ui8StringLength++);

Nach diesen Zeilen steht in der Variable ui8StringLength die Länge
Deines Strings.

@oldbug
So Konstruktionen sind glaube ich schon möglich, aber frag' mich bloß
nicht, ob das nur bei manchen Compilern geht oder ob es Standard in C
ist. Nix genaues weiß ich nicht.

MfG, Daniel

von flyingwolf (Gast)


Lesenswert?

...Es ist übrigens Grundsätzlich schlecht array 'by Value'????
übergeben zu wollen.

Bezieht sich das auf char sendstring[8]? Das war nur ein Versuch weil
ich mir erhofft habe damit die richtige Länge des Strings zu
rückgeliefert zu bekommen.

... Besser ist es, die Daten des Arrays 'by reference' zu
übergeben und nötigenfalls zu kopieren, wobei das Kopieren relativ
Zeitinsiv sein dürfte.

Das bedarf einer näheren Erklärung.

Welchen Weg gibt es, zu erfahren, wieviele Zeichen *sendstring enthält?

von OldBug (Gast)


Lesenswert?

Nene :-)

Ich hab das schon so halbwegs überprüft. Allerdings hab ich mir nicht
die Speicherauslastung beim Betreten der Funktion angeschaut, weshalb
ich eigentlich nur vermuten kann, daß die 8 Bytes gar nicht erst
reserviert werden.

Hier ein Beispiel:

#include <stdio.h>

void foo(unsigned char *);
unsigned char baz[8], src[] = "TestMB01";

int
main(void)
{
        foo(src);

        return 0;
}

void
foo(unsigned char bar[8])
{
        unsigned char bay[8];
        printf("bar has %d bytes\n"
               "content consists of %d bytes\n"
               "baz and bay have %d and %d bytes and no content\n",
               sizeof(bar), strlen(bar), sizeof(baz), sizeof(bay));
        printf("btw: bar points to %p and src to %p\n",
               bar, src);
}

Kompilieren mit:

  $ gcc -O -ggdb -o foo.exe foo.c

Ausgabe:

bar has 4 bytes
content consists of 8 bytes
baz and bay have 8 and 8 bytes and no content
btw: bar points to 00402010 and src to 00402010

Wie man sehr schön erkennen kann zeigt 'bar' auf 'src' und nicht
auf neu reservierten Speicher!

von mthomas (Gast)


Lesenswert?

Uebergabe von Arrays in C m.W. immer "by reference".
Laengenangabe ([8]) bei ersten Aufruf macht wenig Sinn (ohnehin
implizit Pointer). Wenn man wirklich einen String (="null
terminiert") senden will, ist die Laenge des Strings mit strlen
ermittelbar. Im Zweifel fuer CAN auf 8 Zeichen begrenzen. Ansonsten
Anzahl Zeichen (wird DLC) als Parameter zur Funktion mituebergeben.
Alternativ: ein "can_msg-Struct" als Parameter und DLC-Wert/DTA-Feld
vor dem Aufruf anlegen und (pointer auf) Struct-Objekt uebergeben.
Vorgehensweise ueber struct oft effektiver, da der Compiler auf Offsets
optimieren kann und nicht viele Regsiter fuer Parameter verwalten muss.

von flyingwolf (Gast)


Lesenswert?

@Daniel
Sorry, Dein Post stand noch nicht bei mir drin, als ich die Antwort
geschrieben habe.

@all
erst mal Danke. ich werd es mal mit strlen probieren.

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.