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


von jan (Gast)


Lesenswert?

Hallo,
ich habe zwei arrays, die ich einer FUnktion Übergebe. Bei einem Array, 
wird die Anzahl der Elemente in der Funktion aber mehr.
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4
5
static void add(char* summe, const char* sum1, const char* sum2);
6
7
int main(void) {
8
  const char sum_1[] = {0x00, 0x10, 0x00, 0x00};
9
  const char sum_2[] = {0x00, 0x11, 0x12};
10
  char sum[1000] = {0};
11
12
13
  for(uint8_t x=0; x<sizeof(sum_2)/sizeof(sum_2[0]); x++)
14
  {
15
    printf("%02x ", sum_2[x]);
16
  }
17
  printf("\r\n\r\n");
18
19
  /* 1052928 */
20
  add(sum, sum_1, sum_2);
21
22
  return EXIT_SUCCESS;
23
}
24
25
26
static void add(char* summe, const char* sum1, const char* sum2)
27
{
28
  const uint32_t length_1 = sizeof(sum1)/sizeof(sum1[0]);
29
  const uint32_t length_2 = sizeof(sum2)/sizeof(sum2[0]);
30
  printf("length1: %d\r\n", length_1);
31
  printf("length2: %d\r\n", length_2);
32
33
  for(uint8_t x=0; x<length_1; x++)
34
  {
35
    printf("%02x ", sum1[x]);
36
  }
37
  printf("\r\n\r\n");
38
  for(uint8_t x=0; x<length_2; x++)
39
  {
40
    printf("%02x ", sum2[x]);
41
  }
42
}

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.

von g457 (Gast)


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

von Rufus Τ. F. (rufus) Benutzerseite


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.

von foobar (Gast)


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.

von loeti2 (Gast)


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):
1
void dir_getfullname_buf(TCHAR (*buf)[MAX_PATH], DIRITEM item);

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

von Rolf M. (rmagnus)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von foobar (Gast)


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.

von Rolf M. (rmagnus)


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:
1
void function(int count)
2
{
3
    int array[count];
4
    printf("%zd\n", sizeof array);
5
}

von jan (Gast)


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
1
static void add(char* summe, const uint8_t* length, const char sum1[], const uint8_t length1, const char sum2[], const uint8_t length2)
2
{
3
  uint16_t temp = 0;
4
  uint8_t overflow = 0;
5
  for(uint8_t x=0; x<length2; x++)
6
  {
7
    printf("sum2[%d] = %04x \r\n", length2-1-x, (uint16_t)sum2[length2-1-x]);
8
  }
9
  printf("\r\n");
10
  for(uint8_t x=0; x<length2; x++)
11
  {
12
    temp = (uint16_t)sum1[length1-1-x] + (uint16_t)sum2[length2-1-x] + (uint16_t)overflow;
13
    summe[5-x] = (uint8_t)temp;
14
    overflow = (uint8_t)(temp >> 8);
15
16
    printf("%04x %04x %04x\r\n", (uint16_t)sum1[length1-1-x], (uint16_t)sum2[length2-1-x], (uint16_t)overflow);
17
  }
18
}
1
const char sum_1[] = {0x10, 0x20, 0x30, 0x40};
2
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

von Dirk B. (dirkb2)


Lesenswert?

Wie rufst du die Funktion auf?

Wie sind dort die Variablen definiert.

von g457 (Gast)


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.

von jan (Gast)


Lesenswert?

Dirk B. schrieb:
> Wie rufst du die Funktion auf?
>
> Wie sind dort die Variablen definiert.
1
const char sum_1[] = {0x10, 0x20, 0x30, 0x40};
2
const char sum_2[] = {0x11, 0x11, 0x11};
3
char summe[5] = {0};
4
const uint8_t length_1 = sizeof(sum_1)/sizeof(sum_1[0]);
5
const uint8_t length_2 = sizeof(sum_2)/sizeof(sum_2[0]);
6
uint8_t length=0;
7
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).

von g457 (Gast)


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.

von Peter Petersson (Gast)


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.

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.