pass variable by reference [pointer] or by value

On arduino I have some problems, I don’t really understand.

  • A simple example of just one variable referencing to another variable.

In C

 int *p; // reference
  int a;
  p = &a;
  // print  p -  address
  // print &p -  address of memory location 'p'
  // print *p -  dereferencing : returns value on that address
  // 'a' MUST BE initialized and then 'p' allocated to 'a' ####
  a = 10;
  p = &a;
  
  print  p -  address
  print &p -  address of memory location 'p'
  print *p -  dereferencing : returns value on that address

On the arduino

  int a = 1;
   int *b = &a;
   *b += 1;
   
  //now a == 2 (and b's value is a pointer to the location of a in memory)
  Serial.print("a -  ");
  Serial.println(a, DEC );
  Serial.print("b -  ");
  Serial.print(*b, DEC );  // dereferencing

So I have the ERROR error: call of overloaded ‘println(int*&, int)’ is ambiguous if I try

Serial.print(b, DEC );   // address of 'b'
// OR
Serial.print(&b, DEC );  // address of memory location 'p'
  • My original intension is to make a swap function using reference
/*
Variables
*/
const long SERIAL_SPEED=38400;//baud rate of the serial communication

struct rect {
  int width;
  int height;
};

void swap(struct rect *input);

void swap(struct rect *input) {
    int tmp = input->width;
    input->width = input->height;
    input->height = tmp;
}

void setup() {

    Serial.begin(SERIAL_SPEED);      // open the serial port at SERIAL_SPEED bps:

    struct rect first;
    first.width = 111;
    first.height = 222;  

    Serial.println( "\n -- BEFORE -- ");
    Serial.print( "  - first.width : ");  Serial.println(first.width,  DEC);
    Serial.print( "  - first.height : ");  Serial.println(first.height,  DEC);

    swap($first);
    
    Serial.println( "\n -- AFTER -- ");
    Serial.print( "  - first.width : ");  Serial.println(first.width,  DEC);
    Serial.print( "  - first.height : ");  Serial.println(first.height,  DEC);

Thks

swap($first);

What are the chances you meant -

swap(&first);
 int *p; // reference

No, it is NOT. It is a pointer that does not (yet) point to anything.

droopy4u: My original intension is to make a swap function using reference[/li][/list]

First of all, notice this is C++, not C.

In C++ you can pass the parameter by:

  1. Value
  2. Reference
  3. Pointer

Your intention is to do it by pointer, not by reference and you do it right, except you call it wrong (as corrected by others).

To send it by reference, you should:

void swap_reference(struct rect &input) {
  int tmp = input.width;
  input.width = input.height;
  input.height = tmp;
}
...
swap_reference(first);
void swapInt( int*a, int *b)
{
     int c = *a;
     *a = *b;
     *b = c;
}

// usage
swapInt(&int1, &int2);

You can probably use a Template to make it type agnostic, but I am a C guy.

The term ‘reference’ in this usage has multiple meanings depending on the context.

Some C tutorials do indeed refer to passing by address as passing by reference, although from a C++ programmers perspective this not quite right.

https://www.tutorialspoint.com/cprogramming/c_function_call_by_reference.htm

error: call of overloaded ‘println(int*&, int)’ is ambiguous

Well, evidently Serial.println doesn’t take those arguments. It won’t print out a pointer to int - not on the arduino at least. Try casting the pointer to an int.

Paul M has the right solution:

void setup() {
  // put your setup code here, to run once:
  int a = 1;
  int *b = &a;
  *b += 1;

  Serial.begin(115200);

  //now a == 2 (and b's value is a pointer to the location of a in memory)
  Serial.print("a -  ");
  Serial.println(a, DEC );
  Serial.print("b -  ");
  Serial.println(*b, DEC );  // dereferencing

  Serial.println( (int) b, DEC );   // NO! This is the content of the pointer variable b
  // OR
  Serial.println( (int) &b, DEC );  // address of memory location where b is stored
  Serial.println( (int) &a, DEC );  // address of memory location where a is stored
}

void loop() {
  // put your main code here, to run repeatedly:

}

I ran this code on a Mega 2560 Pro Mini the output is:

a - 2 b - 2 8697 8695 8697

Keep in mind that the content of b (i.e., its rvalue), since it is a properly-initialized pointer, should be the memory address of variable a. Any pointer variable should only hold one of two values: 1) NULL, in which case it points to no valid data, or 2) a memory address. This says the rvalue of b is 8697 and that variable b "lives" at memory address 8695 (i.e., the lvalue of b). The third number is where variable a lives in memory (i.e., the lvalue of a). The numbers tell you that the rvalue of b is the lvalue of a. That is, b points to where a lives in memory. Since b knows where variable a lives in memory, b can change its value "indirectly" using the process of indirection.

