volatile Info

B

Ben Pfaff

Malcolm McLean said:
I answered him that it will return the square.But he told that it wont
as the argument is volatile.

Can you people throw some insight into this problem?
He might be coming from a different angle to you. The only point of
declaring the parameter as "volatile" is so that some process from
outside the program can modify it. [...]

Another reason is to obtain predictable semantics in the presence
of setjmp() within the function.
 
B

Ben Bacarisse

Walter Banks said:
I don't think they are the same. I am assuming that
clock is an external true volatile where value as an
argument in square is copied as part of the call
square. The scoping issue that I see is value which
is a local variable with a scope restricted to square
with no apparent way that it can be modified.

I don't think that volatile objects have to be modified using their
name, which is why the scope of the name seems to me to be irrelevant.
That's why I posted another scenario in which none of the volatile stack
objects would be modified by name but where they would, nonetheless, be
modified.

<snip>
 
B

Ben Bacarisse

Keith Thompson said:
Ben Bacarisse said:
This is the bit I don't follow. What has the small scope got to do with
it? Is this the same:

int minutes(void)
{
extern volatile int clock;
return clock/60;
}

The scope is, if anything, even shorter but this seems like a normal use
of volatile.
[...]

I'd say that it's not the scope but the lifetime that's relevant.

I though that might be Walter's point but he has replied now and it
appears not.
In your example, ``clock'' (whose name conflicts with a predefined
function, BTW) has static storage duration, and it's entirely
plausible that something external to the program could modify it.

In the original example, the volatile object was simply a parameter
to a small function, existing only for the duration of that program's
execution.

"that function's execution" presumably.
It's far less plausible that any external entity would
even know about it, let alone touch it. (Unless some compiler magic
causes the creation of a volatile object to make it visible to some
external entity, but that's a bit of a stretch.) In principle, if
it's declared volatile then it's volatile; in practice, it hardly
makes sense to apply volatile to a simple object with automatic
storage duration.

No one is saying that the original example made sense. It's purpose
(however unintentional) has been to start a discussion of volatile
automatic objects and, having thought about the notion, it seems to me
that it is not entirely daft. Daft, yes, but not entirely daft. Hence
my example about a garbage collector where an external agent might be
able to tell which stack objects are pointers (it would need some help
from the compiler, of course).
 
J

James

manu said:
Hi guys,

In an interview I was asked the following question:

The function calculates the square of the number is given

int square(volatile int value)
{
return value*value;
}

His question was Will this function return square of the argument
passed?

I answered him that it will return the square.

It should because `value' is private to the function; right?

But he told that it wont
as the argument is volatile.

Highly contrived scenario: I guess the compiler could have given the address
of the `value' parameter to some other concurrently executing entity that
can perform stores.
 
J

jchl

Kenneth Brody said:
Finally, can a typedef include a volatile qualifier? My compiler allows
this, even with warnings at max:

typedef volatile int v_int;
int vsquare(v_int i)
{
return i*i;
}

(It appears to work, but that may be a compiler extension.)

It's quite common to do eg:

typedef volatile struct
{
unsigned int blah1;
unsigned int blah2;
unsigned int blah3;
/*
...however many regs the device has...
*/
} SomeHardwareReg;

int func()
{
SomeHardwareReg *const device = (SomeHardwareReg *)0x1234ABCD;
/* or whatever address the device is mapped to*/

device->blah1 = 1;

return 0;
}

to interface with some hardware device with memory-mapped registers.

Admittedly, it's quite a specific situation but working in embedded systems
it's quite common.
 
L

lawrence.jones

Ben Bacarisse said:
I don't think that volatile objects have to be modified using their
name, which is why the scope of the name seems to me to be irrelevant.

That's true in general, but auto objects don't even exist until their
containing function is called, so there simply isn't any way to locate
one other than by name within the calling function. Since we have the
complete code of the containing function for the example under
discussion and that code doesn't do anything that would make the
variable accessible to an external agent, there's no way the value can
change. So I would say it's the combination of scope, linkage, and
lifetime that limit the range of accessibility, which is actually the
key to whether volatile is meaningful or not.
 
M

Mark

Keith said:
Ah, but it's still potentially wrong. The new macro definition is:

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365UL)

