Forum: Mikrocontroller und Digitale Elektronik Pointerrückgabe C Funktion unklar


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.
von C. L. (calle)


Bewertung
0 lesenswert
nicht lesenswert
Hi!

Ich komme nicht ganz klar mit dem Übergeben und der Rückgabe von 
Pointern einer C Funktion.
Alles was ich machen will ist ein übergebenes Byte in einer Funktion zu 
drehen und es wieder zurückzugeben.
Ich habe ein Array mit 12 Bytes, diese müssen alle gedreht werden (nicht 
invertiert).
Deklariert habe ich folgendes:
1
// Daten ungedreht
2
unsigned char Data[12] = {0x5B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};
3
4
// Speicher für gedrehte Daten
5
unsigned char DataGedreht[12];

Jetzt habe ich eine Routine geschrieben, welche ich das Ausgangsarray 
übergeben möchte und die Funktion soll mir dann die gedrehten Daten 
zurückschreiben in das andere Array.
Ich kriegs nicht hin; Verständnisspropobleme!
1
 unsigned char* ByteDrehen(unsigned char *byte)
2
 {
3
 unsigned char o, *DataGedreht_ = 0;
4
 
5
 for(o=0; o<=11; o++)                                        
6
            {
7
            if ((byte[o] & 0x01) == 0x01) {DataGedreht_[o] |= 0x80;}
8
            if ((byte[o] & 0x02) == 0x02) {DataGedreht_[o] |= 0x40;}
9
            if ((byte[o] & 0x04) == 0x04) {DataGedreht_[o] |= 0x20;}
10
            if ((byte[o] & 0x08) == 0x08) {DataGedreht_[o] |= 0x10;}
11
            if ((byte[o] & 0x10) == 0x10) {DataGedreht_[o] |= 0x08;}
12
            if ((byte[o] & 0x20) == 0x20) {DataGedreht_[o] |= 0x04;}
13
            if ((byte[o] & 0x40) == 0x40) {DataGedreht_[o] |= 0x02;}
14
            if ((byte[o] & 0x80) == 0x80) {DataGedreht_[o] |= 0x01;}
15
            
16
            return &DataGedreht_[o];
17
            DataGedreht_ = 0;
18
            }
19
}

in der MAIN dann aufgerufen:
1
 *DataGedreht = ByteDrehen(&Data);

Entweder meckert der Compiler mit Implicit Ptr conversion oder er weißt 
Fehler aus und compiliert nicht.
Eigentlich sollte doch bei 0x5B dann 0xDA rauskommen usw.

Kann mich mal jemadn wieder auf die Spur setzen?

CL

von Hans (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Du musst beide Zeiger an die Funktion übergeben, auf die originalen 
Daten und auf die gedrehten Daten.
1
void dreheBytes(const unsigned char *input, unsigned char *output)
2
{
3
  for (int i = 0; i < 12; ++i)
4
  {
5
    // ...
6
    output[i] = gedrehtesByte;
7
  }
8
]

Normalerweise übergibt man auch die Länge der Daten an die Funktion, 
damit sie nicht nur mit 12 Byte funktioniert, sondern universell 
einsetzbar ist.

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
C. L. schrieb:
> unsigned char o, *DataGedreht_ = 0;

Der Pointer "DataGedreht_" zeigt also auf NULL.

> DataGedreht_[o]

Da dereferenzierst Du einen Pointer, der auf NULL zeigt.

von C. L. (calle)


Bewertung
0 lesenswert
nicht lesenswert
Ok,

das heisst dann rein nur 2 mal Übergabe und nicht als klassische 
Rückgabe mit "return".
Geht denn sowas nicht als Rückgabeparameter?

Bin allerdings auch so zufrieden.

CL

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
C. L. schrieb:
> Geht denn sowas nicht als Rückgabeparameter?

Nur, wenn Du den dafür benötigten Speicher dynamisch (mit malloc & 
Co.) anforderst, oder ihn als static innerhalb der Funktion 
deklarierst. Das aber kann unappetitliche Nebenwirkungen haben, wenn die 
Funktion mehrfach aufgerufen wird und Du an den unterschiedlichen 
Stellen annimmst, der Speicher, auf den der zurückgegebene Pointer 
zeigt, wäre unverändert.

Alternativ könntest Du auch eine globale Variable dafür anlegen, aber 
das ändert am Problem nichts und ist obendrein auch noch Pfusch und 
Murks.

von C. L. (calle)


Bewertung
1 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> Pfusch und
> Murks.

;-) neee, das wollen wir ja nicht und es ist obendrein auch ziemlich 
kompliziert. Liegt aber auch an meinem Verständniss über Zeiger.
Da ist noch Luft nach oben. ;-)
Habe das dann mit den beiden Pointerübergaben im Aufruf gelöst.
Funktiniert auch!

