Meaning of the warning

S

somenath

Hi All,
I have one question regarding the code.


#include<stdio.h>
char *f1(void);
char *f1(void)
{
char *abc ="Hello";

return abc;
}

int main(void )
{
char *p;
p = f1();

printf("%s\n", p);
return 0;
}


While compiling the above program as mentioned below I am getting the
meaning
$ gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align -
Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wstrict-
prototypes -Wmissing-declarations -Winline -Wundef -Wnested-externs -
Wcast-qual -Wshadow -Wconversion -Wwrite-strings -ffloat-store -O2
jj.c
jj.c: In function `f1':
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?
2) is it safe to return the local pointer value (i.e return abc ;) is
correct ?

My understanding is we should not return address of local
variable .So above code may not be working always .

Regards,
Somenath
 
A

Asbjørn Sæbø

somenath said:
#include<stdio.h>
char *f1(void);
char *f1(void)
{
char *abc ="Hello";

return abc;
}

int main(void )
{
char *p;
p = f1();

printf("%s\n", p);
return 0;
}


While compiling the above program as mentioned below I am getting the
meaning
$ gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align -
Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wstrict-
prototypes -Wmissing-declarations -Winline -Wundef -Wnested-externs -
Wcast-qual -Wshadow -Wconversion -Wwrite-strings -ffloat-store -O2
jj.c
jj.c: In function `f1':
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?

May it have anything to do with the signed-ness of char and the
signed-ness of "Hello"?

Asbjørn
 
W

Willem

Asbjørn wrote:
)
)> char *f1(void)
)> {
)> char *abc ="Hello";
)>
)> return abc;
)> }
)> <snip>
)> jj.c:5: warning: initialization discards qualifiers from pointer
)> target type
)>
)> I have two question
)> 1) What is the meaning of the warning ?
)
) May it have anything to do with the signed-ness of char and the
) signed-ness of "Hello"?

Unlikely. My first guess would rather be the const-ness.

About question 2): Is the above legal code ?

Yes it is. You're not returning the address of a local variable,
but that of a string literal. It's basically the same as:

char *f1(void)
{
return "Hello";
}

Which might give a similar warning, or might not.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Richard Heathfield

somenath said:

char *abc ="Hello";
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?

There are, alas, no restrictions on the amount of gibberish that
implementations are allowed to produce when translating a program.

In this case, gcc is confusing "constant" with "const". The string literal,
"Hello", is an array of 6 char (so it has type char[6]), with static
storage duration, and it's "constant" in the sense that, if you try to
modify it, the behaviour is undefined. But it is *not* const. The
assignment doesn't discard any qualifiers at all.

gcc means well - it's trying to stop you from hurting yourself by pointing
an ordinary non-const-qualified char * to a string literal, which is
invariably a bad idea - but the wording of the warning is broken.

2) is it safe to return the local pointer value (i.e return abc ;) is
correct ?

It's unwise. Use const char * when pointing at string literals.
My understanding is we should not return address of local
variable .So above code may not be working always .

String literals are not variables, and their lifetime is not restricted to
that of the function (if any) in which they appear.
 
P

pete

somenath said:
Hi All,
I have one question regarding the code.

#include<stdio.h>
char *f1(void);
char *f1(void)
{
char *abc ="Hello";

return abc;
}

int main(void )
{
char *p;
p = f1();

printf("%s\n", p);
return 0;
}

