Go Down

Topic: 2 gleichnamige Funktionen in der Library (Read 1 time) previous topic - next topic

spaceball

Hallo,
ich versuch mich gerade mit Pointern anzufreunden und studier deshalb grad eine Library für die RTC  DS1307.
Darin hab ich nun 2 gleichnamige Funktionen gefunden, wobei eine die andere aufzurufen scheint.
Code: [Select]

void DS1307::get(uint8_t *sec, uint8_t *min, uint8_t *hour, uint8_t *day, uint8_t *month, uint16_t *year)
{
  //get time and date
  Wire.beginTransmission(DS1307_ADDR);
  Wire.send(0x00);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDR, 7);
  *sec   = bcd2bin(Wire.receive() & 0x7F);
  *min   = bcd2bin(Wire.receive());
  *hour  = bcd2bin(Wire.receive());
           bcd2bin(Wire.receive()); //day of week
  *day   = bcd2bin(Wire.receive());
  *month = bcd2bin(Wire.receive());
  *year  = bcd2bin(Wire.receive()) + 2000;

  return;
}


void DS1307::get(int *sec, int *min, int *hour, int *day, int *month, int *year)
{
  return get((uint8_t*)sec, (uint8_t*)min, (uint8_t*)hour, (uint8_t*)day, (uint8_t*)month, (uint16_t*)year);
}


Was ist der Sinn und wie funktioniert dies????
Müßte nicht eine Funktion allein reichen?
Wieso wird in der zweiten Funktion bei
Code: [Select]
(uint8_t*)sec
die Klammer gesetzt?

Danke im Voraus für Eure Hilfe!
Reinhard

hammerhai

Die zwei Funktionen haben zwar den gleichen Namen aber eine unterschiedliche Signatur, d.h. Anzahl und / oder Typen der Parameter sind verschieden. Dadurch kann der Compiler die auseinanderhalten, sind praktisch zwei verschiedene Funktionen.

Die Klammer-Schreibweise ist ein sog. Type-Casting, da wird ein Wert eines Typs in einen anderem umgewandelt (gecastet).
Die obere Funktion verlangt die Parameter im Typ uint8_t (irgend ein spezieller Typ der irgendwo definiert wurde, ich nehme mal un unsigned (vorzeichenlos) integer 8 bit), die untere Funktion hat die Werte aber im Typ int (genau genommen jeweils Zeiger auf ..).
Das passt erst mal nicht zusammen, muss also gecastet werden. Wobei theoretisch der Wertebereich beim int höher sein dürfte als beim uint8_t, das Casten also nicht ganz sauber ist, da aber als Werte bei Skunde, Minute etc. soweiso keine höheren Werte als 255 auftreten können passt das hier schon.

voithian

#2
Nov 03, 2011, 10:09 am Last Edit: Nov 03, 2011, 10:56 am by voithian Reason: 1

ich versuch mich gerade mit Pointern anzufreunden...

Löblich, oder verwerflich (je nach persönlicher Einstellung). Man kann mit so einem Pointer irrtümlich ganz beliebig irgendwo hinschreiben ;)
Quote

Darin hab ich nun 2 gleichnamige Funktionen gefunden, wobei eine die andere aufzurufen scheint.
Code: [Select]

void DS1307::get(uint8_t *sec, uint8_t *min, uint8_t *hour, uint8_t *day, uint8_t *month, uint16_t *year)
{
...
 return;
}


void DS1307::get(int *sec, int *min, int *hour, int *day, int *month, int *year)
{
 return get((uint8_t*)sec, (uint8_t*)min, (uint8_t*)hour, (uint8_t*)day, (uint8_t*)month, (uint16_t*)year);
}


Was ist der Sinn und wie funktioniert dies????

Das Stichwort lautet (Funktions-)Überladung. Dabei können mehrere Funktionen den gleichen Namen haben. Sie müssen sich nur im Typ und/oder der Anzahl der übergebenen Parameter unterscheiden (im Beispiel einmal Pointer auf 8-Bit-Werte und einmal Pointer auf 16-Bit-Werte).  Auf diese Weise kann der Ersteller der Library für seine Nutzer spezialisierte Versionen einer Funktion zur Verfügung stellen. Man stelle sich zum Beispiel eine Funktion mit Namen Multi() vor, die einmal zur Multiplikation von 8-Bit int-Werten oder zur Multiplikation von 16-Bit int-Werten oder zur Multiplikation von float-Werten dienen kann. Es gäbe dann drei Funktionen, die alle Multi heißen, sich aber im Typ der Parameter unterscheiden würden.
Quote

Müßte nicht eine Funktion allein reichen?

Kommt drauf an. Braucht man nur eine Version, dann ja. Möchte man unterschiedliche Versionen zur Verfügung stellen, dann nein.
Dann könnte man zwar auch komplett unterschiedliche Versionen schreiben, aber der Aufwand wäre natürlich größer. Hier in diesem Fall wird die 1. Version von get() praktisch "recycelt", um ohne großen Aufwand eine 2. Version zu schaffen.
Quote

Wieso wird in der zweiten Funktion bei
Code: [Select]
(uint8_t*)sec
die Klammer gesetzt?

Die zweite Funktion get() hat ja Pointer auf int-Werte als Parameter. Da in der 2. Funktion aber die ursprüngliche 1. Version mit Pointern auf 8-Bit-Werte aufgerufen wird, muss mit (uint8_t*) der Datentyp des Parameters auf uint8_t* gewandelt werden, damit "es passt". Diese Kontruktion nennt man "cast". Damit wird also der übergebene Datentyp "pointer auf int" bei der 2. Version von get() auf den Datentyp "pointer auf "uint8_t" gewandelt.
Quote

Danke im Voraus für Eure Hilfe!

Bitte, gern geschehen.
Wolfgang

Edit: Da war wohl jemand schneller. Aber ich war ausführlicher ;)

spaceball

Danke!

Das bringt mich auf dem Pfad der Erleuchtung schon ein gutes Stück weiter.
Besonders die Sache mit den verschiedenen Funktionen unter dem selben Namen!

Könnt Ihr Literatur über solche und andere Feinheiten der Arduino-Programmierung empfehlen ( Buch, aber auch Web-Tutorial)?

thx Reinhard

hammerhai

Das ist ja eher nicht Arduino-typisch sondern ganz klassisch C. Der "normale" Arduino-Nutzer soll sich mit Pointern etc. ja gar nicht rumärgern müssen.

Go Up