Danke Euch.

CL

von Hans (Gast)


Bewertung
0 lesenswert
nicht lesenswert
C. L. schrieb:
>
> Geht denn sowas nicht als Rückgabeparameter?
>

Wenn Du einen Zeiger zurückgibst, ist das einfach nur eine 
Speicheradresse, also eine Zahl. Du willst aber 12 Byte zurückgeben.

Es gäbe noch zwei andere Möglichkeiten:

1. Du gibst ein struct mit einem 12-Byte-Array zurück. Das ist 
allerdings unflexibel, weil die Funktion dann nur exakt 12 Byte 
zurückgeben kann und keine andere Längen. Je nachdem was Compiler draus 
macht, kann es auch ineffizienter sein, wenn die Daten nochmal umkopiert 
werden.

2. Du holst Dir mit malloc() 12 Byte dynamischen Speicher und gibst den 
Zeiger darauf zurück. Dann muss der Aufrufer der Funktion allerdings 
dran denken, den Speicher mit free() wieder freizugeben. Außerdem ist 
malloc() recht teuer, gerade auf einem Mikrocontroller.

Daher geht man in C meistens lieber den Weg, der Funktion einen Zeiger 
auf den Speicherbereich zu übergeben, in den sie ihre Daten schreiben 
soll.

von malsehen (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Meines Erachtens bearbeitet die Schleife aber nur

byte[0]

da

return &DataGedreht_[o];

in der Schleife steht.

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Ja, aber bereits DataGedreht_[0] ist ungültig.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Hans schrieb:
> Du musst beide Zeiger an die Funktion übergeben, auf die originalen
> Daten und auf die gedrehten Daten.

Ich würd nochmal genau überlegen, ob die alten Daten danach überhaupt 
noch gebraucht werden. Oftmals reicht nämlich ein Pointer und man 
überschreibt einfach die alten Daten.

von C. L. (calle)


Bewertung
0 lesenswert
nicht lesenswert
Ja, das könnte man so machen und sich ein Pointer sparen.
In diesem Fall hätte ich es aber nicht machen wollen, denn die Daten im 
Ausgangsarray werden immer wieder so benötigt.
Darauf hatte ich aber nicht hingewiesen.

CL

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Du könntest auch dein Problem in Teilprobleme gliedern und somit auch 
"Sauberkeit" im Code halten.

Falls du es mit Zeigern lösen möchtest, dann hätte ich dir folgendes 
Bsp.:
1
void byte_rotate(uint8_t src, uint8_t *dst)
2
{
3
  uint8_t i;
4
5
  for(i=0; i<7; i++)
6
  {
7
    *dst |= (src & 0x01);
8
    *dst = (*dst << 1);
9
    src = (src >> 1);
10
  }
11
12
  *dst |= (src & 0x01);
13
}
14
15
void array_rotate(const uint8_t *input, uint8_t *output, size_t size)
16
{
17
  uint8_t i;
18
19
  for(i=0; i<size; i++)
20
  {
21
    byte_rotate(input[i], &output[i]);
22
  }
23
}

Aufruf:
1
#define BUF_SIZE    12
2
3
uint8_t buf_orig[BUF_SIZE];
4
uint8_t buf_rotate[BUF_SIZE];
5
6
array_rotate(buf_orig, buf_rotate, BUF_SIZE);


Es gibt mehrere Lösungen das Byte zu rotieren, somit musst du nicht 
diese nehmen, ich finde es mit der Schleife nur "schöner" als in deinem 
ersten Beitrag.

Gruß

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]
  • [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.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

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