Forum: Mikrocontroller und Digitale Elektronik Array einer Variable übergeben in C


von Hans (Gast)


Lesenswert?

Hi zusammen

Ich möchte ein Array einer Variable übergeben und bekomme es aufgrund 
der verlangten Arraygrösse durch den Compiler nicht hin.

Um ein Array zurück zu geben, muss man sich einem Trick bedienen.
Dazu habe ich ein struct definiert. Ich habe das irgendwo aus dem 
Internet.
Mein Ziel ist es ein Summenarrayaus 3 verschiedenen Arrays  zu bilden .
Die Summe soll aber nur zwischen limitIndexLeft und Right gebildet 
werden.
Das ist also auch letztendlich meine tatsächliche Arraylänge.
Im Main habe ich aber das Problem, dass ich nie weiss wie lang das Array 
ist, da limitIndexLeft und Right unterschiedlich sein können. Wenn ich 
den Array im struct einfach gross genug mache, funktioniert das auch 
nicht. Das bringt ja auch nichts, da ich ja die Länge der beiden Arrays 
direkt verändere. Also die des zurückgegebenen und die des neuen im 
main, da beide selbige Variable nutzen.
Wie löse ich das am Besten?
1
im h-file
2
#define MAXARRAYLENGTH   150
3
typedef struct array 
4
{
5
  uint16_t array[MAXARRAYLENGTH]; 
6
}Array_t;
7
8
im c.file
9
Array_t getSumArrayValues(uint16_t *array1, uint16_t *array2, uint16_t *array3) 
10
{  
11
  Array_t sumArray;   
12
  
13
  for(uint8_t i = limitIndexLeft; i <= limitIndexRight; i++)
14
  {
15
    sumArray.array[i] = array1[i] + array2[i] + array3[i];
16
  }
17
  
18
  return sumArray; 
19
}
20
21
im main:
22
23
    sumArray.array = TSC_getSumArrayValues(arraydiffLS1, arraydiffLS2, arraydiffLS3);     
24
25
C-Code

von Karl M. (Gast)


Lesenswert?

Hallo,

vielleicht solltest Du nachmal nachdenken, was dies bedeutet:
1
typedef struct array 
2
{
3
  uint16_t array[MAXARRAYLENGTH]; 
4
} Array_t;

Warum nicht so etwas?
1
typedef uint16_t array_t[MAXARRAYLENGTH];

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

1
void getSumArrayValues(uint16_t *array1, uint16_t *array2, uint16_t *array3, uint16_t * sumArray) 
2
{
3
  uint8_t t = 0;
4
5
  for(uint8_t i = limitIndexLeft; i <= limitIndexRight; i++)
6
  {
7
    sumArray[t++] = array1[i] + array2[i] + array3[i];
8
  }
9
}

in main:
1
    uint16_t sumArray[limitIndexRight - limitIndexLeft + 1];
2
3
    sumArray.array = TSC_getSumArrayValues(arraydiffLS1, arraydiffLS2, arraydiffLS3, sumArray);

1. sumArray wird in main(!) dynamisch erzeugt und nicht in der
   Summenfunktion.

2. Es werden die Indexlimits beachtet.

3. Der Zähler t sorgt dafür, dass der Index bei 0 beginnt.

4. Eine zusätzliche Struct als "Trick" wird nicht verwendet

: Bearbeitet durch Moderator
von Hans (Gast)


Lesenswert?

Vielen Dank

Das funktioniert bei mir jetzt.
Nun frage ich mich aber, warum die Länge meines sumarrays nicht richtig 
ausgegeben wird.

Das sollte so doch gehen, bekomme aber den Wert = 2?!
1
ausserhalb main:
2
uint16_t val = 0;
3
4
c file
5
void calcSumArrayValues(uint16_t *array1, uint16_t *array2, uint16_t *array3, uint16_t *sumArray) 
6
{  
7
  uint8_t t= 0;
8
  
9
  for(uint8_t i = limitIndexLeft; i < limitIndexRight; i++)
10
  {
11
    sumArray[t++] = array1[i] + array2[i] + array3[i];
12
  }
13
}
14
15
uint16_t getArrayLength(uint16_t *array)
16
{  
17
  uint16_t arrayLength;   
18
  
19
  arrayLength = sizeof(array)/sizeof(array[0]);
20
  
21
  return arrayLength; 
22
}
23
24
im main:
25
26
uint16_t sumArray[limitIndexRight - limitIndexLeft]; 
27
  
