473,882 Members | 1,646 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 9133

"Mark Gordon" <sp******@fla sh-gordon.me.uk> wrote in message
news:2003110713 3110.453220b5.s p******@flash-gordon.me.uk...
On Thu, 06 Nov 2003 20:59:08 GMT
"Glen Herrmannsfeldt" <ga*@ugcs.calte ch.edu> wrote:
"Dan Pop" <Da*****@cern.c h> wrote in message
news:bo******** **@sunnews.cern .ch...
In <99aqb.82956$27 5.242639@attbi_ s53> "Glen Herrmannsfeldt" <ga*@ugcs.calte ch.edu> writes:
>"Dan Pop" <Da*****@cern.c h> wrote in message
>news:bo******* ****@sunnews.ce rn.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(a p,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.c h> wrote in message
news:bo******** **@sunnews.cern .ch...
In <8b************ *************@p osting.google.c om> ku****@wizard.n et (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.e du)
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.e du)
Nov 13 '05 #64
ch***********@c bau.freeserve.c o.uk (Christian Bau) wrote on 02.11.03 in <ch************ *************** ******@slb-newsm1.svr.pol. co.uk>:
In article <aE0pb.81932$HS 4.680953@attbi_ s01>,
"Glen Herrmannsfeldt" <ga*@ugcs.calte ch.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.e du)
Nov 13 '05 #65
In <3F************ ***@null.net> "Douglas A. Gwyn" <DA****@null.ne t> 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.ne t> 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.a u> | "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$9 E1.493592@attbi _s52> "Glen Herrmannsfeldt" <ga*@ugcs.calte ch.edu> writes:

"Dan Pop" <Da*****@cern.c h> wrote in message
news:bo******* ***@sunnews.cer n.ch...
In <8b************ *************@p osting.google.c om> ku****@wizard.n et(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********@new s.unimelb.edu.a u> Fergus Henderson <fj*@cs.mu.oz.a u> 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**********@s unnews.cern.ch> Da*****@cern.ch (Dan Pop) writes:
In <3f********@new s.unimelb.edu.a u> Fergus Henderson <fj*@cs.mu.oz.a u> 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

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

Similar topics

10
2282
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 http://www.xs4all.nl/~nd/dekkerware
34
16711
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 - 3;
8
1701
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
16420
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 take those two and convert them into a short though. In C I would just use a union and assign them accordingly. Thanks! Ken.
15
8449
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; val = a; val <<= 8;
4
5224
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 'uint16_t short'. The compiler (GNU 3.3.5) allows this but ignores the original unsigned keyword and initialzes the variable as a signed short int. I created a very simple test program just to see what was happening: #include <stdio.h> ...
10
5661
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; } else
10
5459
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 b = 2; short result = a + b; Can anyone explain why??
3
6413
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 function 'int main()': bla.cxx:25: error: call of overloaded 'foo(short unsigned int*&)' is ambiguous bla.cxx:2: note: candidates are: void foo(OutputType*) bla.cxx:10: note: void foo(PixelType*)
0
9931
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
11108
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10725
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
10403
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9557
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7956
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7113
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5978
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
4198
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.