Forum: Mikrocontroller und Digitale Elektronik kann kein Array zuweisen


von Anfänger (Gast)


Lesenswert?

Ich hab eine Fifo-Klasse und muss das Array definieren. Ich bekomme das 
leider nicht hin. Beim Initialisieren vom Fifo möchte ich festlegen, wie 
groß der Fifo(Array) sein soll, weil ich welche mit unterschiedlichen 
Größen habe. Den Größenparameter übergebe ich im Konstruktor.

Ich muss das Array aber auch vorher im Header definieren, damit ich es 
anderswo einbinden kann.

Wie krieg ich das hin mit unterschiedlichen Initialwerten? Oder muss ich 
mit Konstanten arbeiten und dann z.B. fifo1.h/fifo1.cpp, 
fifo2.h/fifo2.cpp ... mit Festwerten in dem Header initialiseren? Das 
wäre ja ziemlich umständlich.


Headerdatei:
1
#ifndef FIFO_H
2
#define FIFO_H
3
4
#include "mbed.h"
5
6
// Headerdatei
7
8
class Fifo {
9
 public:
10
    uint8_t    Put  (uint16_t element);
11
    uint8_t    Get  (uint16_t  *element);
12
    void       Clear ();
13
    uint16_t   Anzahl ();
14
    uint8_t    RingBuffer(uint16_t size);
15
 private:
16
    uint16_t buffer_size;
17
    uint16_t buffer_mask;
18
    uint16_t data[buffer_size];   // <--- Hier ist der Fehler
19
    uint16_t read;
20
    uint16_t write;
21
};
22
23
#endif

cpp-Datei:
1
#include "fifo.h"
2
3
uint8_t Fifo::RingBuffer(uint16_t size) {
4
    if (size%2 != 0) { 
5
         return false;
6
    }
7
    else {
8
         read = 0;
9
         write = 0;
10
         buffer_size = size;
11
         buffer_mask = size-1;
12
         data = data[size];    // <--- Hier ist der Fehler
13
                               // wie muss ich das Array definieren?    
14
         return true;
15
    }
16
}
17
 
18
uint8_t Fifo::Put(uint16_t element) {
19
  uint8_t next = ((write + 1) & buffer_mask);
20
  if (read == next)
21
    return false;
22
  data[write] = element;
23
  // buffer.data[buffer.write & BUFFER_MASK] = element; // absolut Sicher
24
  write = next;
25
  return true;
26
}
27
 
28
uint8_t Fifo::Get(uint16_t *element) {
29
  if (read == write)
30
    return false;
31
  *element = data[read];
32
  read = (read+1) & buffer_mask;
33
  return true;
34
}
35
36
void Fifo::Clear()
37
{
38
    read = write = 0;
39
}
40
41
uint16_t Fifo::Anzahl()
42
{
43
    return (write - read) & (buffer_mask);
44
}

von Peter II (Gast)


Lesenswert?

Anfänger schrieb:
> weil ich welche mit unterschiedlichen
> Größen habe. Den Größenparameter übergebe ich im Konstruktor.

entweder mit C++ Templates arbeiten oder mit malloc den Speicher im 
Konstruktor anfordern.

von Anfänger (Gast)


Lesenswert?

meinst Du so?
1
#ifndef FIFO_H
2
#define FIFO_H
3
4
#include "mbed.h"
5
6
// Headerdatei
7
8
class Fifo {
9
 public:
10
    uint8_t    Put  (uint16_t element);
11
    uint8_t    Get  (uint16_t  *element);
12
    void       Clear ();
13
    uint16_t   Anzahl ();
14
    uint8_t    RingBuffer(uint16_t size);
15
 private:
16
    uint16_t buffer_size;
17
    uint16_t buffer_mask;
18
    uint16_t *data;
19
    uint16_t read;
20
    uint16_t write;
21
};
22
23
#endif
1
uint8_t Fifo::RingBuffer(uint16_t size) {
2
    if (size%2 != 0) { 
3
         return false;
4
    }
5
    else {
6
         read = 0;
7
         write = 0;
8
         buffer_size = size;
9
         buffer_mask = size-1;
10
         data = (uint16_t*) malloc (buffer_size);
11
         return true;
12
    }
13
}

von Peter II (Gast)


Lesenswert?

Anfänger schrieb:
> meinst Du so?