Should not the usual arithmetic conversion apply to this expression? In this
macro 60, 60 and 24 are of integer type, and 365 is of unsigned long, which
would make integral constants be converted to unsigned long. Isn't it true?
which works just fine -- as long as INT_MAX >= 86400. The expression
is evaluated as

(((60 * 60) * 24) * 365UL)

How do you know that the expression is evaluated in exactly this order?
 
S

Seebs

Should not the usual arithmetic conversion apply to this expression? In this
macro 60, 60 and 24 are of integer type, and 365 is of unsigned long, which
would make integral constants be converted to unsigned long. Isn't it true?

Not exactly.
How do you know that the expression is evaluated in exactly this order?

Multiplication is left-associative. That's not actually the way the
wording is done, but it's what the words mean. Without any inner ()s,
(a * b * c * d)
is always equivalent to
(((a * b) * c) * d)

So the conversion to unsigned long happens at:

((60 * 60) * 24) * 365UL

so it's the value (60*60*24), or 86400, which is converted to unsigned long.

-s
 
B

Ben Bacarisse

That's true in general, but auto objects don't even exist until their
containing function is called, so there simply isn't any way to locate
one other than by name within the calling function. Since we have the
complete code of the containing function for the example under
discussion and that code doesn't do anything that would make the
variable accessible to an external agent, there's no way the value can
change.

That's an interesting point of view. I would have said that a volatile
object could have its value changed without there having to be an
obvious way for the external agent to see it.
So I would say it's the combination of scope, linkage, and
lifetime that limit the range of accessibility, which is actually the
key to whether volatile is meaningful or not.

I don't think scope matters because, as you agree, the name is not
needed for the object to be changed. The lifetime might surely have an
effect on how /likely/ a change might be but no on /whether/ it can
occur and you are sure that there is no way the value can change. To
me, that leaves only the linkage. If volatile objects whose names have
no linkage can't have their values changed, then would it not be better
to say so explicitly in the standard?

If, on the other hand, it really is a combination of the three, where is
the cut-off line on the scope/lifetime graph for automatic objects or,
if there is no hard line, what properties of the scope and lifetime
would change your verdict from can't change to might change?
 
R

Richard Bos

manu said:
int square(volatile int value)
{
return value*value;
}

His question was Will this function return square of the argument
passed?

I answered him that it will return the square.But he told that it wont
as the argument is volatile.

He is correct in theory, but I have never seen an implementation that
will actually change a volatile _function parameter_ behind your back. A
volatile normal object, sure. But not a function parameter.
Theoretically, though, it's possible.
A more important problem - depending on what values you pass to it - is
that the multiplication may overflow.
As per my knowledge the parameter is pushed to the stack and the
function square() will refer to that value even if it is defined as
the volatile.

Not necessarily to the stack. It could easily be passed in a register,
for example. The important thing, though, is that only a _value_ is ever
passed. The "volatile" applies _only_ to that passed value. The status
of whatever object (or literal value!) that was passed to the function
is completely irrelevant.
Therefore, while this program is officially required to read the value
of "value" twice, I would be very surprised if it ever resulted in two
different values. There would have to be a mechanism to designate this
volatile _function parameter_ to change in a certain way, and I've never
seen anything like that, much though it's legal.

Richard
 
K

Keith Thompson

Mark said:
Should not the usual arithmetic conversion apply to this expression?

Certainly, but they don't help.
In this macro 60, 60 and 24 are of integer type, and 365 is of
unsigned long, which would make integral constants be converted to
unsigned long. Isn't it true?

No.

BTW, all four constants are of integer type. 60, 60, and 24 are
of type int, and 365UL is, as you say, of type unsigned long.
(It's important to remember than "integer" and "int" are not
synonymous; int is one of several integer types.)
How do you know that the expression is evaluated in exactly this
order?

