Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting Const to non Const in c

Tags:

c

casting

I'm working on a school project in which I need to reproduce many of the C library functions. I'm just struggling with one specific aspect of it.

If you look at the man page for memchr you will see that it takes a const void * as input and returns a plain void *. I would assume that somewhere in the function they are casting from const to non const for the return variable.

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

Is there any "correct" way to do this?

like image 602
ryan27968 Avatar asked Jun 04 '17 16:06

ryan27968


People also ask

Can I cast const in C?

Const casts are only available in C++.

How do you cast off const?

The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a . This process of using const_cast to remove the const qualification of an object is called casting away constness.

Is const_cast safe?

const_cast is safe only if you're casting a variable that was originally non- const . For example, if you have a function that takes a parameter of a const char * , and you pass in a modifiable char * , it's safe to const_cast that parameter back to a char * and modify it.

Why does Const cast exist?

The whole purpose of const is to prevent you from modifying something, that's why your code generates an error. Adding in const_cast is basically telling the compiler to shut up, that you know what you're doing.


1 Answers

As you correctly noted, some C library functions must cast their const pointer argument to remove the const qualifier for the return value: memchr, strchr, strstr etc. Other standard functions store a pointer to the end of the parsed string into a char **, although it points into the array to which they were passed a const char *: strtol, strod`...

If your compiler is anal about this and produces warnings, try casting to uintptr_t before casting to unsigned char *. You can also use a union with both pointer types.

The C Standard specifies memcpy this way:

7.24.5.1 The memchr function

Synopsis

#include <string.h>

void *memchr(const void *s, int c, size_t n);

Description

The memchr function locates the first occurrence of c (converted to an unsigned char) in the initial n characters (each interpreted as unsigned char) of the object pointed to by s. The implementation shall behave as if it reads the characters sequentially and stops as soon as a matching character is found.

Returns

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

If you cannot use other types, you may get away with a cast as 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;
}
like image 160
chqrlie Avatar answered Oct 03 '22 18:10

chqrlie