While compiling the above program as mentioned below I am getting the
meaning
$ gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align -
Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wstrict-
prototypes -Wmissing-declarations -Winline -Wundef -Wnested-externs -
Wcast-qual -Wshadow -Wconversion -Wwrite-strings -ffloat-store -O2
jj.c
jj.c: In function `f1':
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?
Spurious.

2) is it safe to return the local pointer value (i.e return abc ;) is
correct ?

My understanding is we should not return address of local
variable .So above code may not be working always .

"abc" isn't a local pointer value.
"abc" has static duration. It exists from program start to end.

Your code is flawless. The warning is garbage.

I suspect that your compiler thinks that the type of ("abc" + 0)
is supposed to be (const char *),
but in C, the type of ("abc" + 0) is (char *).

In C,
the type of ("abc") is (char [4]),
not (const char [4]).
 
C

Chris Dollin

somenath said:
Hi All,
I have one question regarding the code.

#include<stdio.h>
char *f1(void);
char *f1(void)
{
char *abc ="Hello";
return abc;
}

int main(void )
{
char *p;
p = f1();
printf("%s\n", p);
return 0;
}


While compiling the above program as mentioned below I am getting the
meaning
$ gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align -
Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wstrict-
prototypes -Wmissing-declarations -Winline -Wundef -Wnested-externs -
Wcast-qual -Wshadow -Wconversion -Wwrite-strings -ffloat-store -O2
jj.c
jj.c: In function `f1':
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?

Since you compiled with -Wwrite-strings, gcc non-Standardly makes
string literals be of type `const char *` rather than `char *`.
Then, when you try and assign the `const char *` to the `char *`
variable `abc`, it correctly complains: you've discarded the const
qualifier and left yourself open to someone changing something
which they're not supposed to change.

If you don't want this behaviour, don't ask for it.
2) is it safe to return the local pointer value (i.e return abc ;) is
correct ?

That isn't a "local pointer value"; it's the value of a local variable,
but that value is a pointer-to-string-literal, and a string literal
is a static and has lifetime equal to that of the entire executing
program.
My understanding is we should not return address of local
variable.

You shouldn't, and you aren't.
 
P

pete

pete said:
Hi All,
I have one question regarding the code.

#include<stdio.h>
char *f1(void);
char *f1(void)
{
char *abc ="Hello";

return abc;
}

int main(void )
{
char *p;
p = f1();

printf("%s\n", p);
return 0;
}

