Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Generates integer literal of the largest value a variable can hold.Macro takes only variable-name. (http://www.velocityreviews.com/forums/t945662-generates-integer-literal-of-the-largest-value-a-variable-can-hold-macro-takes-only-variable-name.html)

John Reye 04-23-2012 07:38 PM

Generates integer literal of the largest value a variable can hold.Macro takes only variable-name.
 
Assume you have a variable called
var
of unknown type. (Or that the type can be changed).

How can one construct a literal, to be the largest value that this
variable can hold, without information about the variables type?





#include <stdio.h>
#define MAX_VALUE_OF_VAR(var) (how should this macro look like, please
use helper macros if necessary)

int main()
{
signed char var = 0; // only change this line (to other types)
do {
++var;
printf("%lld, ", (long long int) var);
} while (var != MAX_VALUE_OF_VAR(var));
return 0;
}

In the above, I currently expect the output to be 1, 2, 3, ..., 127

If above is changed:
signed short var = 0;
.... then I would like the output to be
1, 2, 3, ..., 32767

If above is changed:
signed int var = 0;
.... and recompile, then I would like the output to be
1, 2, 3, ..., 2147483647

etc.


Is it possible to construct a macro MAX_VALUE_OF_VAR that handles both
signed and unsigned?
I've tried and am having a lot of trouble with integer promotions and
the MSB for negative numbers.

Is this possible at all.
Thanks for pointers.

Thomas Richter 04-23-2012 08:08 PM

Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.
 
On 23.04.2012 21:38, John Reye wrote:
> Assume you have a variable called
> var
> of unknown type. (Or that the type can be changed).
>
> How can one construct a literal, to be the largest value that this
> variable can hold, without information about the variables type?


Not in C in a completely portable way. If you are contained to standard
architectures with binary representation of data, you could check

a) whether the 1/2 in this variable equals zero or not. If not, it not
an integer type, otherwise, HUGE_VAL should be the largest possible value,
b) if (-1) casted to the type is positive, it is unsigned, and the
result is the largest possible value,
c) otherwise, on *many standard* systems, you may try to use 1 <<
((sizeof(type) << 3)-1) for signed types.

But as said, this is not portable. In C++, type traits would offer the
full functionality you need, and even without using the preprocessor.

So long,
Thomas


John Reye 04-23-2012 08:28 PM

Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.
 
Ahh that C's right?

Sortof slightly "statically typed".
Then then they throw in integer promotions to ease writing code in
some cases, but causes novice programmer's bugs and kills the type-
system in other cases.

Writing portable C-code that works across different word-sizes must be
a real horror!

Ben Pfaff 04-23-2012 08:36 PM

Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.
 
John Reye <jononanon@googlemail.com> writes:

> Assume you have a variable called
> var
> of unknown type. (Or that the type can be changed).
>
> How can one construct a literal, to be the largest value that this
> variable can hold, without information about the variables type?


The following works for integer types on "ordinary" sytems.

/*
* Copyright (c) 2008, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef TYPE_PROPS_H
#define TYPE_PROPS_H 1

#include <limits.h>

#define TYPE_IS_INTEGER(TYPE) ((TYPE) 1.5 == (TYPE) 1)
#define TYPE_IS_SIGNED(TYPE) ((TYPE) 1 > (TYPE) -1)
#define TYPE_VALUE_BITS(TYPE) (sizeof(TYPE) * CHAR_BIT - TYPE_IS_SIGNED(TYPE))
#define TYPE_MINIMUM(TYPE) (TYPE_IS_SIGNED(TYPE) \
? ~(TYPE)0 << TYPE_VALUE_BITS(TYPE) \
: 0)
#define TYPE_MAXIMUM(TYPE) (TYPE_IS_SIGNED(TYPE) \
? ~(~(TYPE)0 << TYPE_VALUE_BITS(TYPE)) \
: (TYPE)-1)

/* Number of decimal digits required to format an integer of the given TYPE.
* Includes space for a sign, if TYPE is signed, but not for a null
* terminator.
*
* The value is an overestimate. */
#define INT_STRLEN(TYPE) (TYPE_IS_SIGNED(TYPE) + TYPE_VALUE_BITS(TYPE) / 3 + 1)

