volatile Info

M

manu

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?

Manu
 
T

Tom St Denis

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?

You were right and he was wrong. "volatile" just means the compiler
cannot optimize access around the variable [e.g. it can't alias it to
a CPU register]. your function with GCC 4.4.0 on my box produces

square:
..LFB0:
.cfi_startproc
movl %edi, -4(%rsp)
movl -4(%rsp), %edx
movl -4(%rsp), %eax
imull %edx, %eax
ret
.cfi_endproc

Which quite clearly produces a square and as you can see it loads the
value twice [as opposed to once and just aliasing it].

You might be better off without the job ;-)

Tom
 
M

Malcolm McLean

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. So you can't rely on getting
value^2 every time you call the function, in fact you should expect
some other return on occasion. However there's absolutely no
information as to what those circumstances might be, or why anyone
would want to do such a strange thing.
 
W

Willem

Malcolm McLean wrote:
)> 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. So you can't rely on getting
) value^2 every time you call the function, in fact you should expect
) some other return on occasion. However there's absolutely no
) information as to what those circumstances might be, or why anyone
) would want to do such a strange thing.

It's very unlikely that an _argument to a function_ could be changed
by an outside process. After all, it is a copy of what the function
was called with. I'm not even sure the compiler is obliged to put
it into a memory location. (Does 'volatile' alone require that ?)

In any case, if the interviewer really said it *won't* then he's wrong.
He could have said it *might not*, then he would have a (flimsy) case.


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
 
I

Ian Collins

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. So you can't rely on getting
value^2 every time you call the function, in fact you should expect
some other return on occasion.

That can't realistically happen in this context.
 
B

Ben Bacarisse

You were right and he was wrong. "volatile" just means the compiler
cannot optimize access around the variable [e.g. it can't alias it to
a CPU register]. your function with GCC 4.4.0 on my box produces

square:
.LFB0:
.cfi_startproc
movl %edi, -4(%rsp)
movl -4(%rsp), %edx
movl -4(%rsp), %eax
imull %edx, %eax
ret
.cfi_endproc

Which quite clearly produces a square and as you can see it loads the
value twice [as opposed to once and just aliasing it].

That does not directly answer the question. The question was not
whether the function returns 'value' multiplied by 'value' (in this
case the product of two stack relative moves) but whether it returns the
square of the argument passed. That is, can the reader be sure that
'value' is the same on both accesses?

From the C point of view, I'd say one can't be sure. Given knowledge of
the machine and how the implementation makes calls one could say more
because it might then be obvious that nothing outside of the C program
can manipulate function parameters.

From an interview perspective, I'd want to make it clear how peculiar
this construct is as well as trying to explain its consequences.

<snip>
 
M

Malcolm McLean

Malcolm McLean wrote:

 I'm not even sure the compiler is obliged to put
it into a memory location.  (Does 'volatile' alone require that ?)
Yes. An assembly routine could quite probably get the stack pointer
and know that 'value' was on top of it. So, for instance you could
have a keyboard interrupt that intercepted the call and negated value,
if the user manged to hit the i key (naturally) at the precise moment
the call was executing.
 
M

Malcolm McLean

The volatile in the argument for value refers to
value. This function will return the square of
value because the scope of value is limited to
the function square. Any other reference to value
would be out of scope.
The interviewer didn't use that argument. We can only speculate as to
why.
 
T

Tom St Denis

That does not directly answer the question.  The question was not
whether the function returns 'value' multiplied by 'value' (in this
case the product of two stack relative moves) but whether it returns the
square of the argument passed.  That is, can the reader be sure that
'value' is the same on both accesses?

So actually in this case volatile works against the goal since it
would be safer if the parameter was aliased.

Though if someone handed me code where a variable passed was being
modified externally [with the possible exception of it being a
hardware register pointer] I'd hand the code back to them and tell
them to do it properly.

Tom
 
B

Ben Bacarisse

Walter Banks said:
The volatile in the argument for value refers to
value. This function will return the square of
value because the scope of value is limited to
the function square. Any other reference to value
would be out of scope.

I think I am missing your point. It seems to me that the function will
return value multiplied by value and the compiler must use two accesses
to get these two quantities. The result need not be a perfect square,
let alone the square of the argument passed (as was asked).
 
B

Ben Bacarisse

Tom St Denis said:
That does not directly answer the question.  The question was not
whether the function returns 'value' multiplied by 'value' (in this
case the product of two stack relative moves) but whether it returns the
square of the argument passed.  That is, can the reader be sure that
'value' is the same on both accesses?

So actually in this case volatile works against the goal since it
would be safer if the parameter was aliased.

Though if someone handed me code where a variable passed was being
modified externally [with the possible exception of it being a
hardware register pointer] I'd hand the code back to them and tell
them to do it properly.