Read that paragraph about 50 times and it will make sense.

KeithRB: ``` void swapInt( int*a, int *b) {     int c = *a;     *a = *b;     *b = c; }

// usage swapInt(&int1, &int2);




You can probably use a Template to make it type agnostic, but I am a C guy.

Could you please explain how to do about the template, thx

Header file …

// File - swap.h

#ifndef swap_H
#define swap_H

template<typename T>
void swap(T& lhs, T& rhs)
{
    T   t   = lhs;
    lhs     = rhs;
    rhs     = t;
}

#endif

… example usage file …

// File - swap.ino

#include "swap.h"

struct rectT
{
    int width;
    int height;
};

void loop()
{   }

void setup()
{
    struct rectT   rect = { 100, 200 };
    
    swap(rect.width, rect.height);
}

arduino_314: In C++ you can pass the parameter by: 1. Value 2. Reference 3. Pointer

That’s interesting. Having not yet jumped into learning C++, I did not know that. The way I keep it straight in my head for plain old C is that parameters are ALWAYS passed to functions by VALUE. That value may be the value of a pointer variable, so it’s a reference to another variable. But, it’s the VALUE of whatever was inside the (..) of the calling statement.

So code like:

void myFunct(int);


void setup() {
  int myVariable;

  myFunct(myVariable);

}



void myFunct(int dog) {
  dog++;
}

Will never change the value of myVariable

econjack:
Keep in mind that the content of b (i.e., its rvalue), since it is a properly-initialized pointer, should be the memory address of variable a. Any pointer variable should only hold one of two values: 1) NULL, in which case it points to no valid data, or 2) a memory address. This says the rvalue of b is 8697 and that variable b “lives” at memory address 8695 (i.e., the lvalue of b). The third number is where variable a lives in memory (i.e., the lvalue of a). The numbers tell you that the rvalue of b is the lvalue of a. That is, b points to where a lives in memory. Since b knows where variable a lives in memory, b can change its value “indirectly” using the process of indirection.

Read that paragraph about 50 times and it will make sense.

in annex is this what you mean?

(or https://drive.google.com/open?id=0B2WLaA0HlUBVVmtRdXBoV0loQzA)

memory.JPG

This shows how to use reference or pointer variables in a simple Bubble Sort.

int values[] = {11, 25, 69, 32, 21};

void swapElements(int &x, int &y);      // Prototype for reference
void swapPointers(int *x, int *y);      // Prototype for pointer


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

  bubbleSort();
  for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
    Serial.println(values[i]);
  }

}

void loop() {
}

void bubbleSort() {
   bool swap;
   int elementCount = sizeof(values) / sizeof(values[0]);
   int temp;
   int i,j;
   
   for(i = 0; i < elementCount - 1; i++) { 
      swap = false;
    
      // loop through numbers falling ahead 
      for(j = 0; j < elementCount - 1 - i; j++) {     
         if(values[j] > values[j+1]) {
//          swapElements(values[j], values[j + 1]);   // Using reference
          swapPointers(&values[j], &values[j + 1]);   // Using pointers
           swap = true;
         }    
      }
      if(swap == false) {
         break;
      }
   }
}

void swapElements(int &x, int &y) {          // Uses references
   int temp;
   temp = x; 
   x = y;   
   y = temp; 
}

void swapPointers(int *x, int *y) {          // Use pointers
   int temp;

   temp = *x; 
   *x = *y;    
   *y = temp; 
}

As you can see, they are almost the same. The reference version has less “clutter” in it