#endif /* type-props.h */

James Kuyper 04-23-2012 08:45 PM

Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.
 
On 04/23/2012 04:08 PM, Thomas Richter wrote:
> On 23.04.2012 21:38, John Reye wrote:
>> Assume you have a variable called
>> var
>> of unknown type. (Or that the type can be changed).
>>
>> How can one construct a literal, to be the largest value that this
>> variable can hold, without information about the variables type?

>
> Not in C in a completely portable way. If you are contained to standard
> architectures with binary representation of data, you could check


The error density in the next sentence is truly amazing. Some people
consider sentences like this one to be the sign of a troll. I'll
withhold judgement for now on that issue.

> a) whether the 1/2 in this variable equals zero or not. ...


Setting any arithmetic type to 1/2 should produce a result of 0 for all
arithmetic types. I think you mean 0.5.

> ... If not, it not
> an integer type, ...


This is both simpler and has better grammar: "if so, it is an integer
type". This would also fix the error in the rest of the sentence:

> ... otherwise, HUGE_VAL should be the largest possible value,


I think you got confused by having two many "not"s. As written, assuming
that you meant 0.5 rather than 1/2, and were thinking of 'double' as the
only floating point type, that's exactly backwards.

But that still doesn't work; HUGE_VAL is for doubles, HUGE_VALF and
HUGE_VALL are for float and long double, respectively. If you knew which
one of those three options was relevant, that would violate one of the
specified conditions: no information about the type.

The HUGE_VAL* macros are special positive values used by the standard
library for indicating error conditions; their values are otherwise not
constrained. It's entirely possible for HUGE_VAL to be 1 (though that
would be a very bad idea).

> b) if (-1) casted to the type is positive, it is unsigned, and the
> result is the largest possible value,


Again, if he knew the type to cast it to, that would violate the
specified condition: "no information about the type".

> c) otherwise, on *many standard* systems, you may try to use 1 <<
> ((sizeof(type) << 3)-1) for signed types.


Why use "<<3" rather than "*CHAR_BIT"? It's not portable, but it's more
portable than "<<3".
You're missing the final -1 in your expression.

James Kuyper 04-23-2012 09:01 PM

Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.
 
On 04/23/2012 04:28 PM, John Reye wrote:
> Ahh that C's right?
>
> Sortof slightly "statically typed".
> Then then they throw in integer promotions to ease writing code in
> some cases, but causes novice programmer's bugs and kills the type-
> system in other cases.
>
> Writing portable C-code that works across different word-sizes must be
> a real horror!


Not really. If you need exact or minimum sizes, using the size-named
types from <stdint.h>. If you need C90 capability (or just want to use
shorter type names), think of [un]signed char as essentially the same as
[u]int_least8_t, [unsigned] short as [u]int_least16_t, [unsigned] int as
[u]int_fast16_t, and [unsigned] long as [u]int_least32_t. Except, of
course, that they're not required to have 2's complement type, and
(except for unsigned char) are allowed to have padding bits.

I won't claim it's trivial to deal with all of these issues, but it's
not a horror. Careful use of the corresponding MIN and MAX macros from
<stdint.h> or <limits.h> respectively, will deal with most of the
relevant problems.

If you want a language that guarantees more about it's fundamental types
than C does, try Java; but keep in mind the efficiency penalties of
using a type guaranteed to be exactly 16 bits on a 32-bit machine (or
vice versa). If that inefficiency doesn't bother you, and the
corresponding uncertainty about whether 'int' has 16 or 32 bytes does,
then C is definitely NOT the language for you.

James Kuyper 04-23-2012 09:11 PM

Re: Generates integer literal of the largest value a variable canhold. Macro takes only variable-name.
 