Oh, absolutely. At one level the code is obviously daft, but the
situation might arise in some peculiar settings.

Consider, for example, a freestanding implementation where the stack
bottom is mapped to interesting hardware. The entry point might then be
declared like this:

int c_start_up(volatile int clock,
volatile char in_b, volatile char outb,
int argc, char *argv);

It's just crazy for a function called 'square'. The function name
causes the whole question to be a puzzle. I'd much rather a question
that said something like "what does the declaration of c_start_up tell
you about this implementation?".
 
K

Keith Thompson

Vincenzo Mercuri said:
I think that question is taken (and modified) from the
following "C Test" (see page 5-6):

http://www.google.it/url?sa=t&sourc...oJ38Cw&usg=AFQjCNGcHAdLEHN_fMXVJuL5_4mZvTP4Hw

Interesting test. Apparently some of the formatting was messed up when
the PDF was generated.

The "volatile" question has a square() function whose argument is a
*pointer* to volatile int. That makes some sense. I wonder whether
it was the OP or the interviewer who got it wrong by changing it
to just a volatile int.

There's a serious error in his answer to the first question:

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

The "UL" suffix applies to an integer constant, *not* to a parenthesized
expression (even if it happens to be a constant expression).

I'm guessing the author had enough sense to run his examples through a
compiler. The above is a perfectly legal macro definition, but any
attempt to use it will result in a syntax error (unless you do something
silly like "#define UL").

A correct answer is:

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

or:

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

or even:

#define SECONDS_PER_YEAR 31536000 /* 60 * 60 * 24 * 365 */

(Note that the question explicitly says to ignore leap years.)
 
B

Ben Bacarisse

Kenneth Brody said:
Tom St Denis<[email protected]> writes:
[... volatile function parameters ...]
Oh, absolutely. At one level the code is obviously daft, but the
situation might arise in some peculiar settings.

Consider, for example, a freestanding implementation where the stack
bottom is mapped to interesting hardware. The entry point might then be
declared like this:

int c_start_up(volatile int clock,
volatile char in_b, volatile char outb,
int argc, char *argv);

It's just crazy for a function called 'square'. The function name
causes the whole question to be a puzzle. I'd much rather a question
that said something like "what does the declaration of c_start_up tell
you about this implementation?".

It tells me that the implementer had a moment of insanity, passing a
volatile parameter, rather than a pointer to a volatile value. :)

If I can be picky for a moment, you can't "pass a parameter" what gets
passed (if anything) is an argument and the argument is not volatile.
I.e. nothing volatile is being passed. This is start-up code, so it is
probably not called in the usual sense, but if it were, the argument
expression would be used to initialise (by assignment) the volatile
parameter object.

I'm not sure why a pointer to a volatile object (not a value) is any
better, but I suppose the smiley might mean that you don't think that
anyway! Is it a question of being less surprising?
And here's where I always have to stop and think, even after 27+ years
of C programming...

How does one declare "foo" to be a volatile pointer to int, and "bar"
to be a pointer to a volatile int?

int *volatile foo;
volatile int *bar;

(I include this just in case anyone reading is interested -- I know you
know it.)
Finally, can a typedef include a volatile qualifier? My compiler
allows this, even with warnings at max:

I can't think of any reason why not and I don't think there is any
specific text that limits type qualifiers in typedefs.
 
T

Tim Rentsch

manu said:
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?

There is a sense in which his statement could be argued
as "right". Beyond that, however, I would say he's at
least 99% wrong, in that if we chose an implementation
at random I'd be happy to bet money at 100 to 1 that
the numerical result would be the same as if 'volatile'
were left off. Unless he's trying to make some other
point (which is possible), this kind of comment shows
a poor understanding of what 'volatile' means. In
essentially all real implementations, there will be
no effect from adding 'volatile' in this way other
than that the generated code will probably be different,
and in particular the numerical result will be exactly
the same on any common hardware (essentially all hardware
that doesn't go WAY out of its way to make the result be
different).
 
T

Tim Rentsch

Ben Bacarisse said:
You were right and he was wrong. "volatile" just means the compiler
cannot optimize access around the variable [e.g. it can't alias it to
a CPU register]. your function with GCC 4.4.0 on my box produces

square:
.LFB0:
.cfi_startproc
movl %edi, -4(%rsp)
movl -4(%rsp), %edx
movl -4(%rsp), %eax
imull %edx, %eax
ret
.cfi_endproc

Which quite clearly produces a square and as you can see it loads the
value twice [as opposed to once and just aliasing it].

That does not directly answer the question. The question was not
whether the function returns 'value' multiplied by 'value' (in this
case the product of two stack relative moves) but whether it returns the
square of the argument passed. That is, can the reader be sure that
'value' is the same on both accesses?