I didn't say it was evaluated in any particular order. Parentheses
denote grouping, that is, which operands are associated with which
operators; they don't control order of evaluation.

In the abstract machine, 60 is multiplied by 60, yielding the
value 3600 of type int. Then that's multiplied by 24, yielding the
value 86400 of type int -- which may or may not be representable.
Only then does the unsigned long value 365UL come into play,
causing 86400 to be promoted from int to unsigned long before
the final multiplication.

Of course the compiler is free to do whatever reordering and
precalculation it likes -- as long as the final result meets the
standard's requirements. If INT_MAX >= 86400, the
expression will almost certainly be evaluated at compile time
to a constant 31536000UL.

Here's a program that demonstrates the issue if int is 32
bits and unsigned long long is 64 bits:

#include <stdio.h>
#include <limits.h>

#define WRONG (30000 * 30000 * 24 * 365ULL)
#define RIGHT (30000ULL * 30000 * 24 * 365)

int main(void)
{
printf("int is %d bits\n",
(int)sizeof(int) * CHAR_BIT);
printf("unsigned long long is %d bits\n",
(int)sizeof(unsigned long long) * CHAR_BIT);

printf("WRONG = %llu\n", WRONG);
printf("RIGHT = %llu\n", RIGHT);
return 0;
}

gcc produces a warning:

c.c: In function ‘main’:
c.c:14: warning: integer overflow in expression

and the program produces the following output:

int is 32 bits
unsigned long long is 64 bits
WRONG = 45684684800
RIGHT = 7884000000000

Note that the behavior is actually undefined; 45684684800 is the
result that happens to be generated under this implementation.
 
K

Keith Thompson

manu said:
int square(volatile int value)
{
return value*value;
}
[...]

Not necessarily to the stack. It could easily be passed in a register,
for example. The important thing, though, is that only a _value_ is ever
passed. The "volatile" applies _only_ to that passed value. The status
of whatever object (or literal value!) that was passed to the function
is completely irrelevant.

To expand on that a bit:

The parameter (confusingly named "value") is an object, local to the
function, just as if it were declared after the opening brace. The
argument (the expression between the parentheses in the call to
square()) can be any arbitrary expression, not just an object or a
literal; as you say, the volatile qualifer doesn't affect that
expression in any way.
Therefore, while this program is officially required to read the value
of "value" twice, I would be very surprised if it ever resulted in two
different values. There would have to be a mechanism to designate this
volatile _function parameter_ to change in a certain way, and I've never
seen anything like that, much though it's legal.

The "volatile" qualifier actually does two things. It requires the
object to be accessed twice because it could be externally modified
between the two accesses, *and* it does so because accessing the object
is a side effect.
 
S

Shao Miller

Hi guys,

In an interview I was asked the following question:

The function calculates the square of the number is given

int square(volatile int value)
{
  return value*value;

}

His question was Will this function return square of the argument
passed?

I answered him that it will return the square.But he told that it wont
as the argument is volatile.

As per my knowledge the parameter is pushed to the stack and the
function square() will refer to that value even if it is defined as
the volatile.

Can you people throw some insight into this problem?
Regardless of the probabilities yielded by any practical hardware or
practical implementation, C99 simply defines that there is no
guarantee that this function "will return the square" (assuming the
interviewer meant the mathematical square of the mathematical value of
the 'int'-typed object designated by the 'value' identifier and not
something like, say, drawing a square on a chalkboard.)

Whether the value of 'value' is passed on the stack, in a register,
carved into a block of Swiss cheese, passed on a memory-mapped I/O
port which triggers a computer reset, or even whispered mouth-to-ear
around a room of a circle of friends, each calling out "Sequence
point!" as appropriate, 'volatile' means that the implementation
cannot guarantee the value, however infinitesimally small (or
otherwise) the reality of the object might be.