28
calcSumArrayValues(arraydiffLS1, arraydiffLS2, arraydiffLS3, sumArray);     
29
val = getArrayLength(sumArray);

von Stefan F. (Gast)


Lesenswert?

Hans schrieb:
> uint16_t getArrayLength(uint16_t *array)
> {
>   ... sizeof(array)
> }

Du übergibst der Funktionen einen Zeiger auf ein Array und fragst dann 
dessen Größe ab. Des geht deswegen nicht, weil Arrays keine 
Größeninformation enthalten.

Die Größe musst du als zweiten Parameter übergeben, so wie es zum 
Beispiel auch bei memcpy() gemacht wird.

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


Lesenswert?

Hans schrieb:
> getArrayLength(uint16_t *array)
> {
>   uint16_t arrayLength;
>
>   arrayLength = sizeof(array)/sizeof(array[0]);

Welchen Datentyp hat "array"? Wie groß ist er?
Welchen Datentyp hat "array[0]"? Wie groß ist er?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hans schrieb:
> val = getArrayLength(sumArray);

Wie oben schon angedeutet: sizeof() liefert bei Pointern nicht die Größe 
des Arrays, sondern die Speichergröße des Pointers. Auf einem AVR sind 
das 2 Bytes, auf 32-Bit-Systemen in der Regel 4 Bytes.

Schreibe doch einfach:
1
val = limitIndexRight - limitIndexLeft;

Das ist die Anzahl der Member in Deinem Summenarray. Die Funktion 
getArrayLength() kannst Du Dir komplett sparen. Denk doch nicht so 
kompliziert. ;-)

P.S.
Das obige gilt nur, wenn als Index limitIndexRight ausgeschlossen ist. 
Du hast nämlich klammheimlich die Aufgabenstellung geändert:

Vorher: Array läuft von limitIndexLeft bis limitIndexRight ínklusive.
Nachher: Array läuft von limitIndexLeft bis limitIndexRight exklusive.

Wenn inklusive, musst Du das "+ 1" wieder mit reinnehmen und in der 
for-Schleife die Bedingung wieder auf "<=" ändern.

val ändert sich dann natürlich auch:
1
val = limitIndexRight - limitIndexLeft + 1;

: Bearbeitet durch Moderator
von Hans (Gast)


Lesenswert?

Hallo zusammen

Ich denke im Moment deshalb so kompliziert, weil zur Zeit zB
limitIndexRight = 146
limitIndexLeft = 6

Das gibt eine Arraylänge von 140
Beginnend mit t=0 ergibt der letzte Index 139
Aber Index 140 ergibt jetzt bei mir so wie oben den richtigen Wert..
Das gibt es ja nicht.
Ansehen, kann ich das auch nicht wirklich direkt, weil die ArrayVariable 
in einer Funktion (main) steckt.

Und ja:
sizeof von sumArray ergbit die Speichergrösse also 140x16bits = 
280Bystes
sizeof von sumArray[0] ergibt 2 Bytes
280/2 = 140
Also warum 2?

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


Lesenswert?

Hans schrieb:
> Also warum 2?

Weil du eben nicht "sizeof(sumArray)" gemacht hast sondern 
"sizeof(array)" und "array" trotz seines verwirrenden Namens gar kein 
Array, sondern ein Zeiger ist.

von Hans (Gast)


Lesenswert?

Ok, entschuldigt micht für die Fragen, aber dann müsste aber das 
funktionieren:
im main:
uint16_t sumArray[limitIndexRight - limitIndexLeft];

calcSumArrayValues(arraydiffLS1, arraydiffLS2, arraydiffLS3, sumArray);

val = sizeof(sumArray)/sizeof(sumArray[0]);




Das Ergebnis 2 kann ich mir dann also so erklären, dass der Pointer die 
Speichergrösse 4Bytes hat und die Pointerwert array[0] = 2Bytes

4/2 gibt 2
Richtig?

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


Lesenswert?

Hans schrieb:

> val = sizeof(sumArray)/sizeof(sumArray[0]);

Warum so umständlich?

