Kleines Problem mit übergabe eines Array an eine Funktion

Hej,
hoffe ihr könnt mir mal auf die Sprünge helfen.
Ich möchte ein Array mit Variablennamen an eine Funktion übergeben.
Das funktioniert nicht. In der seriellen Ausgabe kommen für a nur 0 en.
Denke da stimmt irgend was in der Syntax nicht, komme aber nicht dahinter.

unsigned long B1off = 11025301; //101010000011101110010101
unsigned long B2off = 10869189; //101001011101100111000101
unsigned long C1on  = 11452798; //101011101100000101111110
unsigned long C2on  = 11146942; //101010100001011010111110
unsigned long C1off = 10680158; //101000101111011101011110
unsigned long C2off = 10899998; //101001100101001000011110
unsigned long D1on  = 11025303; //101010000011101110010111
unsigned long D2on  = 11236423; //101010110111010001000111
unsigned long D1off = 11084007; //101010010010000011100111
unsigned long D2off = 10700087; //101000110100010100110111
void setup() {
  Serial.begin(9600);

}

void loop() {
  unsigned long DSchalt[8] = {A1off,A2off,B1off,B2off,C1off,C2off,D1off,D2off};
  Std_Schalt(DSchalt); // Steckdosen ein senden
      
}

//Steckdosen On/Off senden
void Std_Schalt(unsigned long (DSchalt[])) {
    byte a = sizeof(DSchalt) / sizeof(DSchalt[0]);
    Serial.println(a);
    for (byte i = 0; i < a; i++) {
      Serial.println(DSchalt[i]);
      
    }
}

Hier wo ich nicht an die Funktion übergebe, da gehts.

unsigned long B1off = 11025301; //101010000011101110010101
unsigned long B2off = 10869189; //101001011101100111000101
unsigned long C1on  = 11452798; //101011101100000101111110
unsigned long C2on  = 11146942; //101010100001011010111110
unsigned long C1off = 10680158; //101000101111011101011110
unsigned long C2off = 10899998; //101001100101001000011110
unsigned long D1on  = 11025303; //101010000011101110010111
unsigned long D2on  = 11236423; //101010110111010001000111
unsigned long D1off = 11084007; //101010010010000011100111
unsigned long D2off = 10700087; //101000110100010100110111
void setup() {
  Serial.begin(9600);

}

void loop() {
  unsigned long DSchalt[8] = {A1off,A2off,B1off,B2off,C1off,C2off,D1off,D2off};
  byte a = sizeof(DSchalt) / sizeof(DSchalt[0]);
    Serial.println(a);
    for (byte i = 0; i < a; i++) {
      Serial.println(DSchalt[i]);
      
  }
}

Ausgabe

8
10591628
10792492
11025301
10869189
10680158
10899998
11084007
10700087
usw.

Beim Cast zu einem Zeiger verliert es die Arraygröße!
Also entweder die größe im C Stil mitgeben, oder den Datentype(zumindest die Größe) im C++ Stil mit übergeben.

Mal abgesehen davon, dass von dem Code etwas fehlt, so kann byte a = sizeof(DSchalt) / sizeof(DSchalt[0]); nicht funktionieren, weil nur ein Zeiger übergeben wird. Innerhalb der Funktion kannst Du die Größe des Arrays so nicht ermitteln.

Diese muss mit an die Funktion übergeben:

unsigned long B1off = 11025301; //101010000011101110010101
unsigned long B2off = 10869189; //101001011101100111000101
unsigned long C1on  = 11452798; //101011101100000101111110
unsigned long C2on  = 11146942; //101010100001011010111110
unsigned long C1off = 10680158; //101000101111011101011110
unsigned long C2off = 10899998; //101001100101001000011110
unsigned long D1on  = 11025303; //101010000011101110010111
unsigned long D2on  = 11236423; //101010110111010001000111
unsigned long D1off = 11084007; //101010010010000011100111
unsigned long D2off = 10700087; //101000110100010100110111

void setup() {
  Serial.begin(9600);
  unsigned long DSchalt[8] = {B1off,B2off,C1off,C2off,D1off,D2off};
  Std_Schalt(DSchalt, sizeof(DSchalt) / sizeof(DSchalt[0])); // Steckdosen ein senden
}

void loop() {}

