mikrocontroller.net

Forum: PC-Programmierung länge eines arrays wird ein element mehr als für mich erwartet


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe zwei arrays, die ich einer FUnktion Übergebe. Bei einem Array, 
wird die Anzahl der Elemente in der Funktion aber mehr.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

static void add(char* summe, const char* sum1, const char* sum2);

int main(void) {
  const char sum_1[] = {0x00, 0x10, 0x00, 0x00};
  const char sum_2[] = {0x00, 0x11, 0x12};
  char sum[1000] = {0};


  for(uint8_t x=0; x<sizeof(sum_2)/sizeof(sum_2[0]); x++)
  {
    printf("%02x ", sum_2[x]);
  }
  printf("\r\n\r\n");

  /* 1052928 */
  add(sum, sum_1, sum_2);

  return EXIT_SUCCESS;
}


static void add(char* summe, const char* sum1, const char* sum2)
{
  const uint32_t length_1 = sizeof(sum1)/sizeof(sum1[0]);
  const uint32_t length_2 = sizeof(sum2)/sizeof(sum2[0]);
  printf("length1: %d\r\n", length_1);
  printf("length2: %d\r\n", length_2);

  for(uint8_t x=0; x<length_1; x++)
  {
    printf("%02x ", sum1[x]);
  }
  printf("\r\n\r\n");
  for(uint8_t x=0; x<length_2; x++)
  {
    printf("%02x ", sum2[x]);
  }
}

Die Ausgabe sieht wie folgt aus:
00 11 12

length1: 4
length2: 4
00 10 00 00

00 11 12 00

warum ist length2 = 4?

Bevor ich das array der FUnktion übergeben habe, war es ja auch 3.

