Pointerrückgabe C Funktion unklar

OP #5103876
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
Gast
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.
Persönliche Seite
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.
OP
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
Gast
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.
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.
OP
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
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

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.