1

By playing with some examples I found the following construct:

void Show(int nav = 0) // -1 top, 1 bottom

and I wondered what effect it has to initialize the handover parameters in the function declarations, I never noticed such an construct consciously.

So I made a small demo:

#include <M5Stack.h> //necessary for my board
  int a;
  int b;
  int c;

int addFunction(int x = 3, int y = 3){
  int result;
  result = x + y;
  return result;
}

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

  // testcase 1
  a = 1;
  b = 2;
  c = addFunction(a, b); 
  Serial.println("testcase 1:");
  Serial.println((String)a + " + " + b + " = " + c);

   // testcase 2
  a = 1;
  b = 2;
  c = addFunction(); 
  Serial.println("testcase 2:");
  Serial.println((String)a + " + " + b + " = " + c);

   // testcase 3
  a = 1;
  b = 2;
  c = addFunction(a); 
  Serial.println("testcase 3:");
  Serial.println((String)a + " + " + b + " = " + c);
}

void loop() {
}

The output was:

enter image description here

So I learnd:

  • if you hand over parameters, the initialization is ignored, if you call the function without handing over paramters, the functions works with the init values.

  • if you handover only one parameter it will be assigned to the first in the declaration.

Question:

Is there a syntax possible to only call the function with the second parameter, so that for the first paramter the intialized value of the declaration is used? Spoken for this example with a = 1, b = 2 you only handover b and the expected result would be 5.

4
  • Should a single parameter always be for the second parameter (add a overloaded function) or do you want to choose for which parameter?
    – Jot
    Mar 24, 2019 at 9:52
  • It is just a general question to understand the syntax. So I would be interested in an answer of how to do it in general, which means also with more parameters and the possiblity to choose any parameter depending on the purpose (m out of n)
    – RJPlog
    Mar 24, 2019 at 10:01
  • 1
    An overloaded function is one option to be able to accept different number of parameters. A pointer can be made nullptr (or NULL) and in the code you could check for nullptr. There must be other options as well.
    – Jot
    Mar 24, 2019 at 10:19
  • @Jot tanks for the hint. I had a look into that, I guess this is for my not working, since x and y are of the same type. I will check if I get it working, maybe with different types.
    – RJPlog
    Mar 24, 2019 at 13:00

2 Answers 2

4

This is (unfortunately) not an Arduino question. It is actually about the syntax of C++ which is a rather complex language.

The mechanism you have discovered is called default arguments. The function prototype or definition may contain the default values of the arguments. As this is a list the default values are restricted from right to left. It is not possible to use a default parameter for argument to the left of a given argument. The order is strictly right to left.

f(int x = 0, int y = 1, int z = 2)

f(1,2,3) binds x = 1, y = 2, z = 3
f(1,2) equals f(1,2,2) binds x = 1, y = 2, z = 2
f(1) equals f(1,1,2) binds x = 1, y = 1, z = 2
f() equals f(0,1,2) binds x = 0, y = 1, z = 2

There is a syntax for struct initialization (aka aggregate initialization) in C++ that allows naming of struct field values. This type of naming is not allowed for function calls.

Please read https://en.cppreference.com/w/cpp/language/default_arguments, https://en.cppreference.com/w/cpp/language/aggregate_initialization and https://en.cppreference.com/w/cpp/utility/functional/bind for more details. And a good C++ book.

There are languages that allow default arguments and named parameters e.g. C#, Python, Ruby and Smalltalk. Please see https://en.wikipedia.org/wiki/Named_parameter.

Cheers!

(Update)

Below is a rewrite of @VE7JRO Add function class using cast operator to perform the evaluation:

class Add
{
public:
  Add(int x, int y) : m_x(x), m_y(y) {}
  operator int() { return m_x + m_y; }
  void x(int x) { m_x = x; }
  void y(int y) { m_y = y; }
  int print(Print& outp) {
    int res;
    res = outp.print(F("Add(x="));
    res += outp.print(m_x);
    res += outp.print(F(",y="));
    res += outp.print(m_y);
    res += outp.print(F(")"));
    return res;
  }
private:
  int m_x, m_y;
};

Add func(1,2);

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

  func.print(Serial);
  Serial.print(F("="));
  Serial.println(func);

  func.x(12);
  func.print(Serial);
  Serial.print(F("="));
  Serial.println(func);

  func.y(13);
  func.print(Serial);
  Serial.print(F("="));
  Serial.println(func);
}

void loop() {
}
3
  • Good explanation and material for further Investigation, thanks also for the extension of @VE7JRO, adds some more interesting details for me. (after I checked that you are using a different baud rate ;-))
    – RJPlog
    Mar 24, 2019 at 12:39
  • Missed the baud rate difference. Changed that to avoid confusion, debugging, etc, between the sketches. Mar 24, 2019 at 13:51
  • BW: If the member data is made public the syntax func.x = 12 would be allows (after removing the prefix m_). Mar 24, 2019 at 13:56
1

If your function is inside a class, you can set either variable, both variables or use the defaults.

class Add{

    int a, b;

  public:

    Add(): a(1), b(2){}

    int AddTwoIntegers(){
      return a + b;
    }

    void SetInt1(int int1){
      a = int1;
    }

    void SetInt2(int int2){
      b = int2;
    }

};

Add Test1;

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

  Serial.print("Test default values = ");
  Serial.println(Test1.AddTwoIntegers());

  Test1.SetInt2(4);
  Serial.print("Set b = 4 then add to a = ");
  Serial.println(Test1.AddTwoIntegers());
}

void loop(){}
1
  • got it, thanks for the example, helped me a lot in understandig while trying it out
    – RJPlog
    Mar 24, 2019 at 12:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.