A good answer might have been "This function is not guaranteed to
return the square, but might return the square some of the time, when
the value of 'value' doesn't change by unknown factors and the
abstract machine is not corrupted."

It wouldn't even help to have a local 'int' and read the value once,
then work with the non-volatile local copy; the value of 'value' might
have changed before that assignment.

Who knows what interviewers wish to receive as a response? It might
be worth-while to pretend that they have an average knowledge of C and
that the presence of 'volatile' is a simple test to see if you have
any clue as to what it entails. Unfortunately, what interviewers
mightn't realize is that some C programmers might be inclined to give
it some serious thought (as evidenced by the number of posts in this
thread) and offer an answer with reasoning behind it that goes out-of-
scope of the interviewer's original intent for a simple test.

Oh well. :)
 
S

Shao Miller

Exactly how would that answer be different if the function argument wasn't
declared 'volatile'?
It needn't be, which is why it might have been a good answer. :) Some
references in the C99 C Standard draft to support my claim of
definition are:
- 5.1.2.3, point 5, first sub-point
- 6.7.3, point 6 (and footnote 116)

Enjoy.
 
S

Seebs

Exactly how would that answer be different if the function argument wasn't
declared 'volatile'?

I think the big difference is that 'volatile' suggests that the compiler
is explicitly obliged to generate code such that, IF someone is somehow able
to alter the value of the object between the two reads, it must get different
values, while without it, there's no obligation to even generate two separate
reads, as there's no modification of that object in the abstract machine.

-s
 
K

Keith Thompson

Scott Fluhrer said:
Exactly how would that answer be different if the function argument wasn't
declared 'volatile'?

It's the parameter, not the argument, that's declared volatile.

The difference is that, at least in principle, the two values fetched
by the subexpressions ``value'' and ``value'' in ``value*value''
could be different.
 
C

crisgoogle

I think the big difference is that 'volatile' suggests that the compiler
is explicitly obliged to generate code such that, IF someone is somehow able
to alter the value of the object between the two reads, it must get different
values, while without it, there's no obligation to even generate two separate
reads, as there's no modification of that object in the abstract machine.

No obligation to do two separate reads, correct. But neither are two
separate
reads prohibited. So I think Scott's question stands: how is the
answer
different _without_ the "volatile"? If there's some bizarre mechanism
by
which the value of, uh, "value" could change, then the returned result
may
not be be the square of the original argument.
 
S

Seebs

So I think Scott's question stands: how is the
answer
different _without_ the "volatile"? If there's some bizarre mechanism
by
which the value of, uh, "value" could change, then the returned result
may
not be be the square of the original argument.

Interesting question. Normally, "volatile" is used to hint that something
external might change unexpectedly. I'm not at all sure that it really
means anything on a function parameter, because after all, that's not really
external.

I'll tell you what: While I do think this may have semantic content, I would
be seriously shocked to find a single real-world example of a case where it
makes a difference in the output of a program.

-s
 
S

Shao Miller

No obligation to do two separate reads, correct. But neither are two
separate
reads prohibited. So I think Scott's question stands: how is the
answer
different _without_ the "volatile"? If there's some bizarre mechanism
by
which the value of, uh, "value" could change, then the returned result
may
not be be the square of the original argument.
Please see the draft with filename 'n1256.pdf'. Please read section
5.1.2.3, point 8. "...The keyword volatile would then be
redundant." (Except that it is also a hint to readers of source code
about objects whose values should not be cached, for example.)

However, consider what the interviewer might have been testing. It
might have been Richard Bos' note about overflow... But 'volatile' is
the "stick in your eye" in the example, in my opinion (whatever that's
worth).
 
B

Ben Bacarisse

Seebs said:
Normally, "volatile" is used to hint that something
external might change unexpectedly. I'm not at all sure that it really
means anything on a function parameter, because after all, that's not really
external.

No? What about a free-standing implementation that defines the entry
point to be:

int run_c(volatile int pad_pressure, volatile struct point location);

Is that not permitted and relatively sane?

<snip>
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top