While compiling the above program as mentioned below I am getting the
meaning
$ gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align -
Wpointer-arith -Wbad-function-cast -Wmissing-prototypes -Wstrict-
prototypes -Wmissing-declarations -Winline -Wundef -Wnested-externs -
Wcast-qual -Wshadow -Wconversion -Wwrite-strings -ffloat-store -O2
jj.c
jj.c: In function `f1':
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?
Spurious.

2) is it safe to return the local pointer value (i.e return abc ;) is
correct ?

My understanding is we should not return address of local
variable .So above code may not be working always .

"abc" isn't a local pointer value.
"abc" has static duration. It exists from program start to end.

Your code is flawless. The warning is garbage.

I suspect that your compiler thinks that the type of ("abc" + 0)
is supposed to be (const char *),
but in C, the type of ("abc" + 0) is (char *).

In C,
the type of ("abc") is (char [4]),
not (const char [4]).

I forgot that we were talking about ("Hello") and not ("abc")

I suspect that your compiler thinks that the type of ("Hello" + 0)
is supposed to be (const char *),
but in C, the type of ("Hello" + 0) is (char *).

In C,
the type of ("Hello") is (char [6]),
not (const char [6]).
 
C

CBFalconer

somenath said:
#include<stdio.h>
char *f1(void);
char *f1(void) {
char *abc ="Hello";
return abc;
}

int main(void ) {
char *p;
p = f1();

printf("%s\n", p);
return 0;
}

While compiling the above program as mentioned below I am getting
the meaning .... snip ...
jj.c:5: warning: initialization discards qualifiers from pointer
target type

I have two question
1) What is the meaning of the warning ?
2) is it safe to return the local pointer value (i.e return abc ;)
is correct ?

My understanding is we should not return address of local
variable .So above code may not be working always .

Change "char *abc ="Hello";" to "const char *abc ="Hello";". You
are not returning a pointer to local storage, you are returning the
value of that local storage.
 
R

Richard Tobin

Richard Heathfield said:
In this case, gcc is confusing "constant" with "const".

.... which the user asked it to do, by means of the flag -Wwrite-strings:

`-Wwrite-strings'
When compiling C, give string constants the type `const
char[LENGTH]' so that copying the address of one into a
non-`const' `char *' pointer will get a warning; when compiling
C++, warn about the deprecated conversion from string constants to
`char *'. These warnings will help you find at compile time code
that can try to write into a string constant, but only if you have
been very careful about using `const' in declarations and
prototypes. Otherwise, it will just be a nuisance; this is why we
did not make `-Wall' request these warnings.

-- Richard
 
C

CBFalconer

^^^^^^^^^^^^^^^
.... snip ...
Not spurious.

.... snip ...
The code is flawed. The warnings are accurate.

Look up the meaning of the underlined gcc option above.

.... snip ...
In C, the type of ("Hello") is (char [6]), not (const char [6]).

Not when it has been told otherwise.
 
R

Richard Heathfield

Richard Tobin said:
... which the user asked it to do, by means of the flag -Wwrite-strings:

Quite. Nevertheless, gcc is confusing "constant" with "const".
 
S

somenath

Change "char *abc ="Hello";" to "const char *abc ="Hello";". You
are not returning a pointer to local storage, you are returning the
value of that local storage.

Just to clarify myself I would like to explain my understanding.
In the definition char *abc ="Hello";
Say 'H' is stored in address 100 and the 'e' will be stored in 108 and
so on . Now "abc" will have the value 100. When "return abc" is
getting executed it will try to return 100 . Is it not correct? If it
is so I am trying to return a address obtained locally. So it should
be wrong. I think I am missing the knowledge about string literal . Is
it handled specially than local variable .
Suppose
int x = 5;
return &x;
According to me we should not this, as address of x will be scrapped
after the execution flow returns from particular function.
 
R

Richard Heathfield

somenath said:
somenath wrote:
char *abc ="Hello";
return abc;
My understanding is we should not return address of local
variable .So above code may not be working always .

[...] You are not returning a pointer to local storage, you
are returning the value of that local storage.

Just to clarify myself I would like to explain my understanding.
In the definition char *abc ="Hello";
Say 'H' is stored in address 100 and the 'e' will be stored in 108 and
so on .

The byte is the smallest addressable unit of storage, and an array occupies
a contiguous block of bytes. If 'H' is in address 100, 'e' is going to be
in address 101.
Now "abc" will have the value 100. When "return abc" is
getting executed it will try to return 100 . Is it not correct?

Yes, that's right, although of course the 100 will have pointer type.
If it
is so I am trying to return a address obtained locally.

Yes, but it isn't the address of an automatic object, i.e. an object that
will automatically be destroyed on scope exit. Rather, it is the address
of a string literal, which survives throughout the lifetime of the program
and doesn't move around in memory (in the abstract machine, that is).
So it should be wrong.

No, but I understand why you're worried, so let's deal with that next.
I think I am missing the knowledge about string literal . Is
it handled specially than local variable .

No, it's just that it's not a local variable - it's a completely different
animal.
Suppose
int x = 5;
return &x;
According to me we should not this, as address of x will be scrapped
after the execution flow returns from particular function.

You are right that we shouldn't do this, but it's not because the address
will be scrapped, so much as that it will become meaningless (because the
object at that address is (conceptually) destroyed when the function
returns). The point of this (conceptual) destruction is that it makes room
for further automatic variables to be constructed during subsequent
processing.
 
C

Chris Dollin

somenath said:
Just to clarify myself I would like to explain my understanding.
In the definition char *abc ="Hello";
Say 'H' is stored in address 100 and the 'e' will be stored in 108 and
so on .

Well, that's mildly unlikely, `sizeof(char)` being 1, unless you
have 8-bit chars on a bit-addressed machine.
Now "abc" will have the value 100. When "return abc" is
getting executed it will try to return 100 . Is it not correct?

For values of `100` which are pointers.
If it is so I am trying to return a address obtained locally.

Nothing wrong with that. It's /exporting the address of an automatic
variable/ that's the problem.
So it should
be wrong. I think I am missing the knowledge about string literal . Is
it handled specially than local variable .

It's handled /differently/. It's not a local variable.
Suppose
int x = 5;
return &x;
According to me we should not this, as address of x will be scrapped
after the execution flow returns from particular function.

Yes. But that's not the same thing at all.
 
P

pete

CBFalconer said:
pete wrote:
In C, the type of ("Hello") is (char [6]), not (const char [6]).

Not when it has been told otherwise.

The C standard says that the array elements have type char.
You don't get to tell C otherwise.

Maybe there's another newsgroup
where your language extensions
that allow you to respecify parts of C
that have been already specified by the C standard,
are on topic, but this isn't it.
 
S

Stephen Sprunk

pete said:
CBFalconer said:
pete said:
In C, the type of ("Hello") is (char [6]), not (const char [6]).

Not when it has been told otherwise.

The C standard says that the array elements have type char.
You don't get to tell C otherwise.

-Wwrite-strings tells GCC to act _as if_ string literals were of type const
char[] and warn accordingly, though programs still compile correctly. Since
compilers are allowed to emit any diagnostics they want, even incorrect
ones, it's still compliant (as far as this goes, at least). This is little
different from the canonical example of warning on "if (x=0)".

This is a pretty decent warning to have around if you're starting a project
from scratch. Literals _should_ have been const char[] in C90, but they
were left as merely char[] due to the massive existing codebase that assumed
they weren't const.

S
 
H

Harald van Dijk

pete said:
CBFalconer said:
pete wrote:
In C, the type of ("Hello") is (char [6]), not (const char [6]).

Not when it has been told otherwise.

The C standard says that the array elements have type char. You don't
get to tell C otherwise.

-Wwrite-strings tells GCC to act _as if_ string literals were of type
const char[] and warn accordingly, though programs still compile
correctly. Since compilers are allowed to emit any diagnostics they
want, even incorrect ones, it's still compliant (as far as this goes, at
least). This is little different from the canonical example of warning
on "if (x=0)".

-Wwrite-strings causes this strictly conforming program to be rejected by
design:

int main(void) {
if (0) *"" = 'x';
}

Because of this, -Wwrite-strings, while very useful, causes gcc to not
act as a conforming implementation.


(However, even without -Wwrite-strings, gcc has a bug in which the
equally strictly conforming

int main(void) {
if (0) ""[0] = 'x';
}

is unconditionally rejected.)
 
C

CBFalconer

Harald said:
.... snip ...

(However, even without -Wwrite-strings, gcc has a bug in which the
equally strictly conforming

int main(void) {
if (0) ""[0] = 'x';
}

is unconditionally rejected.)

Not a bug. "" is a constant string, stored in (possibly) constant
memory, and thus is not writable. You may be complaining that gcc
hasn't bother to notice that the statment won't be executed, and
thus should suppress the message. However, compilers are allowed
to emit all the messages they wish.
 
C

CBFalconer

somenath said:
Just to clarify myself I would like to explain my understanding.
In the definition char *abc ="Hello";
Say 'H' is stored in address 100 and the 'e' will be stored in 108 and
so on . Now "abc" will have the value 100. When "return abc" is
getting executed it will try to return 100 . Is it not correct? If it
is so I am trying to return a address obtained locally. So it should
be wrong. I think I am missing the knowledge about string literal . Is
it handled specially than local variable .

No, because in your case above the 100 is an address in static
memory, and has nothing to do with the automatic memory of the
function. abc is in that automatic memory, and has been set to
100. The accessibility and content of 100 does not change on
exiting the function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top