In C, strings giving me warnings about initialization discarding qualifiers - c

I am getting the following warning for two lines of my code.
initialization discards qualifiers from pointer target type
The two lines are the sources of the warning.
function (const char *input) {
char *str1 = input;
char *str2 = "Hello World\0";
}
I think the first line gives an error because I try to assign a const char* to a char*. How would I fix that?

You need to declare it const:
const char *str1 = input;

void function (const char *input) {
char *str1 = input;
char *str2 = "Hello World\0";
}
in C an object of type char * cannot be initialized with an object of type const char *.
You have do this instead:
const char *str1 = input;
Also a string literal like "Hello World" is already null terminated, there is no need to add the null character yourself, do this instead:
char *str2 = "Hello World";

Related

Assign char to char *

I need an entire string to be one char of another string.
const char *const_string = "FOOBAR";
char *character_string = malloc(1024);
// character_string = const_string[3];
How can I make the last (commented) line work?
It seems you mean the following
void do_something(char *str, int idx)
{
str[0] = glob_str[idx];
str[1] = '\0';
}
You can add a check to the function that the index is not outside the string literal pointed to by glob_str.
Given
char *glob_str = "test test"; // glob_str is literal string and cannot be modified
then
glob_str[0] = val; // modification won't work
You need to change to
char glob_str[] = "test test";
See this question

How do I pass an anonymous string literal to a function?

Since a string literal can be initialized like
char myString [] = "somestring";
it seems logical to be able to use a function like
int stringLength ( char * str )
{
char * c2 = str;
while (*c2++);
return (c2-str);
}
and call it like
printf("%d",stringLength("somestring"));
However, I get an error when I do that.
Is there some way I can "cast" "something" into something proper to input into the function, or do I always have use an extra line like
char str [] = "somestring";
printf("%d",stringLength(str));
or is there something else I should be doing altogether?
char myString [] = "somestring";
creates an array of characters that are modifiable.
When you use
printf("%d",stringLength("somestring"));
it is analogous to:
char const* temp = "somestring";
printf("%d",stringLength(temp));
That's why the compiler does not like it.
You can change the function to use a char const* as argument to be able to use that.
int stringLength ( char const* str )
{
char const* c2 = str;
while (*c2++);
return (c2-str);
}
You know that your function "stringLength" will never mutate/change the contents of the string right so make that function so
int somefunc(const char* ptr)
{
const char* base=ptr;
while(*(ptr++));
return (ptr-base);
}
int main()
{
printf("%d",somefunc("HELLO"));
return 0;
}

strcpy() and strcat() giving errors in initialization & conversion. in C

invalid conversion from const char to const char* ,
initializing argument 2 of char* strcpy(char*, const char*) ,
invalid conversion from const char to const char* ,
initializing argument 2 of char* strcat(char*, const char*).
void subString(char s[])
{
char *sub;
char newS;
sub=s;
strcpy(newS,sub[0]);
strcat(newS,sub[1]);
printf("%s\n",newS);
return;
}
Please answer in terms of C language.
let s="abab"
you need to make newS a char* and allocate space for it...
char *newS = malloc(strlen(sub) + 1);

Why I get; initializing 'char *' with an expression of type 'const char *' discards qualifiers?