On 04/23/2012 03:38 PM, John Reye wrote:
> Assume you have a variable called
> var
> of unknown type. (Or that the type can be changed).
>
> How can one construct a literal, to be the largest value that this
> variable can hold, without information about the variables type?
>
> #include <stdio.h>
> #define MAX_VALUE_OF_VAR(var) (how should this macro look like, please
> use helper macros if necessary)
>
> int main()
> {
> signed char var = 0; // only change this line (to other types)
> do {
> ++var;
> printf("%lld, ", (long long int) var);
> } while (var != MAX_VALUE_OF_VAR(var));
> return 0;
> }
>
> In the above, I currently expect the output to be 1, 2, 3, ..., 127
>
> If above is changed:
> signed short var = 0;
> ... then I would like the output to be
> 1, 2, 3, ..., 32767
>
> If above is changed:
> signed int var = 0;
> ... and recompile, then I would like the output to be
> 1, 2, 3, ..., 2147483647


Do you have enough time to read that output? Do you have enough paper
an toner to print it out?

> Is it possible to construct a macro MAX_VALUE_OF_VAR that handles both
> signed and unsigned?
> I've tried and am having a lot of trouble with integer promotions and
> the MSB for negative numbers.
>
> Is this possible at all.


Not in general.

For unsigned types, assigning a value of -1 to the variable will set it
to the maximum value of it's type. Would it be acceptable for the macro
to change the variable's value? It wouldn't work in your example code -
would your intended use for this macro allow a re-write to avoid that
problem? Assigning a value of -1 to a variable is a perfectly safe thing
to do for all arithmetic types, and testing whether the result is
greater than 0 is a safe and reliable way of testing for unsignedness.

If you're willing to make non-portable but very often correct
assumptions, like 2's complement and no padding bits or trap
representations, then

((long long)pow(2.0,CHAR_BIT*sizeof(var) - 1)-1)

works for the signed types. If you need portability to systems where
those assumptions don't apply, you're out of luck.

The "no type information" approach seems rather odd - it's not something
that comes up very often in idiomatically written C - you almost always
know the type of anything you work with, except when using typedefs. It
sound almost as if you were trying to write a C++ template in C. You
need to approach problems differently when using C than when using C++.
If you try to force C to work like C++, you're going to frustrate
yourself and mystify those who work on your code later, trying to
implement poor substitutes for genericity in C.

Stefan Ram 04-23-2012 09:53 PM

Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.
 
John Reye <jononanon@googlemail.com> writes:
>How can one construct a literal, to be the largest value that this
>variable can hold, without information about the variables type?


The largest value a single bit can hold is not limited.
It just depends on the code used. For example, I can use this code:

bit
state meaning
0 the number 0
1 the number 100^100^100^100^100^100^100^100^100^100^100^100^10 0^100

For large numbers, see:

http://www.scottaaronson.com/writings/bignumbers.html
http://mathoverflow.net/questions/34...us-busy-beaver
http://jeremykun.wordpress.com/2012/...r-big-numbers/
http://en.wikipedia.org/wiki/Busy_beaver
http://www.strangehorizons.com/2001/..._numbers.shtml
http://mrob.com/pub/math/largenum-5.html

. With C, one can use the literal »1«:

{ number c;
init( &c, 1 );
print( c ); }

will print

100^100^100^100^100^100^100^100^100^100^100^100^10 0^100

, given an appropriate definition for »number«, »init«, and »print«
(exercise).


John Gordon 04-23-2012 10:03 PM

Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.
 
In <number-20120423234415@ram.dialup.fu-berlin.de> ram@zedat.fu-berlin.de (Stefan Ram) writes:

> The largest value a single bit can hold is not limited.


That's stretching the meaning of the word "hold", isn't it?

--
John Gordon A is for Amy, who fell down the stairs
gordon@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"


Stefan Ram 04-24-2012 02:11 AM

Re: Generates integer literal of the largest value a variable can hold. Macro takes only variable-name.
 
John Gordon <gordon@panix.com> writes:
>In <number-20120423234415@ram.dialup.fu-berlin.de> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>The largest value a single bit can hold is not limited.

>That's stretching the meaning of the word "hold", isn't it?


What's the largest number a double can hold in your preferred C implementation?

What's the second largest number it can hold (the next representable number smaller
than the first)?

In which sense does a double object »hold« these two values that does not apply
to the bit I described?



All times are GMT. The time now is 04:14 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.