Pointers question

Pointers- my Achilles heel...

In this code, what is the difference in the two calls to memset()?

/*
   Demo of pointers and memset()

   Prototype:
   void * memset ( void * ptr, int value, size_t num );
     Fill block of memory
     Sets the first num bytes of the block of memory pointed by ptr to the specified
     value (interpreted as an unsigned char).

*/
void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println();
  Serial.println();

  char str[] = "Almost every programmer should know memset!";
  memset (str, '-', 6);
  Serial.println(str);

  //&str represents the address of the variable str.
  memset (&str, '!', 6);
  Serial.println(str);

}

void loop() {
}

Is memset (&str, '!', 6); grammatically correct but functionally the same as memset (str, '!', 6); ?

str is known by the compiler as an array of 44 constant char (if i counted well with the invisible trailing null char)

When str is used directly in the memset call, the variable is said to decay to a pointer to the first element of the array: basically a conversion takes place and the resulting type is a const char *. If you add 1 to that pointer you jump to the next char.

When str is used with the address of (&) operator, there is no decay. The & tells the compiler to take the address of the array and thus the type of &str is a pointer to the array as a whole. (If you were to add 1 to this pointer you would jump in memory by the size of the array).

So basically the type is different, but because the first element of the array is at the same position in memory as the start of the whole array, these two pointers have exactly the same value.

This is this value that is passed to the memset function. As the parameter is declared as void* and a pointer can always be cast to a void* (a generic pointer type pointing at nothing special, basically a memory address with no information about what you are pointing to) in the code of the function the value just look the same, the type has been transformed and all info has been lost and memset can do its job (because it does not care what you are pointing at).

Developers use void* instead of uint8_t* (byte pointer) because you won’t get a warning if you pass the address of a structure or a char*, they are all compatible types with void*

So long story short it does not matter what notation you use, just remember you loose information during the decaying process.

J-M-L:
just remember you loose information during the decaying process.

Perhaps, but it's always decayed to what I wanted. Meaning, at the end of the day, I've always wanted to end up with a char *, not a char[50] *.

In fact, after 30+ years of C programming, I only saw the &str notation recently. In my mind, the name of an array has always been interpreted as a pointer to the first element in the array (and of the correct pointer type) when used in a function call. Been that way since before K met R.

Agreed for cStrings, most of the time it’s what you want to use (and because C does not support passing a variable by reference you usually end up with an extra parameter to carry the size into the function call).

(Note also that we are compiling with C++ not C. C++ is more "type aware" than C, allowing for compile time checking capabilities)

Thanks. I had never heard of "decay" in C, but here's what I found:

What is Array Decay?
The loss of type and dimensions of an array is known as decay of an array.This generally occurs when we pass the array into function by value or pointer. What it does is, it sends first address to the array which is a pointer, hence the size of array is not the original one, but the one occupied by the pointer in the memory.

So, if I understand array decay, then

memset (&str, '!', 6);

is the correct syntax. ??

Not really - both are fine because in the signature of memset() for the pointer you have void* and thus the function tells explicitly to the compiler it does not expect nor care for any particular type of pointer.

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