Da du das Array vorher explizit auf diese Größe festgelegt hast, genügt 
doch:
1
val = (limitIndexRight - limitIndexLeft) * sizeof(uint16_t);

> Das Ergebnis 2 kann ich mir dann also so erklären, dass der Pointer die
> Speichergrösse 4Bytes hat und die Pointerwert array[0] = 2Bytes
>
> 4/2 gibt 2
> Richtig?

So ist es.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> val = limitIndexRight - limitIndexLeft;

Jörg W. schrieb:
> val = (limitIndexRight - limitIndexLeft) * sizeof(uint16_t);

Was will der TO? Die Anzahl der Array-Member oder die Größe des 
dynamischen Arrays in Bytes?

Nach den verzweifelten Versuchen mit 
"sizeof(sumArray)/sizeof(sumArray[0])" zu urteilen, will er doch eher 
die Anzahl und nicht die Größe, oder?

Aber da könnte Hans uns mal aufklären.

: Bearbeitet durch Moderator
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Frank M. schrieb:
> will er doch eher die Anzahl und nicht die Größe, oder?

Stimmt auffallend.  Dann entfällt ja auch noch das "* sizeof(uint16_t)" 
…

von Hans (Gast)


Lesenswert?

Ich hatte geschrieben, dass mir die differenz aus rechts u links nichts 
bringt.
Da ich den wert im letzten index überprüfen wollte wollte ich es durch 
siteof ermitteln ob das auch wirklich so übernommen wurde
dass mein letzter Index 140 ist macht ja iwie keinen Sinn. Müsste ja 
nach t beginnend mit 0 höchstens 139 sein. deshalb

von Hans (Gast)


Lesenswert?

Jetzt tut es iwie.
Ich habe das Gefühl dass der uC iwie nicht richtig flasht.

von Hans (Gast)


Lesenswert?

Hans schrieb:
> Ok, entschuldigt micht für die Fragen, aber dann müsste aber das
> funktionieren:
> im main:
> uint16_t sumArray[limitIndexRight - limitIndexLeft];
> calcSumArrayValues(arraydiffLS1, arraydiffLS2, arraydiffLS3, sumArray);
> val = sizeof(sumArray)/sizeof(sumArray[0]);
>
>

Bleibt also noch warum val hier 0 ist.
Das ist nun aber wirklich kein Zeiger mehr in den ein array zerfällt..

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hans schrieb:
> dass mein letzter Index 140 ist macht ja iwie keinen Sinn. Müsste ja
> nach t beginnend mit 0 höchstens 139 sein. deshalb

val ist die Größe des Summenarrays, also 140.

Wenn Du jetzt noch in main() eine Schleife über das Summenarray machen 
möchtest:
1
    uint8_t idx;
2
3
    val = limitIndexRight - limitIndexLeft;   // val ist 140
4
5
    for (idx = 0; idx < val; idx++) // idx geht von 0 bis 139
6
    {
7
       // mache etwas mit sumArray[idx]
8
    }

Kann aber sein, dass ich noch nicht verstehe, was Du überhaupt willst.

Jetzt noch eine Bemerkung dazu:

Hans schrieb:
> Bleibt also noch warum val hier 0 ist.

Hier ein vollständig übersetzbarer Beispiel-Code:
1
#include <stdio.h>
2
#include <stdint.h>
3
4
uint16_t limitIndexLeft  = 7;
5
uint16_t limitIndexRight = 22;
6
7
int main ()
8
{
9
    uint16_t sumArray[limitIndexRight - limitIndexLeft];
10
    uint16_t val;
11
12
    val = sizeof(sumArray)/sizeof(sumArray[0]);
13
    printf ("%d\n", val);
14
    return 0;
15
}
1
$ cc a.c && ./a.out
2
15

Das funktioniert also wie erwartet.

val kann dann 0 werden, wenn limitIndexLeft == limitIndexRight.

Ich habe leider keine Ahnung, welche Werte und Typen Deine (globalen?) 
Variablen limitIndexLeft und limitIndexRight haben, denn darüber hast Du 
Dich bisher ausgeschwiegen.

von zitter_ned_aso (Gast)


Lesenswert?

Hans schrieb:
> Das ist nun aber wirklich kein Zeiger mehr in den ein array zerfällt..

Doch, das ist ein Zeiger (ein konstanter sogar).

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.