ja, denke aber ans Freigeben vom Speicher und das der Kopierkonstruktor 
und der Zuweisungsoperator jetzt für deine Klasse nicht mehr sinnvoll 
arbeiten.

von Karl H. (kbuchegg)


Lesenswert?

und anstelle von malloc benutzt du natürlich new!


Es gäbe noch eine dritte Variante.
In der stellt man sich auf den Standpunkt, dass gar nicht die FiFo 
Klasse das Array bereitstellen muss, sondern derjenige, der ein FiFo 
Objekt erzeugt dafür zuständig ist. Im Konstuktor muss man dann 
mitgeben, welches Array zu benutzen ist und dessen Länge. Das Objekt 
merkt sich dann einen Pointer auf dieses Array.

Ist nicht unbedingt schön und geht auch ein wenig am OOP Prinzip vorbei.

von Karl H. (kbuchegg)


Lesenswert?

>
1
> uint8_t Fifo::RingBuffer(uint16_t size) {
2
>

die Funktionalität dieser Funktion sollte besser der Konstruktor 
übernehmen.

von Peter II (Gast)


Lesenswert?

Karl Heinz schrieb:
> und anstelle von malloc benutzt du natürlich new!

was ist das gegenstück zu realloc?

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:
> Karl Heinz schrieb:
>> und anstelle von malloc benutzt du natürlich new!
>
> was ist das gegenstück zu realloc?

gibt es nicht.

Array wegwerfen und neu allokieren. Hat dann auch den Vorteil, dass 
entsprechende Konstruktoren bzw. Destruktoren aufgerufen werden, wenn es 
sich um ein Array aus einem Objekttyp handelt.

Allerdings: er wird in seinem Programm auf einem µC kein realloc 
brauchen. :-)

von Anfänger (Gast)


Lesenswert?

Karl Heinz schrieb:
> Es gäbe noch eine dritte Variante.
> In der stellt man sich auf den Standpunkt, dass gar nicht die FiFo
> Klasse das Array bereitstellen muss, sondern derjenige, der ein FiFo
> Objekt erzeugt dafür zuständig ist. Im Konstuktor muss man dann
> mitgeben, welches Array zu benutzen ist und dessen Länge. Das Objekt
> merkt sich dann einen Pointer auf dieses Array.

Ich hab mich für diese Variable entschieden, weil der Fifo auf einem 
Mikrocontroller laufen soll und mit malloc und new bin ich mir nicht so 
sicher, ob das gut ist in nem uC. Deshalb hab ich mir jetzt das 
ausgedacht:

Jetzt krieg ich aber die Fehlermeldung:

No instance of constructor Fifo::Fifo matches the argument list
uint16_t fifo_array1[FIFO1_LENGTH];

Was bedeutet denn das? Übergebe ich nicht richtig die Parameter an den 
Konstruktor?
1
#include "mbed.h"
2
#include "fifo.h"
3
4
#define FIFO1_LENGTH 01024
5
#define FIFO2_LENGTH 16384
6
7
uint16_t fifo_array1[FIFO1_LENGTH];
8
uint16_t fifo_array2[FIFO2_LENGTH];
9
10
Fifo myfifo1(&fifo_array1, FIFO1_LENGTH);
11
Fifo myfifo2(&fifo_array2, FIFO2_LENGTH); 
12
13
int main() {
14
15
16
17
}

1
#include "fifo.h"
2
3
Fifo::Fifo(uint16_t *buff, uint16_t size) {
4
    if (size%2 != 0) { 
5
         // return false;
6
    }
7
    else {
8
         read = 0;
9
         write = 0;
10
         buffer_size = size;
11
         buffer_mask = size-1;
12
         buffer_ptr = buff;
13
         // return true;
14
    }
15
}
16
 
17
uint8_t Fifo::Put(uint16_t element) {
18
  uint8_t next = ((write + 1) & buffer_mask);
19
  if (read == next)
20
    return false;
21
  *(buffer_ptr+(sizeof(uint16_t)*write) ) = element;
22
  // buffer.data[buffer.write & BUFFER_MASK] = element; // absolut Sicher
23
  write = next;
24
  return true;
25
}
26
 
