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.
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;
}
strnlen_s() is specified in Annex K of the C Standard starting at version C11. This Annex is not widely implemented and even Microsoft's implementation is not fully conformant with the specified version. The semantics are contorted especially regarding error handling. I would recommend not using it.
strnlen() is a simple function specified in POSIX.1-2008 and available on many platforms. It is easy to implement on platforms that do not provide it:
#include <string.h>
size_t strnlen(const char *s, size_t n) {
size_t i;
for (i = 0; i < n && s[i] != '\0'; i++)
continue;
return i;
}
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?
For C, strnlen is OK as the name is not reserved. It is not part of the standard, so OK for you to add.
POSIX reserves str...(), so you might want to use another name.
strnlen_s collides with K.3.7.4.4 The strnlen_s function and has a controversial history that you might not want your code tied into. Avoid naming your function strnlen_s().
I would avoid name coalitions to common libraries with any function one adds with 2 names: the formal less-likely-to-collide-name and macro
size_t nielsen_strnlen(const char *s, size_t maxsize);
#define slength nielsen_strnlen
Or simply go directly with something less likely to collide.
size_t nstrnlen(const char *s, size_t maxsize);
Deeper: OP appears to want to use a popular function that is outside the standard C library (or current version), but might be available when code is ported to other systems. OP wants to provide a use-my-code-if-not-available function.
Careful where you tread.
I would use a macro (or a wrapper function)
#if ON_SYSTEM_WITH_strnlen
#define slength strnlen
#else
#define slength nielsen_strnlen
#endif
... and then use calls to slenth().
Problems comes up when OP's version of code is not exactly like the desired (today and tomorrow) or because it is not standard, various implementations vary - a little bit, on its implementation. To mitigate, consider a macro or function wrapper indirection.
Side issue: Parameter order and a potential new principle to the "original principles" of C.
size_t foo1(const char *s, size_t maxsize);
// arranged such that the size of an array appears before the array.
size_t foo2(size_t maxsize, const char *s);
size_t foo3(size_t maxsize, const char s[maxsize]);
string is the c++ header and string.h is the c header (at least with gcc). strlen_s (afaik) is a Microsoft extension to the C library. You right, strlen would be the more standard. You could also use memchr if you need a byte count. To #Basile's point, if you need count of characters you need something that is UTF-8 aware.
Related
I'm creating a header only library and I wanted to check if the user has defined <string.h> so that I can use memcpy. I read online about how libraries like stdio have guard macros, but I couldn't find one for string.h. Any ideas? Or is there a way just to see if memcpy is a function?
You can portably tell if string.h has not been included.
Per 7.24.1 String function conventions, paragraph 1 of the (draft) C11 standard:
The header <string.h> declares one type and several functions, and defines one macro useful for manipulating arrays of character type and other objects treated as arrays of character type. The type is size_t and the macro is NULL ...
If NULL is not defined, then the user could not have included string.h prior to including your header(s).
I see no portable way of definitively determining if string.h has been included.
If you need <string.h>, include it yourself. You can also forward-declare memcpy and use it without including anything:
void* memcpy( void *restrict dest, const void *restrict src, size_t count );
I have used strlen() function from the string.h library without including the header which I want to include from the header file which is initially implemented, because I am writing my own implementation of strcpy(),if I include the header it says it's multiple definitions of strcpy ().
So how do I include only a particular definition from the header file.
Do I need to use extern keyword?
#include <stdio.h>
#include <stdlib.h>
#include "exercise 5.5.h"
int main() {
char *s = "hello";
char *t = "helli";
int n = 3;
if (n > strlen(t))
printf("\nsorry the value of n is greater than the size of t");
else {
S = strncpy(s, t, n);
printf("\nther is %d", x);
}
}
The header has definition of strncpy
Terminal trace
exercise. 5.5_main.c:10:7: incompatible implicit declaration of built-in function "strien
exercise 5.5 main.c:10:7: note: include <string.h> or provide a declaration of 'strlen
I don't want to include string.h but how do I explicitly provide definition of strlen
Header
char* strncat(char *s, char *t, int n);
char* strncpy(char *s, char *t, int n);
int strncmp(char *s,char *t, int n);
Reimplementing a standard library function like strcpy can be tricky. Since it's a standard library function, its name is in a sense "reserved" -- you're not supposed to use it yourself. (It's not quite as strongly reserved as is a keyword like switch, but it's still generally a bad idea to try to write a function named strcpy -- not to mention the fact that it's usually perfectly unnecessary!)
In answer to your explicit question, no, there's no way to "selectively include" just your own selection of the declarations in a system header file such as <string.h>.
If for some reason you need to write your own version of strcpy, you have several choices, depending on circumstances.
Rename your own function. For example, call it my_strcpy. (This is the usual approach.)
Make sure the definition of your function is perfectly correct, and matches the declaration in the standard header file exactly. For example, if you have strcpy(char *dst, char *src) {...} or char *strcpy(char *dst, char *src) {...}, those are both wrong -- it needs to be char *strcpy(char *dst, const char *src) {...}.
Don't use the standard strlen function, either, meaning that you don't have to do a #include <string.h> at all. If you need it, write your own version of strlen, too. (This is often the requirement if the reason you're writing your own strcpy is as a teaching exercise: often the assignment says "You may not use any other functions from the standard library.")
Instead of doing a #include <string.h> because you're calling strlen, provide your own prototype for it at the top of your file: extern size_t strlen(const char *);. (This is generally an extremely bad idea for several reasons, and is not a step to be taken except under extreme circumstances and when you know exactly what you're doing.)
It may also be significant to note whether the "redefinition" error you're getting is coming from the compiler or the linker. If it's a compile-time error such as "conflicting types for 'strcpy'", it indicates you probably need to pay attention to point 2 just above. But if it's a link-time error like "ld: duplicate symbol '_strcpy'" there may not be anything you can do about it, and you'll have to fall back on point 1.
How do I can display a string value without using the standard libraries in C language? please see the following code:
//without using the standard libraries that other created it
int main() {
string str = "Hello";
//How do I can display str value without using the standard libraries that other created it?
}
Here's how you can do it :
// Declare the prototype for the write() function,
// with unspecified parameters because why not.
extern long write();
int main(void) {
char const *str = "Hello";
// Retrieve the length
unsigned long size = 0;
while(str[size])
++size;
// Write to stdout (fd 1)
write(1, str, size);
return 0;
}
Live on Coliru.
Of course, it's as non-portable as it gets, and will probably fail to link or trigger UB on the majority of systems other than the one I pulled the declaration from (it's a Linux system call, declared in unistd.h which I retrieved from Coliru). But then, that's why we have the standard library in the first place.
Quite simply, you can't, at least not if you want your code to be at all portable.
Almost certainly there's some way to perform output in C code without using the standard library. But the way to do that will vary widely from one system to another. A solution that works on UNIX systems, for example, almost certainly won't work on Windows, and vice versa -- unless that solution uses the C standard library, which is customized for each system.
That's why the standard library exists. And on freestanding (embedded) implementations that don't support the standard library, you have to write system-specific code to do any I/O.
If you want to know how to do I/O on a particular system without using the standard library, I suggest posting a new question.
int main() {
string str = "Hello";
}
int main() is better written as int main(void).
There is no type string in C. What you probably want here is either
const char *str = "Hello";
or
char str[] = "Hello";
A "string" in C is by definition "a contiguous sequence of characters terminated by and including the first null character". It's a data format, not a data type. (C++ has a type std::string, but you're asking about C, not C++ -- and in C++ std::string is itself defined by the C++ standard library.)
The comp.lang.c FAQ is an excellent resource.
Is there any reason to use the non-standard bzero() and bcopy() instead of memset() and memcpy() in a Linux environment? I've heard many say that they're better for Linux compilers, but haven't seen any advantages over the standard functions.
Are they more optimized than the standard ones, or do they have any behavioral particularity for which they're preferred?
While bzero and bcopy functions aren't ISO C (the actual standard that I assume you're talking about when referring to them as non-standard), they were a POSIX standard thing, although they pre-dated both ISO and POSIX.
And note that use of the word "were" - these functions were deprecated in POSIX.1-2001 and fianally removed in POSIX.1-2008, in deference to memset, memcpy and memmove. So you're better off using the standard C functions where possible.
If you have a lot of code that uses them and you don't want to have to go and change it all (though you probably should at some point), you can use the following quick substitutions:
// void bzero(void *s, size_t n);
#define bzero(s, n) memset((s), 0, (n))
// void bcopy(const void *s1, void *s2, size_t n);
#define bcopy(s1, s2, n) memmove((s2), (s1), (n))
#include <strings.h>
void bcopy(const void *src, void *dest, size_t n);
Description
The bcopy() function copies n bytes from src to dest. The result is correct, even when both areas overlap.
Conforming to:
4.3BSD, it seems b comes from BSD and it seems deprecated.
Which means bcopy is analogous to memmove() not memcpy() as R.. said at his comment.
Note: strings.h is also distinct from string.h.
Actually nowdays it could be the other way around. You see that because memcpy and memset is included in the standard the compiler will be allowed to assume that function called so does exactly what the standard prescribes. This means that the compiler can replace them with the most efficient way of performing the operation it can figure out. With bcopy and bzero on the other hand the standard does not prescribe any behavior on those so the compiler can't assume anything - which means that the compiler would need to issue an actual function call.
However GCC for example knows about bcopy and bzero if it's built for an OS that have them.
I am doing something in C which requires use of the strings (as most programs do).
Looking in the manpages, I found, at string(3):
SYNOPSIS
#include <strings.h>
char * index(const char *s, int c)
(...)
#include <string.h>
char * strchr(const char *s, int c)
So I curiously looked at both strchr(3) and index(3)...
And I found that both do the following:
The strchr()/index() function locates the first occurrence of c in the string
pointed to by s. The terminating null character is considered to be part of the
string; therefore if c is '\0', the functions locate the terminating '\0'.
So, the manpage is basically a copy & paste.
Besides, I suppose that, because of some obfuscated necessity, the second parameter has type int, but is, in fact, a char. I think I am not wrong, but can anyone explain to me why is it an int, not a char?
If they are both the same, which one is more compatible across versions, and if not, which's the difference?
strchr() is part of the C standard library. index() is a now deprecated POSIX function. The POSIX specification recommends implementing index() as a macro that expands to a call to strchr().
Since index() is deprecated in POSIX and not part of the C standard library, you should use strchr().
The second parameter is of type int because these functions predate function prototypes. See also https://stackoverflow.com/a/5919802/ for more information on this.
It looks like the index() function is an older one that should be replaced by strchr().
See http://www.opengroup.org/onlinepubs/000095399/functions/index.html where they suggest to replace index by strchr and mark index as a legacy function.