I can't figure out why I get this warning from clang by myself:
function_prototype_const_modifier.c:13:8: warning: initializing 'char *' with an
expression of type 'const char *' discards qualifiers
[-Wincompatible-pointer-types]
char *ptr1 = source;
^ ~~~~~~
1 warning generated.
The code is very simple
#include<stdio.h>
char *my_strcpy(char *destination, const char *source);
int main(void) {
char str1[] = "this is something";
char str2[] = "123456789123456789";
my_strcpy(str2, str1);
puts(str2);
return 0;
}
char *my_strcpy(char *destination, const char *source) {
char *ptr1 = source;
char *ptr2 = destination;
while(*ptr1 != '\0') {
*ptr2++ = *ptr1++;
}
*ptr2 = '\0';
return destination;
}
any idea?
source is a const char *, a pointer to const characters, so the characters cannot be changed by dereferencing the pointer (i. e. source[0] = 'A'; is a constraint violation).
However, assigning it to a char * discards this constraint; a simple char * suggests that the characters pointed to by the ptr1 pointer are not constant and you can now freely write ptr1[0] = 'A'; without getting compiler errors (a "diagnostic message").
Consider what this means when you pass in a string literal. Since a string literal is "readonly" (it's a const char []), trying to modify its contents is undefined behavior. So if you call
my_strcpy(destination, "Constant String");
but in the code for some reason you write
ptr1[0] = 'A';
you won't get a compiler diagnostic message because ptr1 is a pointer to non-const chars, but your program will still invoke undefined behavior (and in practice, most likely crash, since string literals are placed in readonly memory regions).
You just need to change:
char *ptr1 = source;
to:
const char *ptr1 = source;
You are pointing to the same area in memory, but not qualifying it as const as well, which the argument is.
You then allow the function body to modify that part of memory which is labelled const.
Because type of L.H.S is char * and type of R.H.S is const char *.
The reason is exactly as what error says:
function_prototype_const_modifier.c:13:8: warning: initializing 'char *' with an expression of type 'const char *' discards qualifiers
The statement allows you to discard the const qualifier and it allows to modify the pointed string through ptr1 and ptr2 and hence the compiler complains.
You are assigning a pointer to a character constant to a pointer to a char.
By doing that you risk modifying the character(s).
In this case, just about what's we can do.
Thanks of clearness information for #user529758.
Just plus a answer.
Modified:
#include<stdio.h>
char *my_strcpy(char *destination, const char *source);
int main(void) {
char str1[] = "this is something";
char str2[] = "123456789123456789";
my_strcpy(str2, str1);
puts(str2);
return 0;
}
char *my_strcpy(char *destination, const char *source) {
char *ptr1 = (char*)source;
char *ptr2 = destination;
while(*ptr1 != '\0') {
*ptr2++ = *ptr1++;
}
*ptr2 = '\0';
return destination;
}

How to put values to const char **?

If I declare a variable const char ** stringTable, how should I be able to put values to it if it is a const? (It has to be const because a function I am supposed to use takes const char ** as a parameter.)
Edit:
No you cannot convert from char ** to const char ** implicitly. Compiler complains:
cannot convert parameter 3 from 'char **' to 'const char **'
Wow, I'm surprised nobody got this! Maybe I can get a necromancer badge. Implicit const casting only scans one level deep. So a char* can become a const char* but it won't dig deep enough inside the a char** type to find what needs to be changed to make it a const char**.
#include <iostream>
using namespace std;
void print3( const char **three ) {
for ( int x = 0; x < 3; ++ x ) {
cerr << three[x];
}
}
int main() {
// "three" holds pointers to chars that can't be changed
const char **three = (const char**) malloc( sizeof( char** ) * 3 );
char a[5], b[5], c[5]; // strings on the stack can be changed
strcpy( a, "abc" ); // copy const string into non-const string
strcpy( b, "def" );
strcpy( c, "efg" );
three[0] = a; // ok: we won't change a through three
three[1] = b; // and the (char*) to (const char*) conversion
three[2] = c; // is just one level deep
print3( three ); // print3 gets the type it wants
cerr << endl;
return 0;
}
Apart from other mentions that you can pass char** into function that takes const char **,
const char** is a non-const pointer to const char*, you can declare it and freely put values of type const char* in it.
On the other hand, you would not be able to do it, if you declared it as const char * const * or const char * const * const.
yourfunc(const char **p);
...
const char *array_str[10];
array_str[0] = "foo"; /* OK, literal is a const char[] */
yourfunc(array_str);
Here is what cdecl says:
cdecl> explain const char **table
declare table as pointer to pointer to const char
cdecl> explain const char * const *table
declare table as pointer to const pointer to const char
cdecl> explain const char * const * const table
declare table as const pointer to const pointer to const char
That const declaration is a quarantee of the function, you dont have to fullfill it. That means the function will keep your array untouched (it will just read). So you can pass a nonconst variable to a function expecting const.
You can pass a char ** to a function declared as taking a const char ** -- Might be worth taking a look at the documentation for const on MSDN
char ** can be converted to const char **, so if you want to call a function which takes a const char ** as a parameter, just supply your char ** and it'll be implicitly converted.
If you want to write a function which takes a const char ** as parameter and then modifies the char data it references, you're breaking the contract with your compiler, even if you might get it to work via casts!
With my compiler (gcc version 3.4.4 in cygwin), I found that I could pass char * to const char *, but not char ** to const char **, unlike what most of the answers are saying.
Here is one way you can build something up that works; maybe it will help you.
void printstring( const char **s ) {
printf( "%s\n", *s );
}
int main( int argc, char** argv ) {
char *x = "foo"; // here you have a regular mutable string
const char *x2 = x; // you can convert that to a constant string
const char **y = &x2; // you can assign the address of the const char *
printstring(y);
}
you can un-const char* by using a cast operator: (char*)
void do_something(const char* s)
{
char* p=(char*)s;
p[0]='A';
}
use the same idea with the arrays char**
const char ** indicates that the underlying character is constant. So, while you can't do something like this:
const char **foo = ...;
**foo = 'a'; // not legal
but there is nothing preventing you from manipulating the pointer itself:
// all the following is legal
const char **foo = 0;
foo = (const char **)calloc(10, sizeof(const char *));
foo[0] = strdup("foo");
foo[1] = strdup("baz");
That said, if you did want to modify the actual character data, you could use a non-const pointer and cast it:
char **foo = ...;
func((const char **)foo);

Resources