Pointerrückgabe C Funktion unklar

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

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.

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.