With a function is a char[xxx] parameter passed by ref or value

Hi.

I am on the discovery path to mastering char arrays, char pointer and strings in C++.

I was trying to pass text to a function and then return modified text back.

While testing I tried the code below and it seems to do what I want. I expected that
the "data" parameter would have been passed by value but it's acting like it's passed by reference.

Is that correct?

const int maxMsgLen = 20;

void test2(char message[maxMsgLen+1], char data[maxMsgLen+1+2])
{
  int index=0;
  int index2 = 0;
  
  data[index] = '*'; //(Char)STX;
  
  while(message[index2] != '\0')
  {
    index++;
    data[index] = (char)message[index2];
    index2++;
  }
  
  index++;
  data[index] = '*'; //(char)ETX;
  index++;
  data[index] = '\0';
}

void loop()
{
  char buffer[maxMsgLen+1] = "Message1234567890AA";
  
  char temp[maxMsgLen+1+2];
  test2(buffer,temp);
  
  Serial.println(temp);
  
  delay(1000);  
}

That is correct.

In C there is no such thing as a "string". I think the largest single "atomic" variable is the "long long" - 64 bits. Anything made up of more than one element, as in an array of elements (which a string is, after all - an array of "char" variables) is actually only a block of reserved memory pointed to by the variable.

When you first declare the variable with [...] you set aside that block of memory, and the variable points to the start of it. All operations on that variable are done as a pointer to that memory.

So, the following two statements are the same:

data[3] = 'F';
*(data+3) = 'F';

That is, the "array entry number 3" and "the address 3 places higher than where data is pointing".

So, logically, when you pass the data variable to a function it is actually the pointer to the start of the memory area that you are passing.

It is not possible to pass a whole block of memory to a function, as there is no single data type that is that block of memory, only the pointer to where it starts.

If you want to protect the contents of the string within the function then you will have to manually copy the data into a temporary array within the function and work on that. You can use strdup() or strcpy() (the latter allocates memory for you - don't forget to free it), or memcpy() if the data isn't a string (the str*() functions copy up to the terminating null character).

And don't worry if it's confusing - it took me 6 years to learn how pointers work :wink:

majenko:
And don't worry if it's confusing - it took me 6 years to learn how pointers work :wink:

haha... I am spoiled having a day-job working with C# with almost no memory restrictions.

Thanks for the advice. I always thought you had to do the & to make it a ref type, but you are right... The Char[xxx] Parameter is pointing to the memory location and if you change the contents of the memory you are actually referencing the value. TA-DA!!!!!

Thanks again... :smiley:

majenko:
That is correct.

In C there is no such thing as a "string". I think the largest single "atomic" variable is the "long long" - 64 bits. Anything made up of more than one element, as in an array of elements (which a string is, after all - an array of "char" variables) is actually only a block of reserved memory pointed to by the variable.

Just to be clear, arrays are second class citizens and arrays are always passed by taking the address of the first element, and passing that pointer.

Structs, unions, and classes however are passed by value (unless you use '&' in the declaration), which typically means that the whole structure is copied to a temporary (depending on the ABI, a structure is either copied to a stack location and a pointer to that temporary stack location is passed, or the individual words in the structure are passed as if separate arguments were passed, either on the stack or in registers). Arguments declared with '&' are passed by reference, and the pointer to the first element is passed.