//Steckdosen On/Off senden
void Std_Schalt(unsigned long (DSchalt[]), size_t size) {
    for (byte i = 0; i < size; i++) {
      Serial.println(DSchalt[i]);
    }
}
unsigned long B1off = 11025301; //101010000011101110010101
unsigned long B2off = 10869189; //101001011101100111000101
unsigned long C1on  = 11452798; //101011101100000101111110
unsigned long C2on  = 11146942; //101010100001011010111110
unsigned long C1off = 10680158; //101000101111011101011110
unsigned long C2off = 10899998; //101001100101001000011110
unsigned long D1on  = 11025303; //101010000011101110010111
unsigned long D2on  = 11236423; //101010110111010001000111
unsigned long D1off = 11084007; //101010010010000011100111
unsigned long D2off = 10700087; //101000110100010100110111


//Steckdosen On/Off senden
template<size_t N> void Std_Schalt(unsigned long (&array)[N])
{
  Serial.print("ArraySize: "); Serial.println(N);
  for (unsigned long code : array)
  {
    Serial.println(code);
  }
}

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  unsigned long DSchalt[] = {/*A1off,A2off, */ B1off, B2off, C1off, C2off, D1off, D2off};
  Std_Schalt(DSchalt); // Steckdosen ein senden
  delay(1000);
}

Na, @volvodidi ist dein C++ Buch noch in der Post?

1 Like

magst dir das künftig nicht einfacher machen und das einfach binär hinschreiben?

unsigned long B1off = 0b101010000011101110010101;

Tusen tack!
@ Kai, jep so gehts, danke.

@ combi, deine Lösung ist zwar die elegantere, aber wenn ich das nach einem Jahr wieder anfasse, ist das für mich nicht mehr nachvollziehbar. Ich hab einfach keine Zeit mich da so tief rein zu knien.

@noiasca, das geht so auch, ist aber alles noch im Umbau, ich taste mich langsam voran.

Gruß
Dieter

Für dieses Problem hast du jetzt mindestens 1 Stunde Lebenszeit in diesem Forum "verschwendet". Die du auch in Grundlagenarbeit hättest investieren können. In jedem C und C++ Grundlagen Buch ist das Wie und Warum beschrieben.

Das Verfahren, was du dir jetzt ausgesucht hast, ist seit mindestens 50 Jahren bekannt, eher 60 Jahre. Und genau so lange macht es Probleme.
Ein kleiner Tippfehler und schon hasste die Array Bereichsüberschreitung.
Ich will gar nicht wissen, wieviel Mannjahre an Debugarbeit schon in Zeigerfehler geflossen sind. Sicherlich hohe Tausende Anzahlen. Welche Schäden es schon produziert hat.....
Der Compiler hat noch nicht mal die Chance, dich zu warnen, oder dir Fehler zu zeigen.
C und seine Zeiger.... ein Alptraum.

Der neumodische Kram, der dir offensichtlich so gar nicht schmeckt, vermeidet die allermeisten dieser Probleme wirkungsvoll.
Es macht die C++/Arduino Welt besser.

  1. Es nimmt dir in vielen Fällen. die Chance, solche Fehler überhaupt zu machen
  2. Es kann viel umfangreicher gewarnt und Fehler gemeldet werden.

Aber, wie so oft:
Wer will findet Wege, wer nicht will, Gründe.

PS:
Mein Name ist hier @combie und nicht @combi !
Wenn du den richtigen verwendest, werde ich sogar benachrichtigt, wenn du mich ansprichst.

@combie, sorry das ich dich falsch geschrieben habe, war keine Absicht.
Ich sehe das jetzt nicht als neumodischen Kram, die alte Version kann ich besser nur einfacher nachzuvollziehen. Ich lerne immer mal was dazu, diesmal wollte ich schauen wie das mit der Übergabe von Parametern an eine Funktion funktioniert. Am Anfang wie ich das senden ausgelagert habe hab ich einfach die Anzahl im Array mitgegeben. Ich werde deine Version auch mal probieren. Mein Problem ist nur, das ich alle paar Monate wenn mir was neues einfällt, was die Steuerung machen soll, da auch irgendwie wieder durchsteigen muss.
Zeit geht da sowieso jede Menge drauf, hab den Montag Nachmittag damit verbracht die Brennenstuhl Funksteckdosen ans schalten zu bringen. Gestern ging es dann ganz einfach und fix. Man muss halt ab und zu mal drüber schlafen, und danach gehts dann :-).

bei der "alten" Version brauchst die Krücke mit sizeof/sizeof([0]) ...
bei der "neuen" Version kommt die Array Größe durchs Template.

Wennst die Zeichen mal abzählst (Funktions-Signatur + Funktionsaufruf) gewinnt das Template.
Weniger Zeichen - Weniger zu merken :wink:

Templates sind mächtig, wäre schade wenn du die außen vor lässt.

