0

I am currently working on a project including a somewhat generic linked list implementation using void pointers. Providing some utitily functions for these lists, I decided to make the identifying functions of elements only take (const void *). After adding the const keyword were necessary, I thought about how correct my code is now (if I implemented everything as it should be before).

As the compiler (GCC) didnt warn me, I decided to take a test. I compiled the following code with "gcc -g -Wall test.c" and received no warnings whatsover by GCC.

#include <stdio.h>
#include <stdlib.h>

void testf(const void *testp){
    *((int32_t *) testp) += 1;
}

void testf2(const int32_t *testp){
    *((int32_t *) testp) += 1;
}

int main(){
    int32_t testv = 0;
    printf("%i \n", testv);
    testf(&testv);
    printf("%i \n", testv);
    testf2(&testv);
    printf("%i \n", testv);
    return 0;
} 

The output is the following:

0 
1 
2 

I did not expect that C would actually crash by this, but I expected to receive a warning by the compiler. In this example im only casting, in my real functions I'm also assigning the const void pointers to a tmp variable.

Is this a bug?

Given how sophisticated todays compilers are, Id atleast expect a warning that Im casting a pointer to a non const pointer. If I change the cast and add the const keyword there too, GCC throws the usual error that I try to assign to a read only location

Am I supposed to rethink my trust to functions declaring const pointers? This is not what I understand as a contract :)

alk
  • 69,737
  • 10
  • 105
  • 255
Crumar
  • 122
  • 10
  • 3
    The casts silence the compiler. – alk Aug 25 '15 at 16:29
  • "*I'm also assigning the const void pointers to a tmp variable*" doing so *without* casting definitely would make the compiler yell out a warning. – alk Aug 25 '15 at 16:30
  • gcc will warn if casting away `const` if you enable the recommended warnings. However, if the compiler will not keep you from exploiting _undefined behaviour_. If you need that, use a different language. Ada might be a good candidate. – too honest for this site Aug 25 '15 at 16:30
  • I recognized that, but why. It can detect very much, but not casting a const pointer to non const? – Crumar Aug 25 '15 at 16:30
  • 2
    What do you expect? A cast tells the compiler to shut up, so you are complaining that the compiler does exactly what you tell it? – too honest for this site Aug 25 '15 at 16:32
  • @Olaf LOL, is Ada actually that weak/"dynamically" typed a language, that UB is a common practise? I'd like to read more into this if you have some good links. Thanks. – Cloud Aug 25 '15 at 16:33
  • @Dogbert: Ada dynamically typed? Huh? You seem to have missunderstood my comment. However, you confuse dynamically typing with weak typing. There is no connection between the two. E.g. Python is dynamically, **strong** typed. – too honest for this site Aug 25 '15 at 16:35
  • 1
    somewhat related http://stackoverflow.com/questions/32134305/changing-const-object-no-warning-also-in-which-case-it-is-ub – Giorgi Moniava Aug 25 '15 at 16:50
  • @Olaf The two seem to be associated if not synonymous with each other. http://stackoverflow.com/questions/2351190/static-dynamic-vs-strong-weak As for the question, you seem to suggest Ada or Ada devs frequently make use of undefined behavior. Is this the case? – Cloud Aug 26 '15 at 00:07
  • @Dogbert: If you had read the accepted answer, you might have noticed they are orthogonal. You can have any combination of static/dynamic and weak/strong. Have a look at the Python tag's descripion. In fact, Languages like Python catch any kind of UB or provide measures to prevent such situations (e.g. by type-testing before duck-typing). – too honest for this site Aug 26 '15 at 00:15
  • @Dogbert: Sorry, that was badly worded by me. I meant "However, the compiler will not ..." (remove the "if"). The second sentence intended to use a different language if OP wants the compiler from him exploiting UB. I think we do agree here. – too honest for this site Aug 26 '15 at 00:18
  • @Olaf Tired, misread the accepted answer. Though it said "weak/dynamic" and "strong/static". – Cloud Aug 26 '15 at 00:22

2 Answers2

5

Is this a bug?

No, it's not. By casting you are saying "I know what I am doing" to the compiler.

But GCC does have an option -Wcast-qual which would catch if a qualifier is casted away intentionally.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • I did not know about this, you're absolutely right. I misunderstood -Wall – Crumar Aug 25 '15 at 16:36
  • It *is* undefined behavior, though. [6.7.3/6](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf): "If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined." – John Bode Aug 25 '15 at 17:30
  • Interesting. I guess that only references to const values like hardcoded strings etc.? Because in this example Im actually just manipulating something on the stack (could also be on heap, but is not in process space?) – Crumar Aug 25 '15 at 17:55
  • @JohnBode That's applicable if the object itself has const qualifier which is not the case here. The actual object passed is mutable and writing to it (through cast) is legal i.e. it is *not* undefined behaviour. – P.P Aug 25 '15 at 20:03
0

I compiled the posted code using:

gcc -c -ggdb -Wall -Wextra -pedantic -std=c99 filename.c -o filename.o

(the following list is abbreviated for ease of reading)

error: 'int32_t' undeclared 

error: expected expression before ')' token
    *((int32_t *) testp) += 1;

warning: unused parameter 'testp'
    void testf(const void *testp){

with lots more warnings and errors regarding int32_t

Surely your compiler stated these same items.

BTW: The missing header file is stdint.h.

alk
  • 69,737
  • 10
  • 105
  • 255
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • The OP might have passed the `#define` `_GNU_SOURCE` to gcc from the command line using the option `-D_GNU_SOURCE`. Doing so makes the standard integer types available without including `stdint.h` – alk Aug 26 '15 at 05:35