Filling uint16_t Array with greater than zero

Hi Everyone,

I'm having a problem trying to fill an array with a positive number (not zero), and I'm pretty sure I'm not doing something right, but it escapes me right now. Can someone maybe point out the obvious that I am missing?

Here's some minimum code that duplicates my problem.

uint16_t* myvariable;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  myvariable = (uint16_t*) calloc(21, sizeof(uint16_t));
  setmyvariable();
  printmyvariable();
}

void setmyvariable() {
    memset(&myvariable[0], 4095, 21*sizeof(uint16_t));
}

void printmyvariable() {
  Serial.println("myvariable data:");
  for (int i = 0; i < 21; i++) {
    Serial.print("Slot ");Serial.print(i);Serial.print(": ");Serial.println(myvariable[i]);
  }
}

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

}

And the results:

myvariable data:
Slot 0: 65535
Slot 1: 65535
Slot 2: 65535
Slot 3: 65535
Slot 4: 65535
Slot 5: 65535
Slot 6: 65535
Slot 7: 65535
Slot 8: 65535
Slot 9: 65535
Slot 10: 65535
Slot 11: 65535
Slot 12: 65535
Slot 13: 65535
Slot 14: 65535
Slot 15: 65535
Slot 16: 65535
Slot 17: 65535
Slot 18: 65535
Slot 19: 65535
Slot 20: 65535

The array ends up getting filled with 65535 instead of 4095. What am I doing wrong? Or, is there a better way to do this? I'm using memset because sometimes I don't start at the first position (0). Sometimes I need to start in the middle setting more than one by changing it to something like this.

    memset(&myvariable[5], 4095, 6*sizeof(uint16_t));

Which results in this:

myvariable data:
Slot 0: 0
Slot 1: 0
Slot 2: 0
Slot 3: 0
Slot 4: 0
Slot 5: 65535
Slot 6: 65535
Slot 7: 65535
Slot 8: 65535
Slot 9: 65535
Slot 10: 65535
Slot 11: 0
Slot 12: 0
Slot 13: 0
Slot 14: 0
Slot 15: 0
Slot 16: 0
Slot 17: 0
Slot 18: 0
Slot 19: 0
Slot 20: 0

The second parameter to memset (your 4095 value) is interpreted as an unsigned character (byte). 4095 is 0x0FFF hex. So you end up setting each byte in the array to 0xFF. Each uint16_t is 2 bytes. And 0xFFFF is 65535.

1 Like

so in a nutshell memset only works with bytes.

uint16_t myVariable[21];

void setup() {
  memset(myVariable, 0xFF, sizeof myVariable); // all the bytes to 0xFF
  •••
}

•••

if you want to get something tailored to the type, then write a for loop and access the array's entry to set the value you want

const byte arraySize = 21;
uint16_t myVariable[arraySize];

void setup() {
  for (byte i=0; i < arraySize; i++) myVariable[i] = random(10, 21); // random integral number in [10, 21[ interval
  •••
}

•••

That totally makes sense. I guess I had just forgotten that memset only works with bytes. I will have to write something more custom for it.

Thank you!

I found this example that someone posted to make a memset16 function that they say works, but it doesn't seem to work for me.

void *memset16(void *m, uint16_t val, size_t count)
{
    uint16_t *buf = m;

    while(count--) *buf++ = val;
    return m;
}

The error I get is:

invalid conversion from 'void*' to 'uint16_t*' {aka 'short unsigned int*'} [-fpermissive]

Any thoughts? If if helps, I'm working with an ESP32. Also, I'm using the exact same line as before to call it (except with memset16 instead of memset) just for testing.

Cast the void * to uint16_t *.

    uint16_t *buf = (uint16_t *)m;

The original code will compile with a warning instead of an error on some board packages that have the compiler options -fpermissive

warning: invalid conversion from 'void*' to 'uint16_t* {aka unsigned int*}' [-fpermissive]
     uint16_t *buf = m;
                     ^

From the documentation of the gcc compiler:

"This example" uses a loop to set entire array element by element. It logically perfectly equivalent to for loop, proposed in #3 by @J-M-L

Using the for loop is more readable and does not require the cast

1 Like

I realize that functionally it is the same. It was more of "i found this and it's not working, so I'm curious why." It helped me learn something.

I could have gone with a loop and it would be more readable, but sometimes I like to just have less lines of code to look at too. I know, I like to be difficult. LOL

Honestly, I was all set to use a loop instead, until I scrolled upon a post that had a bunch of different options to try and I just figured it would be another learning experience.

I guess I never really thought about casting the void * to uint16_t * because I haven't written (or used from anyone else to my knowledge) a function that passed anything as a void like that. As suggested, that fixed the problem. This is all new to me and I appreciate the help.

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