27
uint8_t Fifo::Get(uint16_t *element) {
28
  if (read == write)
29
    return false;
30
  *element = *(buffer_ptr+(sizeof(uint16_t)*read));
31
  read = (read+1) & buffer_mask;
32
  return true;
33
}
34
35
void Fifo::Clear()
36
{
37
    read = write = 0;
38
}
39
40
uint16_t Fifo::Anzahl()
41
{
42
    return (write - read) & (buffer_mask);
43
}
1
#ifndef FIFO_H
2
#define FIFO_H
3
4
#include "mbed.h"
5
6
// Headerdatei
7
8
class Fifo {
9
 public:
10
    Fifo(uint16_t *buff, uint16_t size);        // Konstruktor
11
12
    uint8_t    Put  (uint16_t element);
13
    uint8_t    Get  (uint16_t  *element);
14
    void       Clear ();
15
    uint16_t   Anzahl ();
16
17
 private:
18
    uint16_t buffer_size;
19
    uint16_t buffer_mask;
20
    uint16_t *buffer_ptr;
21
    uint16_t read;
22
    uint16_t write;
23
};
24
25
#endif

von Karl H. (kbuchegg)


Lesenswert?

Anfänger schrieb:

> Was bedeutet denn das?

Es bedeutet, dass du dir schleunigst Literatur kaufen solltest.
1
class A
2
{
3
public:
4
  A( int* dataSpace, size_t len ) : dataSpace_( dataSpace ), len_( len ) {};
5
6
  void setElement( size_t index, int value )
7
  int  getElement( size_t index ) const;
8
9
protected:
10
  size_t len_;
11
  int*   dataSpace_;
12
13
private:
14
  A( const A& arg );             // not implemented by intention
15
  A operator=( const A& rhs);    // not implemented by intention
16
};
17
18
19
void A::setElement( size_t index, int value )
20
{
21
  if( index < len_ )
22
    dataSpace_[index] = value;
23
}
24
25
int A::getElement( size_t index ) const
26
{
27
  if( index < len_ )
28
    return_ dataSpace[index];
29
30
  return -1;
31
}
32
33
#define DATA_LEN 8
34
35
int main()
36
{
37
  int mySpace[DATA_LEN];
38
  A myData( mySpace, DATA_LEN );
39
  int i;
40
41
  for( i = 0; i < DATA_LEN; i++ )
42
    myData.setElement( i, 2*i );
43
44
  for( i = 0; i < DATA_LEN; i++ )
45
    printf( "%d %d\n", i, myData.getElement( i );
46
}

Noch einfacher gehts nicht. Was immer du an diesem Code nicht verstehst 
ist ein Hinweis darauf, dass dir absolute Grundlagen fehlen. Auch wenn 
in Desktop-C++ Pointer nicht mehr ganz so häufig gebraucht werden, ist 
die Array-Pointer Dualität und Pointerarithmetik nach wie vor 
unabdingbares Basiswissen. Speziell wenn man aufgrund 
Nebenbeschränkungen dynamische Speicherallokierung nicht benutzen 
will/kann und daher auch nicht die STL Containerklassen benutzen kann.

von gonso (Gast)


Lesenswert?

Karl Heinz schrieb:
> Noch einfacher gehts nicht. Was immer du an diesem Code nicht verstehst
> ist ein Hinweis darauf, dass dir absolute Grundlagen fehlen.

Mag sein, aber ein Fifo ist das nicht und der TE will einen Fifo haben.

Hier fehlt ein Semikolon:
1
  void setElement( size_t index, int value )  ;

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

gonso schrieb:
> Mag sein, aber ein Fifo ist das nicht und der TE will einen Fifo haben.

Das will er in seinem zweiten parallelen Thread.

von Karl H. (kbuchegg)


Lesenswert?

gonso schrieb:
> Karl Heinz schrieb:
>> Noch einfacher gehts nicht. Was immer du an diesem Code nicht verstehst
>> ist ein Hinweis darauf, dass dir absolute Grundlagen fehlen.
>
> Mag sein, aber ein Fifo ist das nicht und der TE will einen Fifo haben.

Schön.
Dann soll er einen schreiben.
Ich bin nicht sein persönlicher unentgelticher "Schreib mal Code für 
mich". Ich zeig ihm gerne das, was ihm syntaktisch fehlt, aber umsetzen 
muss er es alleine.


> Hier fehlt ein Semikolon:

Gratulation. Soll vorkommen, dass man kleinere Syntaxfehler macht, wenn 
man Code direkt hier eintippt.

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.