From the C point of view, I'd say one can't be sure.

That's true in a sense, but it's also true that one can't
be sure what the result will be if 'volatile' is left off.
Furthermore an implementation could choose to define "what
constitutes an access to a volatile-qualified object" so
that there wouldn't be an difference whether the parameter
were made 'volatile' or not. Even assuming that 'volatile'
makes a difference in how the code is compiled, what the
effect is of using 'volatile' (in any circumstance, not
just this one) is -- by definition! -- outside the scope
of the implementation.

The subtlety of the question displays, at least with high
probability, a lack of understanding on the part of the
questioner.
Given knowledge of
the machine and how the implementation makes calls one could say more
because it might then be obvious that nothing outside of the C program
can manipulate function parameters.

Yes, although it seems likely that for any machine and any
implementation actually in existence today there is no
difference.
From an interview perspective, I'd want to make it clear how peculiar
this construct is as well as trying to explain its consequences.

Ditto and double ditto.
 
T

Tim Rentsch

Ben Bacarisse said:
Walter Banks said:
The volatile in the argument for value refers to
value. This function will return the square of
value because the scope of value is limited to
the function square. Any other reference to value
would be out of scope.

I think I am missing your point. It seems to me that the function will
return value multiplied by value and the compiler must use two accesses
to get these two quantities. [snip]

An implementation may have to use two accesses on the actual machine,
or may not, depending on how it defines what constitutes an access to
a volatile-qualified object. I believe it's the intent that this
provision grant sufficient freedom to basically disregard 'volatile'
everywhere (not counting cases like 'setjmp()', etc, where it actually
must make a specific difference).
 
K

Keith Thompson

Vincenzo Mercuri said:
This is a revised version and the author
has corrected his first answer! (fortunately)

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

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

which works just fine -- as long as INT_MAX >= 86400. The expression
is evaluated as

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

60 * 60 * 24 is 86400, which will overflow if INT_MAX is 32767.

Remember, in most cases the type of an expression is not affected
by the context in which it appears.

Note that

#define SECONDS_PER_YEAR (86400 * 365UL)

would be ok if INT_MAX < 86400, then the constant 86400 is of
type long.
 
K

Keith Thompson

Walter Banks said:
The volatile variable in the example has a very limited scope
which essentially prevents it from being altered. The C
standard suggests that both fetches should be independent.
This might be one example where the as if rule could be used.
I don't see any legal way that value can change once the
subroutine is called although I am open for some creative
code that would prove me wrong

I can't present any relevant code, but theoretically some entity
external to the program could modify the value of the parameter.
It would be tricky, since the parameter only exists for the duration
of a few instructions, but it could happen. It happens all the time
on the DS9K.

In practice, if the compiler happens to know that there is no
mechanism that can modify the parameter while the function is
executing, it can just access it once by the "as-if" rule. I'm not
100% sure this is ok, since accessing a volatile object is explicitly
listed as a "side effect" (5.1.2.3p2).
One of our compilers passed value through a processor
register and the multiply simply referenced the same
register for both sides of multiply in the same machine
cycle. I don't know of any reason that a local variable
cannot be stored in an register even if it is volatile

This is a kind of strange question for an interview.

Since the original document Vincenzo Mercuri found uses a pointer to
volatile (which actually makes sense), I think either the interviewer
or the OP messed it up.
 
B

Ben Bacarisse

Walter Banks said:
The volatile variable in the example has a very limited scope
which essentially prevents it from being altered.

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.
The C
standard suggests that both fetches should be independent.
This might be one example where the as if rule could be used.
I don't see any legal way that value can change once the
subroutine is called although I am open for some creative
code that would prove me wrong

Imagine a memory management system (maybe a garbage collector) that can
move pointers around. When memory is low, the C task is stopped and the
GC runs. It moves (or compacts or otherwise alters) the heap in a way
that means that every heap pointer on the stack needs to be altered.
This could be expressed in C by having all parameters and automatic
objects of pointer type declared volatile (at least those that the C
code knows are pointers into the managed heap).
One of our compilers passed value through a processor
register and the multiply simply referenced the same
register for both sides of multiply in the same machine
cycle. I don't know of any reason that a local variable
cannot be stored in an register even if it is volatile

That's perfectly fine, of course, because (as Tim has pointed out)
implementations have huge license to decide what constitutes an access
to a volatile object.
This is a kind of strange question for an interview.

I thought so too, but it's turned out to be more interesting than the
"correct" question which probably has a pointer to a volatile object.
 
K

Keith Thompson

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.

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. 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.
 

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,776
Messages
2,569,603
Members
45,197
Latest member
Sean29G025

Latest Threads

Top