Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCC compiler and converting const char* to char *

I am trying to build the M-SIM architecture simulator, but when I run the make utility, gcc reports this error (it is not even a warning)

note: expected 'char *' but argument is of type 'const char *'

Since when this is considered an error. Is there any flags that can bypass this check?

like image 850
Keeto Avatar asked Jan 18 '12 04:01

Keeto


3 Answers

This is an error because passing a const char* argument to a function that takes a char* parameter violates const-correctness; it would allow you to modify a const object, which would defeat the whole purpose of const.

For example, this C program:

#include <stdio.h>

void func(char *s) {
    puts(s);
    s[0] = 'J';
}

int main(void) {
    const char message[] = "Hello";
    func(message);
    puts(message);
    return 0;
}

produces the following compile-time diagnostics from gcc:

c.c: In function ‘main’:
c.c:10:5: warning: passing argument 1 of ‘func’ discards qualifiers from pointer target type
c.c:3:6: note: expected ‘char *’ but argument is of type ‘const char *’

The final message is marked as a "note" because it refers to the (perfectly legal) declaration of func(), explaining that that's the parameter declaration to which the warning refers.

As far as the C standard is concerned, this is a constraint violation, which means that a compiler could treat it as a fatal error. gcc, by default, just warns about it and does an implicit conversion from const char* to char*.

When I run the program, the output is:

Hello
Jello

which shows that, even though I declared message as const, the function was able to modify it.

Since gcc didn't treat this as a fatal error, there's no need to suppress either of the diagnostic messages. It's entirely possible that the code will work anyway (say, if the function doesn't happen to modify anything). But warnings exist for a reason, and you or the maintainers of the M-SIM architecture simulator should probably take a look at this.

(Passing a string literal to func() wouldn't trigger these diagnostics, since C doesn't treat string literals as const. (It does make the behavior of attempting to modify a string literal undefined.) This is for historical reasons. gcc does have an option, -Wwrite-strings, that causes it to treat string literals as const; this actually violates the C standard, but it can be a useful check.)

As I mentioned in a comment, it would be helpful if you'd show us the code that triggers the diagnostics.

I even downloaded and built the M-SIM architecture simulator myself, but I didn't see that particular message.

like image 139
Keith Thompson Avatar answered Oct 13 '22 06:10

Keith Thompson


Pointers to const-qualified types do not implicitly convert to pointers to non-const-qualified types. An explicit conversion via a cast is necessary, for example:

foo((char *)bar)
like image 22
R.. GitHub STOP HELPING ICE Avatar answered Oct 13 '22 07:10

R.. GitHub STOP HELPING ICE


First in a function call (of a function defined with a prototype), the arguments are converted to the type of the parameters as if by assignment.

You can assign a value of type char * to an object of type const char * but you cannot assign a const char * value to a char * object.

This constraint appears in the constraints of assignment operator:

(C99, 6.5.16.1p1) "One of the following shall hold: [...] - both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;"

This constraint permits the first assignment but disallows the second.

Declaring a pointer with type const char * means you won't modify the object pointed to by the pointer. So you can assign the pointer a value of char * type, it just means the object won't be modified through the const char * pointer.

But declaring a pointer of type char * means you could modify the object pointed to by the pointer. It would not make sense to assign it a value of const char *.

Remember that in C, const does not mean constant but rather read-only. The const qualifier put before pointer types means you promise not to modify objects through objects of these pointers types.

like image 4
ouah Avatar answered Oct 13 '22 05:10

ouah