Autor: g457 (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
> static void add(char* summe, const char* sum1, const char* sum2)
> {
[..]
>  const uint32_t length_2 = sizeof(sum2)/sizeof(sum2[0]);
[..]
>  printf("length2: %d\r\n", length_2);
[..]
> length2: 4
[..]
> warum ist length2 = 4?

Weil ein Zeiger bei Dir augenscheinlich 4 Bytes lang ist. Denk drüber 
nach(!).

HTH

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
jan schrieb:
> static void add(char* summe, const char* sum1, const char* sum2)
> {
>   const uint32_t length_1 = sizeof(sum1)/sizeof(sum1[0]);
>   const uint32_t length_2 = sizeof(sum2)/sizeof(sum2[0]);

Das funktioniert nicht. Innerhalb der Funktion ist nicht bekannt, wie 
groß die Arrays sind.

Das ist eine elementare Eigenschaft von Arrays in C; wenn man die Dinger 
einer Funktion übergibt, zerfallen sie zu einem Pointer auf das erste 
Element. Die Größe muss man der Funktion als separaten Parameter 
übergeben.

Autor: foobar (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
> warum ist length2 = 4?

Weil dein Rechner 32-bit-Pointer hat: sum2 ist ein char* kein char[3]. 
Arrays werden zu Pointern reduziert, die Länge des Arrays geht dabei 
verloren und muß ggf extra übergeben werden.

Autor: loeti2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> Das ist eine elementare Eigenschaft von Arrays in C; wenn man die Dinger
> einer Funktion übergibt, zerfallen sie zu einem Pointer auf das erste
> Element. Die Größe muss man der Funktion als separaten Parameter
> übergeben.

Man kann auch die Adresse eines Arrays übergeben (in C++ als Alternative 
eine Referenz) und damit ist die Größe des Arrays in der Funktion 
bekannt.

Beispiel (C):
void dir_getfullname_buf(TCHAR (*buf)[MAX_PATH], DIRITEM item);

kann nur aufgerufen werden mit Array von genau MAX_PATH Größe:
TCHAR tmp[MAX_PATH];
dir_getfullname_buf(&tmp, item);

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> jan schrieb:
>> static void add(char* summe, const char* sum1, const char* sum2)
>> {
>>   const uint32_t length_1 = sizeof(sum1)/sizeof(sum1[0]);
>>   const uint32_t length_2 = sizeof(sum2)/sizeof(sum2[0]);
>
> Das funktioniert nicht. Innerhalb der Funktion ist nicht bekannt, wie
> groß die Arrays sind.

Die Größe ist zwar nicht bekannt, aber das ist nicht der Grund, warum 
das falsche rauskommt. Das liegt eher daran, dass es ein ganz anderer 
Typ ist.

> Das ist eine elementare Eigenschaft von Arrays in C; wenn man die Dinger
> einer Funktion übergibt, zerfallen sie zu einem Pointer auf das erste
> Element. Die Größe muss man der Funktion als separaten Parameter
> übergeben.

Anders gesagt: Der Parameter ist kein Array, sondern ein Zeiger. Steht 
ja auch so da: "const char* sum1" ist ein Zeiger auf einen const char. 
Damit gibt sizeof auch die Größe eines Zeigers auf const char zurück. 
Dass dieser auf den Anfang eines Arrays zeigt, spielt da gar keine 
Rolle.

loeti2 schrieb:
> Man kann auch die Adresse eines Arrays übergeben (in C++ als Alternative
> eine Referenz) und damit ist die Größe des Arrays in der Funktion
> bekannt.

Die Größe ist dann bekannt, aber nur weil sie explizit Teil des 
Parametertyps ist. Damit ist sie auch von der Funktion fest vorgegeben. 
Wenn man ein Array einer anderen Größe übergeben will, muss man erst die 
Funktion ändern.

Autor: Rufus Τ. F. (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
loeti2 schrieb:
> Man kann auch die Adresse eines Arrays übergeben (in C++ als Alternative
> eine Referenz) und damit ist die Größe des Arrays in der Funktion
> bekannt.

Nicht wirklich, denn Du definierst die Funktion so, daß sie einen 
Pointer auf ein Array dieser Größe erwartet.

Das ist was anderes als einer Funktion ein Array beliebiger Größe so 
übergeben zu können, so daß die Funktion herausfinden kann, wie groß 
das Array jeweils ist.

Autor: foobar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Generell: sizeof wird vom Compiler während der Compilierung zu einer 
Konstanten und kann daher nie eine dynamische (d.h. zur Runtime 
berechnete) Größe liefern.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
foobar schrieb:
> Generell: sizeof wird vom Compiler während der Compilierung zu einer
> Konstanten und kann daher nie eine dynamische (d.h. zur Runtime
> berechnete) Größe liefern.

Stimmt auch nicht ganz. Es gibt eine Ausnahme, nämlich VLAs:
void function(int count)
{
    int array[count];
    printf("%zd\n", sizeof array);
}

Autor: jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
dass die länge in der Funktion nicht bekannt ist, habe ich verstanden. 
Übergebe jetzt auch die länge mit. Allerdings habe ich ein seltsames 
auftreten, welches ich wieder nicht verstehe
static void add(char* summe, const uint8_t* length, const char sum1[], const uint8_t length1, const char sum2[], const uint8_t length2)
{
  uint16_t temp = 0;
  uint8_t overflow = 0;
  for(uint8_t x=0; x<length2; x++)
  {
    printf("sum2[%d] = %04x \r\n", length2-1-x, (uint16_t)sum2[length2-1-x]);
  }
  printf("\r\n");
  for(uint8_t x=0; x<length2; x++)
  {
    temp = (uint16_t)sum1[length1-1-x] + (uint16_t)sum2[length2-1-x] + (uint16_t)overflow;
    summe[5-x] = (uint8_t)temp;
    overflow = (uint8_t)(temp >> 8);

    printf("%04x %04x %04x\r\n", (uint16_t)sum1[length1-1-x], (uint16_t)sum2[length2-1-x], (uint16_t)overflow);
  }
}
const char sum_1[] = {0x10, 0x20, 0x30, 0x40};
const char sum_2[] = {0x11, 0x11, 0x11};

Was ich nicht verstehe, ist die zweite Ausgabe. Die absolute Ausgabe 
sieht wie folgt aus
sum2[2] = 0011
sum2[1] = 0011
sum2[0] = 0011

0040 0011 0000
0030 0051 0000
0020 ff81 00ff

Im ersten Block lasse ich mir den Inhalt von sum2 ausgeben. Das passt.
Im zweiten lasse ihc mir den Inhalt von sum1 und sum2 ausgeben. Warum 
passen die Werte von sum2 hier nicht mehr? (also warum 0051 und ff81?)
Das verstehe ich nicht.
Ich ändere den Wert doch gar nicht und bei der ersten Ausgabe wird es 
auch richtig gegeben.

Ziel ist es zum schluss den array summe als Ergebnis mit
summe[] = {0x00, 0x10, 0x31,0x41, 0x51}; zu bekommen

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie rufst du die Funktion auf?

Wie sind dort die Variablen definiert.

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich ändere den Wert doch gar nicht [..]

Doch. Wo kommt der Speicher für
    char* summe
her?

>  for(uint8_t x=0; x<length2; x++)
[..]
>    summe[5-x] = (uint8_t)temp;

Und wie weisst Du dass length2 immer kleiner oder gleich 5 ist?

> sum2[length2-1-x]

..und Du wirst Dich wesentlich leichter tun wenn Du die (vermutlich 
arbitrary-length-)Zahlen-Arrays als little endian interpretierst, also 
LSB auf Index 0.

Autor: jan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk B. schrieb:
> Wie rufst du die Funktion auf?
>
> Wie sind dort die Variablen definiert.
const char sum_1[] = {0x10, 0x20, 0x30, 0x40};
const char sum_2[] = {0x11, 0x11, 0x11};
char summe[5] = {0};
const uint8_t length_1 = sizeof(sum_1)/sizeof(sum_1[0]);
const uint8_t length_2 = sizeof(sum_2)/sizeof(sum_2[0]);
uint8_t length=0;
add(summe, &length, sum_1, length_1, sum_2, length_2);

g457 schrieb:
> Und wie weisst Du dass length2 immer kleiner oder gleich 5 ist?

Das weiß ich noch nicht. Das käme im nächsten schritt. Zunächst weiß ich 
es nur, da ich es so definiert habe. Eigentlich wäre summe eins größer, 
als sum_1 oder sum_2 (je nachdem welcher größer ist).

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> char summe[5] = {0};
[..]
>  for(uint8_t x=0; x<length2; x++)
[..]
>    summe[5-x] = (uint8_t)temp;

array-inde-xout-of-bounds. Meine anderen Vorschläge oben solltest Du 
dringend in Erwägung ziehen.

Autor: Peter Petersson (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Als ich las, du übergibst ein Array an eine Funktion war schon klar wo 
dein Fehler ist. Das ist nämlich in C nicht möglich.

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.

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