473,386 Members | 1,846 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

va_arg and short

I was compiling a program written by someone else about six years ago, and
widely distributed at the time. It also includes makefiles for many
different systems, so I know it has been compiled with many different
compilers.

I got compile errors when it used va_arg to fetch an argument of type short.
That seemed a little strange to me, so I changed it to int and it compiled
just fine.

So now I wonder, just what is the rule for va_arg and short? It would seem
strange to reject certain types, yet that is what the compiler did.

-- glen
Nov 13 '05
99 8939
In <99aqb.82956$275.242639@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo***********@sunnews.cern.ch...
In <41**************************@posting.google.com > ne*****@tokyo.com(Mantorok Redgormor) writes:
>so to get the effect of a short, you would do something like this?
>
>(short) va_arg(ap, int);


The cast is *useless*, due to the integral promotions. If the original
argument had type short, va_arg(ap, int) will yield a value that is
guaranteed to be in the range of the short type.


But if you don't know that the original was of type short, and requiring int
in the va_arg call means you don't, ^^^^^^^^^^^^^^^^^

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Where did you get this idea from? You require int because you *know* that
short is promoted to int. However, if the function specification required
short, there is no point in casting. See below.
then you can cast it.
What for? If the caller provided a value outside of the range of short,
the cast will prevent you from detecting the error condition (the runtime
equivalent of casting malloc's return value). If the caller provided
a good value, the cast buys you nothing (the analogy with casting malloc
still holds). And if you later decide to change the type of the argument
from short to int, the cast becomes a potential bug (if you forget to
remove it) and no compiler is going to warn you about it. It's a typical
example of a "gratuitous" cast having a fairly high price.
I am not sure
now if the compiler is required to enforce the cast. (If it is required to
enforce short, is it also required to enforce float?)
I don't understand what you're talking about. The compiler doesn't
enforce anything, it merely performs the default argument promotions when
calling the function and nothing else.
As an unrelated topic, did you ever find a web page where the menu didn't
include the value you wanted, download the html page, modify it, and load it
into the browser? CGI programs should not rely on the menu to enforce
limits. va_arg() won't enforce them, either.


va_arg() doesn't enforce anything. It merely retrieves parameter values.
And your point is?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #51
In <v4aqb.82936$275.242278@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <sl******************@kir.physnet.uni-hamburg.de> Daniel Haude

<ha***@physnet.uni-hamburg.de> writes:
(snip)
>A normal computer user has plenty of business installing any kind of
>programs though.
Only binary distributions, validated for his platform.

>There might be a C compiler under the hood of --say-- the
>popular GNU "./configure && make && su root make install" mechanism, or
>there might be some "Windows InstallShield" program at work.

Both require administrator privileges, which the normal computer user is
not supposed to have. In practice, there are plenty of normal users that
do have administrator provileges, and this explains why many machines get
screwed up and reinstalled from scratch far more often than others.


If you want to install it as root, such is in /usr/bin, /usr/local/bin, or
if it requires setuid root, yes.

Many programs can be installed in a users own directory and run fine from
there. The program that started this thread runs fine in a user directory.
A large fraction of the GNU programs will, also.


But, in this case, by installing and using it you're not compromising the
system's integrity or other people's data integrity, you're only
compromising the integrity of *your* data. If things do go wrong,
you get what you deserve.

If you want to shoot yourself in the foot, a good OS should not prevent
you from doing it ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #52

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <99aqb.82956$275.242639@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo***********@sunnews.cern.ch...
In <41**************************@posting.google.com > ne*****@tokyo.com

(Mantorok Redgormor) writes:

>so to get the effect of a short, you would do something like this?
>
>(short) va_arg(ap, int);

The cast is *useless*, due to the integral promotions. If the original
argument had type short, va_arg(ap, int) will yield a value that is
guaranteed to be in the range of the short type.
But if you don't know that the original was of type short, and requiring intin the va_arg call means you don't, ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Where did you get this idea from? You require int because you *know* that
short is promoted to int. However, if the function specification required
short, there is no point in casting. See below.
If I read a value into a short variable with scanf() I can be 100% sure that
the value in the variable is within the range of a short. I might, for
example, use it as an array subscript knowing it couldn't be outside the
range of a short.
then you can cast it. What for? If the caller provided a value outside of the range of short,
the cast will prevent you from detecting the error condition (the runtime
equivalent of casting malloc's return value). If the caller provided
a good value, the cast buys you nothing (the analogy with casting malloc
still holds). And if you later decide to change the type of the argument
from short to int, the cast becomes a potential bug (if you forget to
remove it) and no compiler is going to warn you about it. It's a typical
example of a "gratuitous" cast having a fairly high price.
If I expect a short argument, assume that its value is within the range of a
short, but a sneaky caller supplies an int instead, I might, for example,
access outside of an array. The cast, if enforced, ensures that the value
is within the range of a short.

Though the & operator is probably better at limiting the range of values
than a (short) cast.
I am not sure
now if the compiler is required to enforce the cast. (If it is required toenforce short, is it also required to enforce float?)
Is the compiler required to enforce the cast, such that the value can never
be outside the range of a short?

Is it required to enforce (float), even on machines with extended floating
point form where all arithmetic is done with a 64 bit mantissa?
I don't understand what you're talking about. The compiler doesn't
enforce anything, it merely performs the default argument promotions when
calling the function and nothing else.


If the compiler enforces the cast it will truncate (or something else) the
value to fit within the range of a short, even though it is supplied, and is
assigned to, an in variable.
As an unrelated topic, did you ever find a web page where the menu didn't
include the value you wanted, download the html page, modify it, and load itinto the browser? CGI programs should not rely on the menu to enforce
limits. va_arg() won't enforce them, either.


va_arg() doesn't enforce anything. It merely retrieves parameter values.
And your point is?


The claim, not by me, was that the (short) cast on va_arg() would give the
effect of a short. You were claiming that the cast was useless. I
believe, but I am not sure, that with the cast the compiler is required to
convert to a short before assigning, or otherwise using, the return value of
(short)va_arg().

-- glen
Nov 13 '05 #53
Glen Herrmannsfeldt wrote:
bytes=malloc(sizeof(num)*sizeof(*bytes));
The example looks broken, but anyway,
Two size_t values multiplied together.


the issue was wanting to get wraparound modulo wordsize,
not what you would want here (or in any other legitmate
use of size_t).

Nov 13 '05 #54
In <wP********************@comcast.com> "Douglas A. Gwyn" <DA****@null.net> writes:
Glen Herrmannsfeldt wrote:
bytes=malloc(sizeof(num)*sizeof(*bytes));


The example looks broken, but anyway,
Two size_t values multiplied together.


the issue was wanting to get wraparound modulo wordsize,
not what you would want here (or in any other legitmate
use of size_t).


That's precisely what he wanted here: when multiplying two size_t values
together, to compute the size of a large object, overflow may happen and
you may want to be able to detect it.

As usual, you're replying to a post you haven't bothered to read
carefully.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #55
In <wCyqb.94051$275.261845@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <99aqb.82956$275.242639@attbi_s53> "Glen Herrmannsfeldt"<ga*@ugcs.caltech.edu> writes:
>"Dan Pop" <Da*****@cern.ch> wrote in message
>news:bo***********@sunnews.cern.ch...
>> In <41**************************@posting.google.com > ne*****@tokyo.com
>(Mantorok Redgormor) writes:
>>
>> >so to get the effect of a short, you would do something like this?
>> >
>> >(short) va_arg(ap, int);
>>
>> The cast is *useless*, due to the integral promotions. If the original
>> argument had type short, va_arg(ap, int) will yield a value that is
>> guaranteed to be in the range of the short type. >But if you don't know that the original was of type short, and requiringint >in the va_arg call means you don't,^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Where did you get this idea from? You require int because you *know* that
short is promoted to int. However, if the function specification required
short, there is no point in casting. See below.


If I read a value into a short variable with scanf() I can be 100% sure that
the value in the variable is within the range of a short. I might, for
example, use it as an array subscript knowing it couldn't be outside the
range of a short.


How does this fit into the context of the discussion?
>then you can cast it.
What for? If the caller provided a value outside of the range of short,
the cast will prevent you from detecting the error condition (the runtime
equivalent of casting malloc's return value). If the caller provided
a good value, the cast buys you nothing (the analogy with casting malloc
still holds). And if you later decide to change the type of the argument
from short to int, the cast becomes a potential bug (if you forget to
remove it) and no compiler is going to warn you about it. It's a typical
example of a "gratuitous" cast having a fairly high price.


If I expect a short argument, assume that its value is within the range of a
short, but a sneaky caller supplies an int instead, I might, for example,
access outside of an array. The cast, if enforced, ensures that the value
is within the range of a short.


And without the cast you have the chance to detect the error, instead of
silently accessing a "random" array element. Furthermore, how many times
have you declared arrays having SHRT_MAX elements?

As I have already *clearly* explained, the cast destructively hides the
caller error.
>I am not sure
>now if the compiler is required to enforce the cast. (If it is requiredto >enforce short, is it also required to enforce float?)
Is the compiler required to enforce the cast, such that the value can never
be outside the range of a short?


What the hell are you talking about? If you specify int in the va_arg
macro invocation, how can the compiler be required to enforce any cast to
short?
Is it required to enforce (float), even on machines with extended floating
point form where all arithmetic is done with a 64 bit mantissa?
What the hell are you talking about?
I don't understand what you're talking about. The compiler doesn't
enforce anything, it merely performs the default argument promotions when
calling the function and nothing else.


If the compiler enforces the cast it will truncate (or something else) the
value to fit within the range of a short, even though it is supplied, and is
assigned to, an in variable.


Why the hell should you expect the compiler to enforce any cast to
shorter types, when you specify int or double? I have clearly explained
to you that you cannot specify short of float in a va_arg invocation,
haven't I?
>As an unrelated topic, did you ever find a web page where the menu didn't
>include the value you wanted, download the html page, modify it, and loadit >into the browser? CGI programs should not rely on the menu to enforce
>limits. va_arg() won't enforce them, either.


va_arg() doesn't enforce anything. It merely retrieves parameter values.
And your point is?


The claim, not by me, was that the (short) cast on va_arg() would give the
effect of a short. You were claiming that the cast was useless.


And I have *clearly* explained why, but you chose to ignore my
explanations and arguments.
I
believe, but I am not sure, that with the cast the compiler is required to
convert to a short before assigning, or otherwise using, the return value of
(short)va_arg().


This is, of course, true, but POINTLESS, as I have already explained in
my previous post:

1. If the caller supplied a short value, the cast achieves nothing.

2. If the caller supplied a value out of the range of short, the cast
prevents you from detecting the error. You *will* end up with a short
value, but it will be the *wrong* short value and you'll never know it.
Furthermore, C99 allows such a cast to crash your program, but I don't
believe that any implementor would do that.

Dan

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #56
On Thu, 06 Nov 2003 20:59:08 GMT
"Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> wrote:
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <99aqb.82956$275.242639@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo***********@sunnews.cern.ch...
> In <41**************************@posting.google.com >
ne*****@tokyo.com(Mantorok Redgormor) writes:
>
> >so to get the effect of a short, you would do something like
> >this?
> >(short) va_arg(ap, int);
>
> The cast is *useless*, due to the integral promotions. If the
original> argument had type short, va_arg(ap, int) will yield a
value that is> guaranteed to be in the range of the short type.But if you don't know that the original was of type short, and
requiring intin the va_arg call means you don't, ^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Where did you get this idea from? You require int because you
*know* that short is promoted to int. However, if the function
specification required short, there is no point in casting. See
below.


If I read a value into a short variable with scanf() I can be 100%
sure that the value in the variable is within the range of a short.
I might, for example, use it as an array subscript knowing it couldn't
be outside the range of a short.


I think that Dan's point is that 6 weeks later someone else calls that
function (or does some other change) without realising that you expect
a short.
then you can cast it.
What for? If the caller provided a value outside of the range of
short, the cast will prevent you from detecting the error condition
(the runtime equivalent of casting malloc's return value). If the
caller provided a good value, the cast buys you nothing (the analogy
with casting malloc still holds). And if you later decide to change
the type of the argument from short to int, the cast becomes a
potential bug (if you forget to remove it) and no compiler is going
to warn you about it. It's a typical example of a "gratuitous" cast
having a fairly high price.


If I expect a short argument, assume that its value is within the
range of a short, but a sneaky caller supplies an int instead, I
might, for example, access outside of an array. The cast, if
enforced, ensures that the value is within the range of a short.


It doesn't. The following are the same as far as ISO C is concerned.

short i = va_arg(ap,int);
short i = (short)va_arg(ap,int);

According to P197 of K&R2, "When any integer is converted to a signed
tpe, the value is unchanged if it can be represented in the new type and
is implementation defined otherwise".

So casting or assigned an integer to a short is not guaranteed to
enforce the range, and if the implementation documented that on
accessing the short you might get the original int value (say because it
is stored in a register and has not been truncated) then I would assume
it would still be conforming and your use of it as an array index could
then invoke undefined behaviour.
Though the & operator is probably better at limiting the range of
values than a (short) cast.
I assume you mean passing a pointer to a short. However, that has the
potentially undesirable side effect of preventing passing a constant for
that parameter.
I am not sure
now if the compiler is required to enforce the cast. (If it is
required to
enforce short, is it also required to enforce float?)
Is the compiler required to enforce the cast, such that the value can
never be outside the range of a short?


No. See above.

If, on the other hand, you use unsigned short the result is defined by
the standard, but it is unlikely to be what you want.

IMHO you should write code to check the value yourself if you really
want a short when it is being passed as part of a varidac parameter.
Either that or accept that out of range values will invoke incorrect
behaviour (depending on your use you may not invoke UB).
Is it required to enforce (float), even on machines with extended
floating point form where all arithmetic is done with a 64 bit
mantissa?


In that case you may well find that short and double are identical.
I don't understand what you're talking about. The compiler doesn't
enforce anything, it merely performs the default argument promotions
when calling the function and nothing else.


If the compiler enforces the cast it will truncate (or something else)
the value to fit within the range of a short, even though it is
supplied, and is assigned to, an in variable.


It does not have to.

IIRC when casting from double to float it has to do the cast to enforce
the correct precision, but it still does not have to do what you expect
for out of range values.
As an unrelated topic, did you ever find a web page where the menu
didn't include the value you wanted, download the html page, modify
it, and load it
into the browser? CGI programs should not rely on the menu to
enforce limits. va_arg() won't enforce them, either.


va_arg() doesn't enforce anything. It merely retrieves parameter
values. And your point is?


The claim, not by me, was that the (short) cast on va_arg() would give
the effect of a short. You were claiming that the cast was useless.
I believe, but I am not sure, that with the cast the compiler is
required to convert to a short before assigning, or otherwise using,
the return value of(short)va_arg().


If you are assigning to a short it makes not difference.
If the value is converted to a short (either by cast or due to
assignment) and it is out of range you invoke implementation defined
behaviour which I would expect to not be what you want.
--
Mark Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spamtrap, it is real and I read it.
Nov 13 '05 #57
"Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> wrote in message news:<wCyqb.94051$275.261845@attbi_s53>...
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <99aqb.82956$275.242639@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo***********@sunnews.cern.ch...
> In <41**************************@posting.google.com > ne*****@tokyo.com (Mantorok Redgormor) writes:>
> >so to get the effect of a short, you would do something like this?
> >
> >(short) va_arg(ap, int);
>
> The cast is *useless*, due to the integral promotions. If the original
> argument had type short, va_arg(ap, int) will yield a value that is
> guaranteed to be in the range of the short type.But if you don't know that the original was of type short, and requiring intin the va_arg call means you don't, ^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Where did you get this idea from? You require int because you *know* that
short is promoted to int. However, if the function specification required
short, there is no point in casting. See below.


If I read a value into a short variable with scanf() I can be 100% sure that
the value in the variable is within the range of a short. I might, for
example, use it as an array subscript knowing it couldn't be outside the
range of a short.


Where did scanf() enter into this?
then you can cast it.
What for? If the caller provided a value outside of the range of short,
the cast will prevent you from detecting the error condition (the runtime
equivalent of casting malloc's return value). If the caller provided
a good value, the cast buys you nothing (the analogy with casting malloc
still holds). And if you later decide to change the type of the argument
from short to int, the cast becomes a potential bug (if you forget to
remove it) and no compiler is going to warn you about it. It's a typical
example of a "gratuitous" cast having a fairly high price.


If I expect a short argument, assume that its value is within the range of a
short, but a sneaky caller supplies an int instead, I might, for example,
access outside of an array. The cast, if enforced, ensures that the value
is within the range of a short.


I don't know what "enforced" means to you; it means nothing to the
standard. If the value returned by va_arg(ap,int) is outside the valid
range of 'short', the behavior is undefined.
Though the & operator is probably better at limiting the range of values
than a (short) cast.
I have no idea what you mean by that statement.
I am not sure
now if the compiler is required to enforce the cast. (If it is required toenforce short, is it also required to enforce float?)
Is the compiler required to enforce the cast, such that the value can never
be outside the range of a short?


The behavior is undefined; nothing is required.
I don't understand what you're talking about. The compiler doesn't
enforce anything, it merely performs the default argument promotions when
calling the function and nothing else.


If the compiler enforces the cast it will truncate (or something else) the
value to fit within the range of a short, even though it is supplied, and is
assigned to, an in variable.


In that case, the answer is "No"; there's no such requirement in the
standard. With unsigned types you have a guarantee of wrap-around, so
that

UINT_MAX+1U == 0U

but there's no such guarantee with any other type.
As an unrelated topic, did you ever find a web page where the menu didn't
include the value you wanted, download the html page, modify it, and load itinto the browser? CGI programs should not rely on the menu to enforce
limits. va_arg() won't enforce them, either.


va_arg() doesn't enforce anything. It merely retrieves parameter values.
And your point is?


The claim, not by me, was that the (short) cast on va_arg() would give the
effect of a short. ...


It will, when the argument is in range, produce the same exact value
with a type of short. What it does when the value is out of range is
undefined.
... You were claiming that the cast was useless. I
believe, but I am not sure, that with the cast the compiler is required to
convert to a short before assigning, or otherwise using, the return value of
(short)va_arg().


Yes, it is, when the value is in range.
Nov 13 '05 #58
In <8b*************************@posting.google.com> ku****@wizard.net (James Kuyper) writes:
I don't know what "enforced" means to you; it means nothing to the
standard. If the value returned by va_arg(ap,int) is outside the valid
range of 'short', the behavior is undefined.


Chapter and verse, please.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #59
Dan Pop wrote:
That's precisely what he wanted here: when multiplying two size_t values
together, to compute the size of a large object, overflow may happen and
you may want to be able to detect it.
What is actually wanted is to enforce the total size limit of
SIZE_MAX. That is not necessarily the same as checking for
wraparound.
As usual, you're replying to a post you haven't bothered to read
carefully.


As usual, you haven't bothered to understand any point of view
but your own.
Nov 13 '05 #60

"Mark Gordon" <sp******@flash-gordon.me.uk> wrote in message
news:20031107133110.453220b5.sp******@flash-gordon.me.uk...
On Thu, 06 Nov 2003 20:59:08 GMT
"Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> wrote:
"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <99aqb.82956$275.242639@attbi_s53> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:
>"Dan Pop" <Da*****@cern.ch> wrote in message
>news:bo***********@sunnews.cern.ch...
>> In <41**************************@posting.google.com >
>ne*****@tokyo.com(Mantorok Redgormor) writes:
>>
>> >so to get the effect of a short, you would do something like
>> >this?
>> >(short) va_arg(ap, int);
>>
>> The cast is *useless*, due to the integral promotions. If the
>original> argument had type short, va_arg(ap, int) will yield a
>value that is> guaranteed to be in the range of the short type.

>But if you don't know that the original was of type short, and
>requiring

int
>in the va_arg call means you don't,

^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Where did you get this idea from? You require int because you
*know* that short is promoted to int. However, if the function
specification required short, there is no point in casting. See
below.


If I read a value into a short variable with scanf() I can be 100%
sure that the value in the variable is within the range of a short.
I might, for example, use it as an array subscript knowing it couldn't
be outside the range of a short.


I think that Dan's point is that 6 weeks later someone else calls that
function (or does some other change) without realising that you expect
a short.
>then you can cast it.

What for? If the caller provided a value outside of the range of
short, the cast will prevent you from detecting the error condition
(the runtime equivalent of casting malloc's return value). If the
caller provided a good value, the cast buys you nothing (the analogy
with casting malloc still holds). And if you later decide to change
the type of the argument from short to int, the cast becomes a
potential bug (if you forget to remove it) and no compiler is going
to warn you about it. It's a typical example of a "gratuitous" cast
having a fairly high price.


If I expect a short argument, assume that its value is within the
range of a short, but a sneaky caller supplies an int instead, I
might, for example, access outside of an array. The cast, if
enforced, ensures that the value is within the range of a short.


It doesn't. The following are the same as far as ISO C is concerned.

short i = va_arg(ap,int);
short i = (short)va_arg(ap,int);


No, I meant int i=(short) va_arg(ap,int);
According to P197 of K&R2, "When any integer is converted to a signed
tpe, the value is unchanged if it can be represented in the new type and
is implementation defined otherwise". So casting or assigned an integer to a short is not guaranteed to
enforce the range, and if the implementation documented that on
accessing the short you might get the original int value (say because it
is stored in a register and has not been truncated) then I would assume
it would still be conforming and your use of it as an array index could
then invoke undefined behaviour.
That was the question I was ask, whether the compiler would enforce the
cast. It seems, then, that it doesn't, which is the answer to the question
I was trying, not very successfully, to ask.
Though the & operator is probably better at limiting the range of
values than a (short) cast.
No, I mean something like int i=va_arg(ap,int) & 0x7fff; /* assume I want
16 bit signed short */

(snip)
If, on the other hand, you use unsigned short the result is defined by
the standard, but it is unlikely to be what you want.

IMHO you should write code to check the value yourself if you really
want a short when it is being passed as part of a varidac parameter.
Either that or accept that out of range values will invoke incorrect
behaviour (depending on your use you may not invoke UB).
Yes, that is probably the best way. I was asking if the other way would
work, and apparently it doesn't.
Is it required to enforce (float), even on machines with extended
floating point form where all arithmetic is done with a 64 bit
mantissa?


In that case you may well find that short and double are identical.


So it also doesn't enforce casts to (float).
I don't understand what you're talking about. The compiler doesn't
enforce anything, it merely performs the default argument promotions
when calling the function and nothing else.
If the compiler enforces the cast it will truncate (or something else)
the value to fit within the range of a short, even though it is
supplied, and is assigned to, an in variable. It does not have to.
That is what I was asking.
IIRC when casting from double to float it has to do the cast to enforce
the correct precision, but it still does not have to do what you expect
for out of range values.
No, I was only asking about the precision question for the float/double cast
question.
>As an unrelated topic, did you ever find a web page where the menu
>didn't include the value you wanted, download the html page, modify
>it, and load it
>into the browser? CGI programs should not rely on the menu to
>enforce limits. va_arg() won't enforce them, either. va_arg() doesn't enforce anything. It merely retrieves parameter
values. And your point is?


No, the question was for a cast, applied to the result of the va_arg() call.
The claim, not by me, was that the (short) cast on va_arg() would give
the effect of a short. You were claiming that the cast was useless.
I believe, but I am not sure, that with the cast the compiler is
required to convert to a short before assigning, or otherwise using,
the return value of(short)va_arg().

If you are assigning to a short it makes not difference.
If the value is converted to a short (either by cast or due to
assignment) and it is out of range you invoke implementation defined
behaviour which I would expect to not be what you want.


Well, I might use it in a subscript for an array dimensioned USHORT_MAX, and
cast to (unsigned short) in attempt to force the subscript to be within
range. There are other ways to do it, and it seems like this way doesn't
work. That is all that I was asking, not for a long discussion. Well, the
original question was answered a long time ago, but this new question was
not.

-- glen
Nov 13 '05 #61

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <8b*************************@posting.google.com> ku****@wizard.net (James Kuyper) writes:
I don't know what "enforced" means to you; it means nothing to the
standard. If the value returned by va_arg(ap,int) is outside the valid
range of 'short', the behavior is undefined.


Chapter and verse, please.


I was (more recently) asking about the effect of the cast on the result,
such as:

int i=(short) va_arg(ap,int);

Someone else had suggested that cast, not me.

It seems from a previous reply that the compiler isn't obliged to enforce
that cast. That i may have values outside those allowable for a short.

thanks for the discussion,

-- glen
Nov 13 '05 #62
ai***@acay.com.au (Peter Nilsson) wrote on 02.11.03 in <63**************************@posting.google.com >:
I wonder why va_arg could not accept a type subject to promotion and
handle them accordingly, i.e. accept the promoted type implicitly and
convert it to the original/requested type. [So, cases like the
character types and unsigned short, which might promote to signed or
unsigned int, could be handled without having to resort to integer
limit checks.]


va_arg is a macro. This is insanely hard to get right from a macro (unless
the compiler offers some builtin functions specifically to get it right),
because at the preprocessor stage you don't normally have the kind of
information you need to determine what the default promotions are.

Or, to put it another way, the default promotions are inherently
unportable.

And even if you have that information for a specific implementation, it's
not really very much fun to determine what to do from a type with only the
preprocessor. You *really* want a builtin here - or a guarantee that you
don't have to cope with unpromoted types.

For an excercise, write a macro that determines which integer type a user
defined type actually is. Your choice of how to return the result. Then
remember that va_arg also needs to cope with floats, pointers, structs ...

The preprocessor wasn't designed to cope with this sort of problem.

Kai
--
http://www.westfalen.de/private/khms/
"... by God I *KNOW* what this network is for, and you can't have it."
- Russ Allbery (rr*@stanford.edu)
Nov 13 '05 #63
ai***@acay.com.au (Peter Nilsson) wrote on 05.11.03 in <3f******@news.rivernet.com.au>:
The standard(s) did add mandatory extension requirements for things like
setjmp.


How so? AFAIK, setjmp() was traditionally implemented without compiler
extensions of any kind. (It did typically use library routines written in
assembler, which is a different thing from a compiler extension.)

Kai
--
http://www.westfalen.de/private/khms/
"... by God I *KNOW* what this network is for, and you can't have it."
- Russ Allbery (rr*@stanford.edu)
Nov 13 '05 #64
ch***********@cbau.freeserve.co.uk (Christian Bau) wrote on 02.11.03 in <ch*********************************@slb-newsm1.svr.pol.co.uk>:
In article <aE0pb.81932$HS4.680953@attbi_s01>,
"Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> wrote:
I was compiling a program written by someone else about six years ago, and
widely distributed at the time. It also includes makefiles for many
different systems, so I know it has been compiled with many different
compilers.

I got compile errors when it used va_arg to fetch an argument of type
short. That seemed a little strange to me, so I changed it to int and it
compiled just fine.

So now I wonder, just what is the rule for va_arg and short? It would
seem strange to reject certain types, yet that is what the compiler did.


When you use the va_arg macro, the type that you supply must (with some
exceptions that don't apply here) match the type of the actual argument
_after default promotions_.

Any argument of type short would be promoted to int, so using short in
the va_arg macro can never match the type of the actual argument after
default promotions.


A conforming implementation could have short == int, though, in which case
short would be just fine to use.

Once there were quite a large number of implementations for which this was
true.

Kai
--
http://www.westfalen.de/private/khms/
"... by God I *KNOW* what this network is for, and you can't have it."
- Russ Allbery (rr*@stanford.edu)
Nov 13 '05 #65
In <3F***************@null.net> "Douglas A. Gwyn" <DA****@null.net> writes:
Dan Pop wrote:
That's precisely what he wanted here: when multiplying two size_t values
together, to compute the size of a large object, overflow may happen and
you may want to be able to detect it.


What is actually wanted is to enforce the total size limit of
SIZE_MAX. That is not necessarily the same as checking for
wraparound.


What is the difference? How else can you enforce the total size limit
of SIZE_MAX?
As usual, you're replying to a post you haven't bothered to read
carefully.


As usual, you haven't bothered to understand any point of view
but your own.


As usual, you're naive enough to believe that you can save your ass by
hand waving replies.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #66
Da*****@cern.ch (Dan Pop) writes:
"Douglas A. Gwyn" <DA****@null.net> writes:
Dan Pop wrote:
That's precisely what he wanted here: when multiplying two size_t values
together, to compute the size of a large object, overflow may happen and
you may want to be able to detect it.


What is actually wanted is to enforce the total size limit of
SIZE_MAX. That is not necessarily the same as checking for
wraparound.


What is the difference? How else can you enforce the total size limit
of SIZE_MAX?


For size_t x and y, you have x <= SIZE_MAX && y <= SIZE_MAX,
and x + y <= SIZE_MAX iff SIZE_MAX - x >= y,
and x * y <= SIZE_MAX iff x == 0 || SIZE_MAX / x >= y.

You can hence enforce the total size limit using functions such as
the following:

size_t plus(size_t x, size_t y) {
return (SIZE_MAX - x >= y) ? x + y ; error();
}

size_t times(size_t x, size_t y) {
return (x == 0 || SIZE_MAX / x >= y) ? x * y ; error();
}

--
Fergus Henderson <fj*@cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
Nov 13 '05 #67
In <AbVqb.103266$9E1.493592@attbi_s52> "Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> writes:

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <8b*************************@posting.google.com> ku****@wizard.net(James Kuyper) writes:
>I don't know what "enforced" means to you; it means nothing to the
>standard. If the value returned by va_arg(ap,int) is outside the valid
>range of 'short', the behavior is undefined.


Chapter and verse, please.


I was (more recently) asking about the effect of the cast on the result,
such as:

int i=(short) va_arg(ap,int);


Isn't the effect of the cast clearly enough described by the standard?
Someone else had suggested that cast, not me.

It seems from a previous reply that the compiler isn't obliged to enforce
that cast. That i may have values outside those allowable for a short.


You will have whatever value your caller has provided. What is the merit
of losing this value via a cast and getting some *garbage* instead, if the
caller provided a value outside the range of short? And how many times
do I have to ask this question without getting a reply?

Furthermore, C99 allows the cast to raise an arbitrary signal, if the
value is out of range. Hopefully, no sane implementor would do that...

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #68
In <3f********@news.unimelb.edu.au> Fergus Henderson <fj*@cs.mu.oz.au> writes:
For size_t x and y, you have x <= SIZE_MAX && y <= SIZE_MAX,
and x + y <= SIZE_MAX iff SIZE_MAX - x >= y,
and x * y <= SIZE_MAX iff x == 0 || SIZE_MAX / x >= y.

You can hence enforce the total size limit using functions such as
the following:

size_t plus(size_t x, size_t y) {
return (SIZE_MAX - x >= y) ? x + y ; error();
}

size_t times(size_t x, size_t y) {
return (x == 0 || SIZE_MAX / x >= y) ? x * y ; error();
}


Thanks. Has anyone actually did it this way in *real* C code?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #69
In <bo**********@sunnews.cern.ch> Da*****@cern.ch (Dan Pop) writes:
In <3f********@news.unimelb.edu.au> Fergus Henderson <fj*@cs.mu.oz.au> writes:
For size_t x and y, you have x <= SIZE_MAX && y <= SIZE_MAX,
and x + y <= SIZE_MAX iff SIZE_MAX - x >= y,
and x * y <= SIZE_MAX iff x == 0 || SIZE_MAX / x >= y.

You can hence enforce the total size limit using functions such as
the following:

size_t plus(size_t x, size_t y) {
return (SIZE_MAX - x >= y) ? x + y ; error();
}

size_t times(size_t x, size_t y) {
return (x == 0 || SIZE_MAX / x >= y) ? x * y ; error();
}


Thanks. Has anyone actually did it this way in *real* C code?


And a related question: is calloc() *required* to fail if nmemb * size
exceeds SIZE_MAX?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #70
Da*****@cern.ch (Dan Pop) wrote in message news:<bo**********@sunnews.cern.ch>...
In <8b*************************@posting.google.com> ku****@wizard.net (James Kuyper) writes:

....
[Re: (short)va_arg(ap,int)]
I don't know what "enforced" means to you; it means nothing to the
standard. If the value returned by va_arg(ap,int) is outside the valid
range of 'short', the behavior is undefined.


Chapter and verse, please.


The relevant section is 6.3.1.3, but I overstated the problem a
little; it doesn't say "undefined". What it says is "either the result
is implementation-defined or an implementation-defined signal is
raised".

However, there's no portable way for a program to determine which
signal (if any) needs to be caught, and even if you do catch it,
there's almost nothing portably safe you can do from the signal
handler, and returning from the signal handler might itself cause
undefined behavior. Even if you merely get an implementation-defined
value, that's no better than calling rand().

Therefore, as a practical matter there's little difference between
this and undefined behavior, at least for programs intended to be
portable. I do concede, though, that it is in fact
implementation-defined, not undefined.
Nov 13 '05 #71
In <8b**************************@posting.google.com > ku****@wizard.net (James Kuyper) writes:
Da*****@cern.ch (Dan Pop) wrote in message news:<bo**********@sunnews.cern.ch>...
In <8b*************************@posting.google.com> ku****@wizard.net (James Kuyper) writes:

...
[Re: (short)va_arg(ap,int)]
>I don't know what "enforced" means to you; it means nothing to the
>standard. If the value returned by va_arg(ap,int) is outside the valid
>range of 'short', the behavior is undefined.


Chapter and verse, please.


The relevant section is 6.3.1.3, but I overstated the problem a
little; it doesn't say "undefined". What it says is "either the result
is implementation-defined or an implementation-defined signal is
raised".

However, there's no portable way for a program to determine which
signal (if any) needs to be caught, and even if you do catch it,
there's almost nothing portably safe you can do from the signal
handler, and returning from the signal handler might itself cause
undefined behavior. Even if you merely get an implementation-defined
value, that's no better than calling rand().

Therefore, as a practical matter there's little difference between
this and undefined behavior, at least for programs intended to be
portable. I do concede, though, that it is in fact
implementation-defined, not undefined.


Furthermore, there is no known conforming implementation where a signal
is raised (this is a new C99 "feature" that would break existing and
*portable* C89 code).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #72

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo*********@sunnews.cern.ch...

(snip of related question)
Thanks. Has anyone actually did it this way in *real* C code?


And a related question: is calloc() *required* to fail if nmemb * size
exceeds SIZE_MAX?


What do you do on those unfortunate systems where pointers can address
memory much larger than size_t?

(Remembering all the tricks from the large model x86 days. Maybe that would
be huge model, which I tried not to use.)

This is not unrelated to the fseek() and ftell() problem on file systems
that allow files greater than 2GB or 4GB, but no convenient way to address
them.

-- glen
Nov 13 '05 #73

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bo**********@sunnews.cern.ch...
In <8b**************************@posting.google.com > ku****@wizard.net (James Kuyper) writes:

(snip)
The relevant section is 6.3.1.3, but I overstated the problem a
little; it doesn't say "undefined". What it says is "either the result
is implementation-defined or an implementation-defined signal is
raised". However, there's no portable way for a program to determine which
signal (if any) needs to be caught, and even if you do catch it,
there's almost nothing portably safe you can do from the signal
handler, and returning from the signal handler might itself cause
undefined behavior. Even if you merely get an implementation-defined
value, that's no better than calling rand().


(snip)
Furthermore, there is no known conforming implementation where a signal
is raised (this is a new C99 "feature" that would break existing and
*portable* C89 code).


Not at all trying to start a language war, (there are enough already), but
in PL/I returning from signal handlers is supposed to be portably safe and
well defined. (There is the assumption that the OS and hardware support it.
Machines with imprecise interrupts tended not to support it very well.)

I was disappointed that Java supplies no way to return from signal handlers.

-- glen
Nov 13 '05 #74
"Douglas A. Gwyn" <DA****@null.net> wrote in message news:<3F***************@null.net>...
Dan Pop wrote:
That's precisely what he wanted here: when multiplying two size_t values
together, to compute the size of a large object, overflow may happen and
you may want to be able to detect it.


What is actually wanted is to enforce the total size limit of
SIZE_MAX.


Recently, I've taken to writing code that assumes that the largest
safe size of an object allocation is the minimum of PTRDIFF_MAX and
SIZE_MAX.

--
Peter
Nov 13 '05 #75
Dan Pop wrote:
Thanks. Has anyone actually did it this way in *real* C code?


Most programmers don't try to create objects so large that
they have to worry about SIZE_MAX. If you do have to worry,
use a method like what Francis showed.

Nov 13 '05 #76
Glen Herrmannsfeldt wrote:
"Dan Pop" <Da*****@cern.ch> wrote ...
And a related question: is calloc() *required* to fail if nmemb * size
exceeds SIZE_MAX?

It probably doesn't matter; how is a s.c. program going to
treat the resulting chunk of memory as a single object with
size exceeding SIZE_MAX?
What do you do on those unfortunate systems where pointers can address
memory much larger than size_t?
The answer to questions on this general issue is the subject
of some debate, so if you want an authoritative resolution
you need to get a DR submitted asking for clarification.
Some think that the implementation is obliged to choose a
type for size_t such that this cannot happen.
This is not unrelated to the fseek() and ftell() problem on file systems
that allow files greater than 2GB or 4GB, but no convenient way to address
them.


That's an implementation that has made some unwise choices.
You can use fgetpos/fsetpos for many such purposes, but there
is no standard way to perform arithmetic on those offset
cookies.

Nov 13 '05 #77

"Douglas A. Gwyn" <DA****@null.net> wrote in message
news:gd********************@comcast.com...
Glen Herrmannsfeldt wrote:
"Dan Pop" <Da*****@cern.ch> wrote ...
And a related question: is calloc() *required* to fail if nmemb * size
exceeds SIZE_MAX?

Someone wrote:
It probably doesn't matter; how is a s.c. program going to
treat the resulting chunk of memory as a single object with
size exceeding SIZE_MAX? What do you do on those unfortunate systems where pointers can address
memory much larger than size_t?
Well, that is a good question. Maybe 16 bit int is long past, and we
shouldn't worry about the problem. Though with 32 bit int and memories
larger than 4GB maybe we should. Consider a machine with 64 bit pointers,
but 32 bit int. You could still increment the pointer multiple times, less
than 2GB each time. Now, reasonably likely the machine would also have a
64 bit long or long long, but maybe doesn't supply the ability to increment
pointers (or subscript arrays) with them.

I notice some time ago that Java requires subscripts to be int (or castable
to int).
The answer to questions on this general issue is the subject
of some debate, so if you want an authoritative resolution
you need to get a DR submitted asking for clarification.
Some think that the implementation is obliged to choose a
type for size_t such that this cannot happen. This is not unrelated to the fseek() and ftell() problem on file systems
that allow files greater than 2GB or 4GB, but no convenient way to address them.

That's an implementation that has made some unwise choices.
You can use fgetpos/fsetpos for many such purposes, but there
is no standard way to perform arithmetic on those offset
cookies.


Those are interesting, but it seems that some still have a 32bit limit.
HP-UX seems to have non-standard fgetpos64() and fsetpos(64).

Well, the argument of fseek() and the return from ftell() were long (or even
int?) many years before 4GB of memory was affordable, real or virtual. It
looks like a mistake now, and then we have things like fseek64() and
ftell64().

Some systems have a 64 bit long, but that seems relatively rare these days.

-- glen
Nov 13 '05 #78
On 2003-11-10 14:56, Dan Pop wrote:
In <3f********@news.unimelb.edu.au> Fergus Henderson <fj*@cs.mu.oz.au> writes:
For size_t x and y, you have x <= SIZE_MAX && y <= SIZE_MAX,
and x + y <= SIZE_MAX iff SIZE_MAX - x >= y,
and x * y <= SIZE_MAX iff x == 0 || SIZE_MAX / x >= y.

You can hence enforce the total size limit using functions such as
the following:

size_t plus(size_t x, size_t y) {
return (SIZE_MAX - x >= y) ? x + y ; error();
}

size_t times(size_t x, size_t y) {
return (x == 0 || SIZE_MAX / x >= y) ? x * y ; error();
}


Thanks. Has anyone actually did it this way in *real* C code?


Yes, though I used type-generic macros.
Excerpt:

/*
* T is assumed to be an integer type with minimum value T_MIN and
* maximum value T_MAX. Yields +1 or -1 if the multiplication of
* a and b in T would result in an overflow or underflow,
* respectively, otherwise 0.
*
* Preconditions: (1) a and b are integer values
* (2) T is an integer type
* (3) T_MIN and T_MAX are values of integer type
* (4) T_MIN and T_MAX are valid limits of type T
* (5) T can represent a and b
*
* Does not compile if either T_MIN, T_MAX, a or b is not a numeric
* value or if T is not a numeric type.
*/

#define UT__integer_prd_ovf(T, T_MIN, T_MAX, a, b) ( \
(T)(a) > 0 \
? (T)(b) > 0 \
? (T)(T_MAX) / (T)(b) < (T)(a) ? +1 : 0 \
: (T)(T_MIN) / (T)(a) > (T)(b) ? -1 : 0 \
: (T)(b) > 0 \
? (T)(T_MIN) / (T)(b) > (T)(a) ? -1 : 0 \
: (T)(b) < 0 \
? ( (T)(T_MAX) + (T)(T_MIN) > 0 \
? ( (T)(T_MAX) / -(T)(b) < -(T)(a)) \
: (-((-(T)(T_MAX)) / (T)(b)) > (T)(a)) \
) ? +1 : 0 \
: 0 \
)

#define UT_integer_prd_ovf(T, T_MIN, T_MAX, a, b) ( \
UT_PRECONDITION("a is an integer value", \
UT_is_integer_value(a)), \
UT_PRECONDITION("b is an integer value", \
UT_is_integer_value(b)), \
UT_PRECONDITION("T is an integer type", \
UT_is_integer_type(T)), \
UT_PRECONDITION("T_MIN is an integer value", \
UT_is_integer_value(T_MIN)), \
UT_PRECONDITION("T_MAX is an integer value", \
UT_is_integer_value(T_MAX)), \
UT_PRECONDITION("T_MIN and T_MAX are valid limits of type T", \
UT__valid_integer_type_limits(T, T_MIN, T_MAX)), \
UT_PRECONDITION("T can represent a", \
UT__convertible_to_integer_type(a, T, T_MIN, T_MAX)), \
UT_PRECONDITION("T can represent b", \
UT__convertible_to_integer_type(b, T, T_MIN, T_MAX)), \
UT__integer_prd_ovf(T, T_MIN, T_MAX, a, b) \
)

[...]

#define UT_size_prd_ovf(a, b) UT_integer_prd_ovf(size_t, 0, SIZE_MAX, a, b)

There were similar macros for all common integer types and operations,
for saturation arithmetics and so on.

-- Niklas Matthies
Nov 13 '05 #79
In comp.std.c Douglas A. Gwyn <DA****@null.net> wrote:


You can use fgetpos/fsetpos for many such purposes, but there
is no standard way to perform arithmetic on those offset
cookies.


There is, but it's ugly:

/* add n to pos */
fsetpos(f, pos);
fseek(f, n, SEEK_CUR);
fgetpos(f, &pos);

-Larry Jones

Monopoly is more fun when you make your own Chance cards. -- Calvin
Nov 13 '05 #80
"Douglas A. Gwyn" wrote:

Dan Pop wrote:
Thanks. Has anyone actually did it this way in *real* C code?


Most programmers don't try to create objects so large that
they have to worry about SIZE_MAX. If you do have to worry,
use a method like what Francis showed.


Many of the programs I've work on over the past 20 years have pushed the
limit on available memory, and in several cases they pushed the limit on
what C99 would call SIZE_MAX (though most of them have been C90
programs). I have no idea how common that is; it may be more common in
the kind of applications I work on than in other kinds you're more
familiar with.
Nov 13 '05 #81
In article <8x*********@khms.westfalen.de>,
kaih=8x*********@khms.westfalen.de (Kai Henningsen) wrote:
ch***********@cbau.freeserve.co.uk (Christian Bau) wrote on 02.11.03 in
<ch*********************************@slb-newsm1.svr.pol.co.uk>:
In article <aE0pb.81932$HS4.680953@attbi_s01>,
"Glen Herrmannsfeldt" <ga*@ugcs.caltech.edu> wrote:
I was compiling a program written by someone else about six years ago,
and
widely distributed at the time. It also includes makefiles for many
different systems, so I know it has been compiled with many different
compilers.

I got compile errors when it used va_arg to fetch an argument of type
short. That seemed a little strange to me, so I changed it to int and it
compiled just fine.

So now I wonder, just what is the rule for va_arg and short? It would
seem strange to reject certain types, yet that is what the compiler did.
When you use the va_arg macro, the type that you supply must (with some
exceptions that don't apply here) match the type of the actual argument
_after default promotions_.

Any argument of type short would be promoted to int, so using short in
the va_arg macro can never match the type of the actual argument after
default promotions.


A conforming implementation could have short == int, though, in which case
short would be just fine to use.


No, you can't have short == int. You can have sizeof short == sizeof
int, you can have SHORT_MAX == INT_MAX etc., but you cannot have short
== int.
Once there were quite a large number of implementations for which this was
true.


You would still have undefined behavior. A program producing undefined
behavior may produce exactly the behavior you expect, but it is still
undefined behavior.
Nov 13 '05 #82
On Tue, 11 Nov 2003 08:40:02 GMT, "Glen Herrmannsfeldt"
<ga*@ugcs.caltech.edu> wrote:

"Douglas A. Gwyn" <DA****@null.net> wrote in message
news:gd********************@comcast.com...
Glen Herrmannsfeldt wrote: <attribution uncertain>
What do you do on those unfortunate systems where pointers can address
memory much larger than size_t?

Well, that is a good question. Maybe 16 bit int is long past, and we
shouldn't worry about the problem. Though with 32 bit int and memories
larger than 4GB maybe we should. Consider a machine with 64 bit pointers,
but 32 bit int. You could still increment the pointer multiple times, less
than 2GB each time. Now, reasonably likely the machine would also have a
64 bit long or long long, but maybe doesn't supply the ability to increment
pointers (or subscript arrays) with them.
Then it's nonconforming. Pointer arithmetic is defined for any integer
type (in C99 including any implementation-defined 'extended' types)
not just 'int'. But only within one declared or allocated object,
whose size apparently can be bounded by size_t -- especially if, say,
the actual address space usable without thrashing is only say 10GB,
even though represented in a 64bit format, and address calculations
using >32bit offset are more costly, it might well be a reasonable
tradeoff to support only 4G-1B objects in that address space, and
*then* only subscripting/offseting by up to that. Or maybe even 2G-1B,
so ptrdiff_t can be 32bit signed.

<snip> Well, the argument of fseek() and the return from ftell() were long (or even
int?) many years before 4GB of memory was affordable, real or virtual. It
looks like a mistake now, and then we have things like fseek64() and
ftell64().

More to the point, before 4GB in a single disk; or really filesystem,
which then was at most one disk. Heck, 6ed Unix ran on a system with
5*M*B of disk (2 x RK05, and that's cartridge not the wuss -F).
- David.Thompson1 at worldnet.att.net
Nov 13 '05 #83
Dave Thompson wrote:
On Tue, 11 Nov 2003 08:40:02 GMT, "Glen Herrmannsfeldt"
(snip)
Well, that is a good question. Maybe 16 bit int is long past, and we
shouldn't worry about the problem. Though with 32 bit int and memories
larger than 4GB maybe we should. Consider a machine with 64 bit pointers,
but 32 bit int. You could still increment the pointer multiple times, less
than 2GB each time. Now, reasonably likely the machine would also have a
64 bit long or long long, but maybe doesn't supply the ability to increment
pointers (or subscript arrays) with them.

Then it's nonconforming. Pointer arithmetic is defined for any integer
type (in C99 including any implementation-defined 'extended' types)
not just 'int'. But only within one declared or allocated object,
whose size apparently can be bounded by size_t -- especially if, say,
the actual address space usable without thrashing is only say 10GB,
even though represented in a 64bit format, and address calculations
using >32bit offset are more costly, it might well be a reasonable
tradeoff to support only 4G-1B objects in that address space, and
*then* only subscripting/offseting by up to that. Or maybe even 2G-1B,
so ptrdiff_t can be 32bit signed.


Can an implementation have 64 bit pointers, but no integer type longer
than 32 bits?

How do you make a constant of type size_t?

-- glen

Nov 13 '05 #84
In <apkvb.201767$9E1.1076919@attbi_s52> glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
Can an implementation have 64 bit pointers, but no integer type longer
than 32 bits?
Yes, of course, as far as C89 is concerned. C99 requires long long to be
at least 64-bit.
How do you make a constant of type size_t?


You don't. But you can have a constant expression of type size_t and
constant expressions can be used instead of constants anywhere. E.g.
a C89 program can define SIZE_MAX as (size_t)-1.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #85
glen herrmannsfeldt wrote:
.... snip ...
Can an implementation have 64 bit pointers, but no integer type
longer than 32 bits?


Of course. You see it every day on your garden variety x86
machines. Every pointer involves a segment register value, all of
which just happen to be set the same, and thus effectively
ignored.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #86
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
How do you make a constant of type size_t?


(size_t) 100

--
Micah J. Cowan
mi***@cowan.name
Nov 13 '05 #87
In article <3F***************@yahoo.com>,
CBFalconer <cb********@worldnet.att.net> wrote:
Of course. You see it every day on your garden variety x86
machines. Every pointer involves a segment register value, all of
which just happen to be set the same, and thus effectively
ignored.


That's silly. You might as well say that all pointers include the
page table. The implementation of dereferencing pointers involves the
segment registers, but they are not part of the pointer. If they were,
you'd be able to alter a pointer to include a different segment
register - by abuse of pointers to pointers, or by using a debugger -
and you can't.

-- Richard
--
Spam filter: to mail me from a .com/.net site, put my surname in the headers.

FreeBSD rules!
Nov 13 '05 #88
Richard Tobin wrote:
CBFalconer <cb********@worldnet.att.net> wrote:
Of course. You see it every day on your garden variety x86
machines. Every pointer involves a segment register value, all of
which just happen to be set the same, and thus effectively
ignored.


That's silly. You might as well say that all pointers include the
page table. The implementation of dereferencing pointers involves the
segment registers, but they are not part of the pointer. If they were,
you'd be able to alter a pointer to include a different segment
register - by abuse of pointers to pointers, or by using a debugger -
and you can't.


Yes you can. Just use a debugger that can alter the segment
registers and operates at machine code level. Just before a
dereference alter the implied segment register for that
instruction.

For a safer simulation just use some compact model MSDOS code
under debug, and alter the segment registers. Just because people
have gone to great lengths to hide the unpleasant truths from you
doesn't mean they don't exist.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #89
In article <3F***************@yahoo.com>,
CBFalconer <cb********@worldnet.att.net> wrote:
Yes you can. Just use a debugger that can alter the segment
registers and operates at machine code level. Just before a
dereference alter the implied segment register for that
instruction.


And integers are all 33 bits. Just before an addition, alter the
carry flag.

-- Richard
--
Spam filter: to mail me from a .com/.net site, put my surname in the headers.

FreeBSD rules!
Nov 13 '05 #90
Micah Cowan wrote:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:

How do you make a constant of type size_t?

(size_t) 100


I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.

Maybe an S suffix for size_t constants?

-- glen

Nov 13 '05 #91
Richard Tobin wrote:
In article <3F***************@yahoo.com>,
CBFalconer <cb********@worldnet.att.net> wrote:
Of course. You see it every day on your garden variety x86
machines. Every pointer involves a segment register value, all of
which just happen to be set the same, and thus effectively
ignored.

That's silly. You might as well say that all pointers include the
page table. The implementation of dereferencing pointers involves the
segment registers, but they are not part of the pointer. If they were,
you'd be able to alter a pointer to include a different segment
register - by abuse of pointers to pointers, or by using a debugger -
and you can't.


Well, there are compilers that support 48 bit pointers, with a segment
selector and 32 bit offset. They are rare, though, and I don't think
support huge model where overflowing offset increments the selector.

With the AMD 64 bit processors things may change.

-- glen

Nov 13 '05 #92
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
Micah Cowan wrote:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
How do you make a constant of type size_t?

(size_t) 100


I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.


(size_t) 1000 * (size_t) 1000

Andreas.

--
Andreas Schwab, SuSE Labs, sc****@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Nov 13 '05 #93
In <VZhwb.219482$9E1.1201461@attbi_s52> glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.
It doesn't matter: the type of 1000000 or 3000000000 is automatically
chosen by the compiler to accomodate the value of the constant, if such
a type exists:

5 The type of an integer constant is the first of the corresponding
list in which its value can be represented.

|| |
|| | Octal or Hexadecimal
Suffix || Decimal Constant | Constant
-------------++-----------------------+------------------------
none ||int | int
||long int | unsigned int
||long long int | long int
|| | unsigned long int
|| | long long int
|| | unsigned long long int
-------------++-----------------------+------------------------
u or U ||unsigned int | unsigned int
||unsigned long int | unsigned long int
||unsigned long long int | unsigned long long int
-------------++-----------------------+------------------------
l or L ||long int | long int
||long long int | unsigned long int
|| | long long int
|| | unsigned long long int
-------------++-----------------------+------------------------
Both u or U ||unsigned long int | unsigned long int
and l or L ||unsigned long long int | unsigned long long int
-------------++-----------------------+------------------------
ll or LL ||long long int | long long int
|| | unsigned long long int
-------------++-----------------------+------------------------
Both u or U ||unsigned long long int | unsigned long long int
and ll or LL || |

If an integer constant cannot be represented by any type in
its list, it may have an extended integer type, if the extended
integer type can represent its value. If all of the types in the
list for the constant are signed, the extended integer type shall
be signed. If all of the types in the list for the constant are
unsigned, the extended integer type shall be unsigned. If the
list contains both signed and unsigned types, the extended
integer type may be signed or unsigned.

This effectively guarantees that, if 3000000000000000000000000 is
a supported value for the type size_t, (size_t) 3000000000000000000000000
will give you the right thing, even if there is no standard integer type
that can represent 3000000000000000000000000 (size_t will be an alias for
an extended integer type, in this case).
Maybe an S suffix for size_t constants?


What problem would such a suffix solve that a cast to size_t wouldn't?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #94
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
glen herrmannsfeldt wrote:

... snip ...

Can an implementation have 64 bit pointers, but no integer type
longer than 32 bits?


Of course. You see it every day on your garden variety x86
machines. Every pointer involves a segment register value, all of
which just happen to be set the same, and thus effectively
ignored.


In which case, they are not part of the pointer value, as far as any
correct C program is concerned.

It's the same with the tiny and small memory models of the 8086: they
had 16-bit pointers, although the processor used 20-bit addresses.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #95
In <je************@sykes.suse.de> Andreas Schwab <sc****@suse.de> writes:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
Micah Cowan wrote:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:

How do you make a constant of type size_t?
(size_t) 100


I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.


(size_t) 1000 * (size_t) 1000


Name ONE scenario where (size_t) 1000 * (size_t) 1000 works better than
(size_t) 1000000.

Here's one scenarion where (size_t) 1000 * (size_t) 1000 invokes undefined
behaviour, but (size_t) 1000000 doesn't:

#typedef unsigned short size_t
#define USHRT_MAX 65535
#define INT_MAX 131071

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #96
glen herrmannsfeldt wrote:
Micah Cowan wrote:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:
How do you make a constant of type size_t?


(size_t) 100


I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.


I believe size_t is specified to be an integral type, and the
largest integral type is long (in C90) or long long (in C99).

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #97
CBFalconer wrote:

glen herrmannsfeldt wrote:
Micah Cowan wrote:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:

>How do you make a constant of type size_t?

(size_t) 100


I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.


I believe size_t is specified to be an integral type, and the
largest integral type is long (in C90) or long long (in C99).


More precisely, size_t is specified as being an unsigned integral type.
The largest unsigned integral type is indeed 'unsigned long' in C90, but
it is 'uintmax_t' in C99, which might be larger than 'unsigned long
long'. The only requirements on size_t are UCHAR_MAX<=SIZE_MAX &&
SIZE_MAX<=UINTMAX_MAX.
Nov 13 '05 #98
CBFalconer wrote:

glen herrmannsfeldt wrote:
Micah Cowan wrote:
glen herrmannsfeldt <ga*@ugcs.caltech.edu> writes:

>How do you make a constant of type size_t?

(size_t) 100


I was thinking about (size_t) 1000000 or maybe (size_t) 3000000000

but you don't know if INT_MAX or even LONG_MAX is big enough.


I believe size_t is specified to be an integral type, and the
largest integral type is long (in C90) or long long (in C99).


size_t is integral, and unsigned as well.

C90 defines nine integer types (plain char plus signed
and unsigned versions of char, short, int, and long). The
list is complete; no implementation-provided extra type is
considered an "integer." Thus, size_t is a synonym for one
of the four or five unsigned types.

C99 adds long long, raising the census of standard
integer types to eleven and the number of standard size_t
candidate types to five or six. But C99 also introduces
optional "extended" integer types, and as far as I can
tell it is permissible for size_t to be an extended type.
In C99, `unsigned long long' might not be wide enough for
all size_t values. `uintmax_t' will work, of course.

--
Er*********@sun.com
Nov 13 '05 #99
CBFalconer wrote:
I believe size_t is specified to be an integral type, and the
largest integral type is long (in C90) or long long (in C99).


Those are the widest *standard* integer types.
An implementation can also support extended integer types,
and as of C99 we officially permit them to be used for size_t etc.
Nov 13 '05 #100

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Niels Dekker (no reply address) | last post by:
Is it possible for a standard compliant C++ compiler to have ( sizeof(short) < sizeof(int) ) and ( sizeof(short) == sizeof((short)0 + (short)0) ) ? Regards, Niels Dekker...
34
by: Andy | last post by:
Hi, Are 1 through 4 defined behaviors in C? unsigned short i; unsigned long li; /* 32-bit wide */ 1. i = 65535 + 3; 2. i = 1 - 3; 3. li = (unsigned long)0xFFFFFFFF + 3; 4. li = 1...
8
by: NilsNilsson | last post by:
I wrote this: short s1 = 0; short s2 = 1; short s3 = s1 + s2; And gor this compile error message: Cannot implicitly convert type 'int' to 'short' What is wrong here?
8
by: Ken Dopierala Jr. | last post by:
Hi, I'm reading the header file of a PCX image and I need to convert 2 bytes to a short. How would I go about doing this? I know that they are bytes 8 & 9 in my byte array. I'm not sure how to...
15
by: Steffen Loringer | last post by:
Hi, I'm using the following function to join 2 char (byte) into one short on a 32 bit X86 platform: unsigned short joinUnsigShort(unsigned char a,unsigned char b) { unsigned short val = 0;...
4
by: slougheed | last post by:
I encountered a problem after we had converted our declarations of 'unsigned short int' to uint16_t. In one instance, whoever did the conversion failed to delete the 'short' keyword so we had a...
10
by: Jim Langston | last post by:
Is the following well defined? size_t IntVal = 65537; unsigned short Length; if ( IntVal static_cast<unsigned short>( -1 ) ) { std::cout << "Value too long to fit in a short" << std::endl;...
10
by: nyhetsgrupper | last post by:
The following code result in the following compilation error: Error 1 Cannot implicitly convert type 'int' to 'short'. An explicit conversion exists (are you missing a cast?) short a = 1; short...
3
by: mathieu | last post by:
Could someone please tell me what is wrong with the following -ugly- piece of c++ code. Why when I explicititely set the template parameter my gcc compiler start getting confused: bla.cxx: In...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.