Hier mal 3 Versionen mit einem Zwischenschritt von Alt auf Neu falls der auto range based for auch neu sein sollte:

/*
   Übergabe eines Array an eine Funktion
*/

unsigned long B1off = 11025301; //101010000011101110010101
unsigned long B2off = 10869189; //101001011101100111000101
unsigned long C1on  = 11452798; //101011101100000101111110
unsigned long C2on  = 11146942; //101010100001011010111110
unsigned long C1off = 10680158; //101000101111011101011110
unsigned long C2off = 10899998; //101001100101001000011110
unsigned long D1on  = 11025303; //101010000011101110010111
unsigned long D2on  = 11236423; //101010110111010001000111
unsigned long D1off = 11084007; //101010010010000011100111
unsigned long D2off = 10700087; //101000110100010100110111

void antike(unsigned long (DSchalt[]), size_t size) {
  Serial.print("ArraySize: "); Serial.println(size);
  for (size_t i = 0; i < size; i++) {
    Serial.println(DSchalt[i]);
  }
}

template<size_t size> void mittelalter(unsigned long (&array)[size]) {
  Serial.print("ArraySize: "); Serial.println(size);
  for (size_t i = 0; i < size; i++) {
    Serial.println(array[i]);
  }
}

template<size_t size> void neuzeit(unsigned long (&array)[size]) {
  Serial.print("ArraySize: "); Serial.println(size);
  for (unsigned long &code : array) {
    Serial.println(code);
  }
}

void setup() {
  Serial.begin(9600);

  unsigned long DSchalt[] = {/*A1off,A2off, */ B1off, B2off, C1off, C2off, D1off, D2off};
  antike (DSchalt, sizeof(DSchalt) / sizeof(DSchalt[0]));
  mittelalter(DSchalt);
  neuzeit(DSchalt); 
}

void loop() {
}

Ich möchte dir nicht groß widersprechen.
Aber die Version ist auch schon fast halb modern.

Eisenzeit:

void eisenzeit(unsigned long *DSchalt, size_t size) {
  Serial.print("ArraySize: "); Serial.println(size);
  for (size_t i = 0; i < size; i++) {
    Serial.println(DSchalt[i]);
  }
}

Oder:

void eisenzeit(unsigned long *DSchalt, size_t size) {
  Serial.print("ArraySize: "); Serial.println(size);
  for (size_t i = 0; i < size; i++) {
    Serial.println(*(DSchalt + i));
  }
}

Ist doch die Array Schreibwiese zu der Pointer Notation äquivalent.

Auch gibt es noch eine lustige Variante:

void dieLustige(unsigned long *DSchalt, size_t size) {
  Serial.print("ArraySize: "); Serial.println(size);
  for (size_t i = 0; i < size; i++) {
    Serial.println( i[DSchalt] );
  }
}

danke noiasca, die neuzeit werde ich mal einsetzen und versuchen sie zu verstehen.

Dieter

Gute Entscheidung.

Templates lassen sich auch schön als Codegeneratoren einsetzen.

z.B. lassen sich automatisch Funktionen erzeugen, die nahezu alle eindimensionalen Arrays ausgeben können.
In den Zellen können sowohl die üblichen Datentypen, als auch Erben von Printable stecken.

Als Schmankerl erfolgt die Ausgabe auf beliebigen Instanzen welche Print beerben und das sind gar nicht so wenige.

Beispiel:

unsigned long arrayA[] {63454353,345555};
unsigned int  arrayB[] {6345,4353,345,555};
byte          arrayC[] {63,45,43,53,34,55,55};
float         arrayD[] {634.54,35.3,3.45,55.5};
bool          arrayE[] {true,false,true,true,false,false};
const char *  arrayF[] {"wertzu","hgfds","fg","mnbvcxy"};
char          arrayG[] {'a','s','d',40,41,'f'};



template<typename T, size_t N> void printJedesArray(T (&array)[N], Print &print)
{
  print.println(__PRETTY_FUNCTION__);
  print.print("ArraySize: "); print.println(N);
  for (T &data : array)
  {
    print.println(data);
  }
  print.println();
}

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  printJedesArray(arrayA,Serial);
  //printJedesArray(arrayA,LCD);
  //printJedesArray(arrayA,Serial);
  //printJedesArray(arrayA,DateiAufSD);
  printJedesArray(arrayB,Serial);
  printJedesArray(arrayC,Serial);
  printJedesArray(arrayD,Serial);
  printJedesArray(arrayE,Serial);
  printJedesArray(arrayF,Serial);
  printJedesArray(arrayG,Serial);


  delay(1000);
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.