What is the meaning of this warning, and how do I get rid of it?

J

James H. Newman

I have a portion of code along the following
lines:

volatile unsigned char x ;
unsigned int f(unsigned char *y) ;

When I do

unsigned int z = f(&x) ;

the compiler issues the following warning:

warning: passing arg 1 of `f' discards qualifiers from pointer target type

What does this exactly mean? How do I change my code so that the
compiler is happy about it?
 
W

Walter Roberson

I have a portion of code along the following
lines:
volatile unsigned char x ;
unsigned int f(unsigned char *y) ;
When I do
unsigned int z = f(&x) ;
the compiler issues the following warning:
warning: passing arg 1 of `f' discards qualifiers from pointer target type
What does this exactly mean?

x is volatile, so &x is a pointer to a volatile variable. However,
the receiving function is prototyped for non-volatile and so is not
going to know to preserve volatile semantics.
How do I change my code so that the
compiler is happy about it?

You could prototype f with y being volatile. Or you could create a
new non-volatile variable, initialize that with x's current value,
send that to f and store the modified result after f into x. However,
if x happens to be a memory-mapped I/O register or the like, or happens
to be set by a signal processing routine, then that probably won't
give you are result you want.
 
S

santosh

James said:
I have a portion of code along the following
lines:

volatile unsigned char x ;
unsigned int f(unsigned char *y) ;

When I do

unsigned int z = f(&x) ;

the compiler issues the following warning:

warning: passing arg 1 of `f' discards qualifiers from pointer target
type

It means what it says. Since 'f' is prototyped as taking an unsigned
char *, the volatile qualifier of 'x' is discarded when it is passed
to 'f'. Also note that the expression &x is actually of type volatile
unsigned char ** - not the type that you want to be passing to 'f'.
What does this exactly mean? How do I change my code so that
the compiler is happy about it?

Prototype and define 'f' as:

unsigned int f(volatile unsigned char *y) { /* ... */ }

If 'f' needs to change the caller's copy of it's argument then you
probably want:

unsigned int f(volatile unsigned char **y) { /* ... */ }
 
R

Raymond Martineau

James said:
I have a portion of code along the following
lines:

volatile unsigned char x ;
unsigned int f(unsigned char *y) ;

When I do

unsigned int z = f(&x) ;
[...]

If 'f' needs to change the caller's copy of it's argument then you
probably want:

unsigned int f(volatile unsigned char **y) { /* ... */ }

That would require x to be a pointer. Currently, it's simply an
unsigned char.
 
B

Barry Schwarz

It means what it says. Since 'f' is prototyped as taking an unsigned
char *, the volatile qualifier of 'x' is discarded when it is passed
to 'f'. Also note that the expression &x is actually of type volatile
unsigned char ** - not the type that you want to be passing to 'f'.

Where did the double asterisks come from? There is only one & and x
is not a pointer.


Remove del for email
 
R

Ron Ford

x is volatile, so &x is a pointer to a volatile variable. However,
the receiving function is prototyped for non-volatile and so is not
going to know to preserve volatile semantics.


You could prototype f with y being volatile. Or you could create a
new non-volatile variable, initialize that with x's current value,
send that to f and store the modified result after f into x. However,
if x happens to be a memory-mapped I/O register or the like, or happens
to be set by a signal processing routine, then that probably won't
give you are result you want.

A question for you, Walter.

Since C is completely safe, why does one use the 'volatile' function
specifier?
 
I

Ian Collins

Ron said:
Since C is completely safe, why does one use the 'volatile' function
specifier?

Who says C is completely safe?

volatile is a variable qualifier. It can not be applied to a function.

volatile tells the compiler not to optimise access to a variable. The
value of a volatile variable may be changed by an external source (a
hardware register for example).
 
S

santosh

Raymond said:
James said:
I have a portion of code along the following
lines:

volatile unsigned char x ;
unsigned int f(unsigned char *y) ;

When I do

unsigned int z = f(&x) ;
[...]

If 'f' needs to change the caller's copy of it's argument then you
probably want:

unsigned int f(volatile unsigned char **y) { /* ... */ }

That would require x to be a pointer. Currently, it's simply an
unsigned char.

Sorry, I made a mistake. I deserve it for posting at 03:45!
 
W

Walter Roberson

Ron Ford said:
A question for you, Walter.
Since C is completely safe, why does one use the 'volatile' function
specifier?

I don't recall ever saying that "C is completely safe". It was
certainly never designed to be "completely safe".
 
R

Ron Ford

I don't recall ever saying that "C is completely safe". It was
certainly never designed to be "completely safe".

No, I was engaging in hyperbole. I think of that which is "volatile" to be
opposed to that which is "safe." I've never used this qualifier in my own
code.

So I spent some time with K&R, thinking I would there find the reason to
use the "volatile." Instaed I find §A8.2 in the footnote: "the const and
volatile properties are new with the ANSI standard. The purpose of const
..... The purpose of volatile is to force an implementation to suppress
optimization that could otherwise occur...."

I'm not really any closer than a half hour ago. What is the difference
between type specifiers and type qualifiers?
 
R

rahul

So I spent some time with K&R, thinking I would there find the reason to
use the "volatile."  
Generally volatile is used in embedded system programming. Just a
hypothetical code:

#define READY 0x01
volatile char *mem = 0x1234; /*reading from some memory-mapped device.
When device is ready, it writes READY here
*assume initially it is not READY. */
/* some code */

while (READY != *mem) {
continue; /* busy waiting */
}

If it is not declared as volatile, the compiler may read the value
only once and the while loop becomes an infinite loop.
 
K

Keith Thompson

Ron Ford said:
No, I was engaging in hyperbole. I think of that which is
"volatile" to be opposed to that which is "safe." I've never used
this qualifier in my own code.

The English meaning of the term doesn't tell you much about what it
means in C. "volatile" is not the opposite of "safe" in this context.
So I spent some time with K&R, thinking I would there find the reason to
use the "volatile." Instaed I find §A8.2 in the footnote: "the const and
volatile properties are new with the ANSI standard. The purpose of const
.... The purpose of volatile is to force an implementation to suppress
optimization that could otherwise occur...."

If a program reads the value of a variable, and the compiler is able
to determine what its current value happens to be, it can generate
code that doesn't actually load the variable's value. For example:

...
int x = 42;
printf("x = %d\n", x);
...

The compiler can legitimately replace the printf() call with
puts("x = 42");
because it *knows* what the result of evaluating x would have been.

If x were qualified with "volatile", it would not be permitted to
perform that optimization.

The same applies to writes as well as reads.
I'm not really any closer than a half hour ago. What is the difference
between type specifiers and type qualifiers?

The latest draft of the standard is at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.
It defines both terms, in 6.7.2 and 6.7.3, respectively.

The type specifiers are void, char, short, int, long, and so forth.

The type qualifiers are const, restrict, and volatile (restrict is new
in C99).
 
C

CBFalconer

Keith said:
.... snip ...


If a program reads the value of a variable, and the compiler is
able to determine what its current value happens to be, it can
generate code that doesn't actually load the variable's value.
For example:

...
int x = 42;
printf("x = %d\n", x);
...

The compiler can legitimately replace the printf() call with
puts("x = 42");
because it *knows* what the result of evaluating x would have
been. If x were qualified with "volatile", it would not be
permitted to perform that optimization.

However this doesn't explain the necessity for volatile. If, for
example, that memory location holds the 'ready' status for data on
a peripheral, code is going to have to wait for the signal to
become true. Without the volatile it would read the signal once,
and then just remain in the testing loop, because it knows the
answer. With volatile, the system is forced to reread the ready
status on each pass through the loop.

Volatile means "something other than this code can alter this
value".
 
N

Nick Keighley

Ron Ford said:
since when has C been "completely safe". What does it mean?

I think you need a new dictionary. You seem to be using non-standard
meanings for "safe", "volatile" and "hyperbole"


why do you think this?


nor me
The English meaning of the term doesn't tell you much about what it
means in C. "volatile" is not the opposite of "safe" in this context.

"volatile" isn't the opposite of "safe" in English either!


if you wanted to know what volatile meant in C why didn't
you just ask that?

<snip>
 
S

santosh

CBFalconer said:
However this doesn't explain the necessity for volatile. If, for
example, that memory location holds the 'ready' status for data on
a peripheral, code is going to have to wait for the signal to
become true. Without the volatile it would read the signal once,
and then just remain in the testing loop, because it knows the
answer. With volatile, the system is forced to reread the ready
status on each pass through the loop.

Volatile means "something other than this code can alter this
value".

I remember a long thread on the exact semantics of volatile in
comp.std.c and there were some interesting discussions.

<http://groups.google.com/group/comp.std.c/browse_frm/thread/a1fc78b30424f8c5/35480a3974c5e831>
<http://groups.google.com/group/comp.std.c/browse_frm/thread/d0ab34c579b23a32/24cfd852741d242a>
 
V

vippstar

No, I was engaging in hyperbole. I think of that which is "volatile" to be
opposed to that which is "safe." I've never used this qualifier in my own
code.

So I spent some time with K&R, thinking I would there find the reason to
use the "volatile." Instaed I find §A8.2 in the footnote: "the const and
volatile properties are new with the ANSI standard. The purpose of const
.... The purpose of volatile is to force an implementation to suppress
optimization that could otherwise occur...."
<snip>
Here's a "real world" example, though not valid C.

volatile unsigned char *memory = (void *)0xDEADBEEFUL;
*memory = 'H';
*memory 'I';

The compiler could optimize this to *memory = 'I' if 'volatile' was
not present.
 
R

Ron Ford


These made great reading. It's been years since I've read Dan Pop.

I went through the standard, looking where volatile enters the ballgame,
and it's in a lot of places and a lot of footnotes. I would claim that it
is one of those things that you cannot *learn* from the standard; you must
antecedently know.

The fact that I have to ask leaves me to believe that I have no use for the
'volatile' function qualifier. I had hoped that things I didn't know about
'volatile' would enlighten things I didn't know about the function
specifier 'fortran', but not so.
 
R

Ron Ford

The English meaning of the term doesn't tell you much about what it
means in C. "volatile" is not the opposite of "safe" in this context.


If a program reads the value of a variable, and the compiler is able
to determine what its current value happens to be, it can generate
code that doesn't actually load the variable's value. For example:

...
int x = 42;
printf("x = %d\n", x);
...

The compiler can legitimately replace the printf() call with
puts("x = 42");
because it *knows* what the result of evaluating x would have been.

If x were qualified with "volatile", it would not be permitted to
perform that optimization.


This is a somewhat abstract point here. Can one restate this in terms of
*external* functions that might be called?

The same applies to writes as well as reads.


The latest draft of the standard is at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>.
It defines both terms, in 6.7.2 and 6.7.3, respectively.

The type specifiers are void, char, short, int, long, and so forth.

The type qualifiers are const, restrict, and volatile (restrict is new
in C99).

Of which type was register?

I looked at §6.7.2 and the next and am confident that this is beyond my
experience.
 
S

santosh

Ron Ford wrote:

The fact that I have to ask leaves me to believe that I have no use
for the 'volatile' function qualifier. [ ... ]

Qualify an object as volatile when you want to be sure that writes and
reads to it actually happen according to the abstract semantics of C.
If you need atomicity too, you can further use the sig_atomic_t
qualifier, though that everely restricts the guaranteed range of the
object.

<snip>
 
B

Ben Bacarisse

Ron Ford said:
This is a somewhat abstract point here. Can one restate this in terms of
*external* functions that might be called?

I think you need to restate your question (printf and puts are
external functions). What is it about Keith Thompson's example that
needs restating?
 

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,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top