Casting const to non const in c

I am working on a school project in which I need to reproduce many of the functions of the C library. I am simply struggling with one particular aspect of this.

If you look at the manual page for memchr , you will see that it accepts the input const void * and returns the usual void * . I would suggest that somewhere in the function they cast from const to non const for the returned variable.

However, when I do this ( clang -Weverything +Werror ), it will not compile. It works without the -Weverything tag, but I would prefer to use it if possible, anyway.

Is there a β€œright” way to do this?

+8
c casting
source share
3 answers

This hack will do it. In practice, sizeof(void *) is equal to sizeof(size_t) on each but the most obscure platform. However, I would advise against using this. Instead, -Weverything should be discarded. The standard C functions date back to 70 ', and the original C compilers were much less strict than today Clang or GCC with warnings enabled. The fact that you will find something β€œunsafe” in some of them is inevitable.

 void * memchr_(const void * ptr_, int c, size_t num); int main(void) { unsigned char ary[] = { 1, 6, 2, 45, 23, 75, 23, 43, 23 }, * ptr = NULL; ptr = memchr_(ary, 23, sizeof(ary) / sizeof(ary[0])); printf("ary = %p, ptr = %p, *ptr = %u\n", (void *)ary, (void *)ptr, *ptr); return 0; } void * memchr_(const void * ptr_, int c, size_t num) { size_t i; const unsigned char * ptr = ptr_; for(i = 0; i < num; i++) { if(ptr[i] == (unsigned char)c) { /* Casting to size_t first so that the compiler doesn't complain */ return (unsigned char *)(size_t)ptr + i; } } return NULL; } 
+1
source share

As you rightly pointed out, some C library functions must specify their const pointer argument in order to remove the const qualifier for the return value: memchr , strchr , strstr , etc. Other standard functions store a pointer to the end of the string to be analyzed in char ** , although it points to the array to which they were passed const char * : strtol, strod` ...

If your compiler is anal about this and generates warnings, try casting to uintptr_t before making it unsigned char * . You can also use union with both types of pointers.

The C standard specifies memcpy as follows:

7.24.5.1 memchr function

Summary

 #include <string.h> void *memchr(const void *s, int c, size_t n); 

Description

The memchr function detects the first occurrence of c (converted to unsigned char ) in the initial n characters (each of which is interpreted as unsigned char ) of the object pointed to by s . The implementation should behave as if it were reading characters sequentially and stopping as soon as the corresponding character was found.

Returns

The memchr function returns a pointer to a character located or a null pointer if the character does not occur in the object.

If you cannot use other types, you can leave with an act like size_t to suppress the compiler warning, here is a possible implementation:

 void *my_memchr(const void *ptr, int c, size_t num) { const unsigned char *cptr = ptr; while (num-- > 0) { if (*cptr++ == (unsigned char)c) { /* const pointer is cast first as size_t to avoid a compiler warning. * a more appropriate type for this intermediary cast would be uintptr_t, * but this type is not allowed here. */ return (void *)(size_t)(cptr - 1); } } return NULL; } 
+3
source share

The problem is the unwanted GCC-style diagnostics (Clang enabled) caused by the -Wcast-qual option at a specific location ( -Weverything includes -Wcast-qual ). The solution is to disable only -Wcast-qual only in this place.

 #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #endif void* non_const_ptr = (void*)const_ptr; #ifdef __GNUC__ #pragma GCC diagnostic pop #endif 

Casting to a non-pointer type and back to a pointer type will prevent the sale of all kinds of useful diagnostics and thus defeat the -Weverything goal.

#ifdef __GNUC__ included for greater portability. It is known that some compilers warn about those pragmas that they do not recognize, unless such pragmas come out.

0
source share

All Articles