Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is most standard: strnlen or strnlen_s?

Tags:

c

c11

In my current project, I am coding according to the C11 standard (building with gcc -std=c11) and needed something like strnlen (a "safe" version of strlen which returns the length of a 0-terminated string, but only up to a given maximum). So I looked it up (e.g. https://en.cppreference.com/w/c/string/byte/strlen) and it seems the C11 standard mentions such a function, but with the name strnlen_s.

Hence I went with strnlen_s, but this turned out to be undefined when including string.h. On the other hand, strnlen is defined, so my current solution is to use strnlen with a remark that the standard name seems to be strnlen_s but that this is not defined by GCC.

The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?

Note: Microsoft (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strnlen-strnlen-s) implements both functions with the distinction that strnlen_s checks if the string pointer is NULL and returns 0 in that case while strnlen has no such check.

like image 342
nielsen Avatar asked Dec 18 '22 11:12

nielsen


1 Answers

The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?

No, it isn't portable at all. It was never part of C. It is included in POSIX, which doesn't mean much.

I would imagine the reason why the function doesn't exist in the standard, probably because it's superfluous when we already have memchr(str, '\0', max);.

strnlen_s is part of the optional bounds-checking interface in C11 annex K. This whole chapter turned out a huge fiasco and barely any compiler implements it. Microsoft has similar named functions but they are sometimes not compatible. So I would assume that all _s functions are completely non-portable.

So use neither of these, use memchr or strlen.


EDIT

In case you must implement strnlen yourself for some reason, then this is what I'd recommend:

#include <string.h>

size_t strnlength (const char* s, size_t n) 
{ 
  const char* found = memchr(s, '\0', n); 
  return found ? (size_t)(found-s) : n; 
}
like image 178
Lundin Avatar answered Dec 29 '22 22:12

Lundin