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
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
"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
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).
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
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
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.
"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.
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
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.
"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
"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 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) 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) 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)
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 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.
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
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
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 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.
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
"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
"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
"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
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.
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.
"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
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
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
"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.
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.
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
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
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
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!
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
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!
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!
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!
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
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
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."
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
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
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
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!
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.
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
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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?
|
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...
|
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;...
|
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...
|
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;...
|
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...
|
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...
|
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,...
|
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$) {
}
...
|
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...
|
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...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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...
|
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,...
|
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...
| |