The strnlen function is undefined on UNO Q/Zephyr

The following fails to compile for Uno Q. strnlen is undefined. Works fine on the AVR core.

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);
  const char s[10] = "hello";
  Serial.println(strnlen(s, sizeof(s)));
}

void loop() { }

The pubsubclient3 library calls strnlen(). An easy workaround is to include strnlen in the sketch.

// Required for Uno Q/Zephyr Core. Remove when core is fixed.
size_t strnlen(const char* b, size_t s) {
  size_t i;
  if ((b == NULL) || (s == 0)) return 0;
  for (i = 0; (i < s) && (b[i] != 0); i++);
  return i;
}
1 Like

As strnlen() is not working in UNO Q, then can we do the following to know the length of a string?

const char s[] = "hello";
Monitor.println(sizeof(s) - 1);  //shows: 5

strnlen(const char* b, size_t s) checks if a char array has at least n characters.

Did you test the println(sizeof(s) -1 )?
I expect it will return 2 or 4 as s is the address of a fixed char array.

1 Like

Yes! I run the following codes and got 5 (6-1).

const char s[] = "hello";
Monitor.println(sizeof(s) - 1);  //shows: 5

Wow, completely different what I expected.

Time to dive into some documentation again. Never stop learning!

1 Like

Thanks for your report @customcontroller. I have submitted a proposal to add support for strnlen:

2 Likes

Out of curiosity I tried to just add #include <cstring>

#include <Arduino_RouterBridge.h>
#include <cstring>

void setup() {
  //Initialize Monitor and wait for port to open:
  Monitor.begin();
  delay(5000);
}

void loop() {
  const char* str = "Hello, World!";

  // Get the length of the string, up to maxLen characters
  size_t length = strnlen(str, sizeof(str));
  Monitor.print(length);
  Monitor.print("\r");
}

but that gives a slightly different error:

<err> llext: Undefined symbol with no entry in symbol table atexit, offset 13732, link section 13

which is a known issue:
build: Fix linker errors when using CPP features. by iabdalkader · Pull Request #309 · arduino/ArduinoCore-zephyr

Pushed a minor fix for atexit

PS - that PR may also fix the strlen function as well, if it ever gets incorporated.

That would depend on how s is declared.

const char s[] = "Hello"; //sizeof(s) = 6
const char* s = "Hello";  //sizeof(s) = 2 or 4, depending on size of pointer

Yes, an array name can be used as a pointer to its first element. But they are not the same thing. The type of this identifier is interpreted by the compiler depending on the context. For example, when working with individual array elements, the array name is converted to a pointer to the element.

char s[]="hello";
char* a = s+1; // pointer to s[1]

Meanwhile, functions like sizeof() works with it as an entire array, which allows them to be used in a well-known expression for calculating the number of elements.

int array_size = sizeof(s)/ sizeof(s[0]);
1 Like

Is sizeof() a function or an operator?

You are doing it again, asking a question to which you already know the answer

From the write-up style of @b707 in post #9, it appears that sizeof() is being called/named a function. Within the forum discipline, I believe that I have the liberty to ask the poster whether this interpretation is correct or if it was simply a typo mistake.

I suspect that you already know that sizeof is part of the C/C++ language and is an operator, so why not just point that out instead of asking the question ?

1 Like

@b707 may have a different reasoning which I wished to hear.

To be honest, I didn't know it before @UKHeliBob answer.
Why do you consider this difference important in the context of my message about array and pointers?

For academic purposes, the names of C++ language constructs should be stated and written strictly according to the C++ standard.

It is not an answer to my question.

It could be due to language barrier where (perhaps) @b707 is native English speaker and @GolamMostafa is a non-native English speaker.