I seem to be able to compile code that calls wsprintf with the MinGW gcc if I have these includes (in this order):
#include <stdarg.h>
#include <wingdi.h>
#include <winuser.h>
But I feel like there might be some "cleaner" way to do this. Perhaps with only a single header inclusion. I arrived at this list by searching header files for missing symbols and then including headers one-by-one.
Include <Windows.h>
Do you mean swprintf()?
swprintf() is described in the C99 standard. You need <wchar.h>.
If wsprintf does the same as swprintf you may want to consider using a standard function instead.
7.24.2.3 The swprintf function
Synopsis
[#1]
#include <wchar.h>
int swprintf(wchar_t * restrict s,
size_t n,
const wchar_t * restrict format, ...);
Description
[#2] The swprintf function is equivalent to fwprintf, except
that the argument s specifies an array of wide characters
into which the generated output is to be written, rather
than written to a stream. No more than n wide characters
are written, including a terminating null wide character,
which is always added (unless n is zero).
Do you mean the standard function swprintf? In that case you should include wchar.h.
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 );
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.
I am cleaning up warnings and found the following error:
warning: assignment makes pointer from integer without a cast buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);
This call is at the very top of the function, essentially:
char* buf;
buf = aligned_alloc(ALIGN_VALUE,BUF_SZ);
It is my understanding that aligned_alloc returns a void *. If cast the return from aligned_alloc to a (char *) I get:
warning: cast to pointer from integer of different size [-Wint-to-pointer-ast] buf = (char*)aligned_alloc(ALIGN_VALUE,BUF_SZ);
The only thing that seems to fix it is
buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);
I have made sure that I am including stdlib.h to avoid implicit declarations referred to in another post. I assumed the cast to char pointer should have resolved this. I am not understanding why the cast to uintptr_t resolves it when void* and uintptr_t are equivalent as far as I understand.
The following is an example of the structure of the file
#include <syslog.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <sys/mman.h> // mmap
#include <sys/time.h>
#include <unistd.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pthread.h>
void* ax_read_thread(void* arg)
{
fprintf(stderr, "read thread started\n");
ax_priv* priv = (ax_priv*)arg;
char* buf;
uint32_t count = 0;
size_t len, transferred = 0;
buf = (char*)(uintptr_t)aligned_alloc(ALIGN_VALUE,BUF_SZ);
if (buf == NULL){
fprintf(stderr, "Aligned alloc failed\n");
pthread_exit(NULL);
}
while(1){
//do things
}
}
Thank you for all of the help. I see now that the warning is a result of not indicating the proper version when invoking the compiler.
This answer largely summarizes the observations and suggestions from the comments thread, including mine and many others', and wraps them in a bit of expository prose.
In the first place, the problem arises because when you build your program with your present toolchain, in its current form, the aligned_alloc() function is not explicitly declared. In the absence of a declaration, the compiler is inferring its signature: it guesses that the function returns int, and that its parameter types are those obtained via the default argument promotions applied to the types of the actual arguments. The compiler then warns you that those inferences -- especially the return type -- seem inconsistent with how you're actually using the function.
The solution, supposing that the function is available in your C library at all, is to ensure that a correct prototype is provided. You could insert the prototype manually, but you shouldn't. Since it's a standard library function, you should get its declaration from the appropriate header, which for this function is stdlib.h.
HOWEVER, this particular function is new in C11, and evidently you're using a version of GCC that defaults to compiling for an earlier standard. Glibc supports that in part by protecting functions that are new in C11 with a feature-test macro, _ISOC11_SOURCE. This is for your protection: in the event that you're building code written for an earlier standard, and that code happens to provide is own function with the same name as one of C11's new functions, the feature-test system prevents you from suffering a name collision.
If you are indeed writing for C11, as seems to be the case, and if your version of gcc has an option to support C11 (i.e. -std=c11 and/or -std=gnu11), then compiling with that option enabled is your best alternative. If you happen to have a version of Glibc that provides aligned_alloc() but not a version of the compiler that supports a C11 mode, then you have the alternative of manually ensuring that the needed feature test macro is defined to the compiler before any of the standard headers are included. You can do that via a #define at the top of your source file, or via a command-line option to the compiler (e.g. -D_ISOC11_SOURCE=1).
Glibc does have aligned_alloc() from at least version 2.17 (but I think from as early as 2.16). GCC does have a C11 mode since at least version 4.8. If your versions of these components are at least that recent, then it should be sufficient to add the option -std=c11 (to omit GNU extensions) or -std=gnu11 (to support GNU extensions) to your compilation command:
gcc -std=c11 my_program.c
I'm trying to fix an undefined reference to memcpy_s() error. I've included string.h in my file and the memcpy() function works okay, and I've also tried including memory.h. I'm on x64 Windows 7 and using gcc 4.8.1 to compile.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void doMemCopy(char* buf, size_t buf_size, char* in, int chr) {
memcpy_s(buf, buf_size, in, chr);
}
memory for buf has been allocated in the main function, which calls doMemCpy(buf, 64, in, bytes). in is a string read from standard input
Exact error from cmd terminal:
undefined reference to "memcpy_s" collect2.exe: error: ld returned 1 exit status
GCC 4.8 does not include the function memcpy_s, or any of the other _s bounds checking functions as far as I can tell. These functions are defined in ISO 9899:2011 Annex K and they are optional to implement. Before using them you must check if __STDC_LIB_EXT1__ is defined.
These functions were originally implemented by Microsoft and many parties objected to including them in the standard. I think the main objection is that the error handling that is done by the functions involves a global callback handle that is shared between threads, but they are also quite inefficient.
Further reading is available from Carlos O'Donell and Martin Sebor in Updated Field Experience With Annex K — Bounds Checking Interfaces.
I've never used this, but AFAIK, you need to add
#define __STDC_WANT_LIB_EXT1__ 1
before
#include <string.h>
to use memcpy_s().
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.