How do I get DOUBLE_MAX? - c

AFAIK, C supports just a few data types:
int, float, double, char, void enum.
I need to store a number that could reach into the high 10 digits. Since I'm getting a low 10 digit # from
INT_MAX
, I suppose I need a double.
<limits.h> doesn't have a DOUBLE_MAX. I found a DBL_MAX on the internet that said this is LEGACY and also appears to be C++. Is double what I need? Why is there no DOUBLE_MAX?

DBL_MAX is defined in <float.h>. Its availability in <limits.h> on unix is what is marked as "(LEGACY)".
(linking to the unix standard even though you have no unix tag since that's probably where you found the "LEGACY" notation, but much of what is shown there for float.h is also in the C standard back to C89)

You get the integer limits in <limits.h> or <climits>. Floating point characteristics are defined in <float.h> for C. In C++, the preferred version is usually std::numeric_limits<double>::max() (for which you #include <limits>).
As to your original question, if you want a larger integer type than long, you should probably consider long long. This isn't officially included in C++98 or C++03, but is part of C99 and C++11, so all reasonably current compilers support it.

Its in the standard float.h include file. You want DBL_MAX

Using double to store large integers is dubious; the largest integer that can be stored reliably in double is much smaller than DBL_MAX. You should use long long, and if that's not enough, you need your own arbitrary-precision code or an existing library.

You are looking for the float.h header.

INT_MAX is just a definition in limits.h. You don't make it clear whether you need to store an integer or floating point value. If integer, and using a 64-bit compiler, use a LONG (LLONG for 32-bit).

Related

Difference between INT_MAX and __INT_MAX__ in C

What is the difference between the 2? __INT_MAX__ is defined without adding a library as far as I know and INT_MAX is defined in limits.h but when I include the library INT_MAX gets expanded to __INT_MAX__ either way (or so does VSCode say). Why would I ever use the limits.h one when it gets expanded to the other one?
You should always use INT_MAX, as that is the macro constant that is defined by the ISO C standard.
The macro constant __INT_MAX__ is not specified by ISO C, so it should not be used, if you want your code to be portable. That macro is simply an implementation detail of the compiler that you are using. Other compilers will probably not define that macro, and will implement INT_MAX in some other way.
__INT_MAX__ is an implementation defined macro, which means not all systems may have it. In particular, GCC defines this macro but MSVC does not.
On the other hand, INT_MAX is defined by the C standard and is guaranteed to be present in limits.h for any conforming compiler.
So for portability, use INT_MAX.
Why would I ever use the limits.h one when it gets expanded to the other one?
limits.h is standard and portable.
Every implementation of the C language is free to create the value of macros such as INT_MAX as it sees fit. The __INT_MAX__ value you are seeing is an artifact of your particular compiler, and maybe even the particular version of the compiler you're using.
To add to the other answers, when you're writing code that will be run on several platforms, it really pays to stick to the standards. If you don't, when a new platform comes along, you have a lot of work to do adapting it, and the best way to do that is usually to change it conform to the standard. This work is very dull and uninteresting, and well worth avoiding by doing things right to start with.
I work on a mathematical modeller that was originally written in the 1980s on VAX/VMS, and in its early days supported several 68000 platforms, including Apollo/Domain. Nowadays, it runs on 64-bit Windows, Linux, macOS, Android and iOS, none of which existed when it was created.
__INT_MAX__ is a predefined macro in the C preprocessor that specifies the maximum value of an int type on a particular platform. This value is implementation-defined and may vary across different platforms.
INT_MAX is a constant defined in the limits.h header file that specifies the maximum value of an int type. It is defined as follows:
define INT_MAX __INT_MAX__
The limits.h header file is part of the C standard library and provides various constants that specify the limits of various types, such as the minimum and maximum values of the int, long, and long long types.
The reason why INT_MAX is defined as __INT_MAX__ is because __INT_MAX__ is a predefined macro that specifies the maximum value of an int type on a particular platform, and INT_MAX is simply an alias for this value.
You can use either __INT_MAX__ or INT_MAX to get the maximum value of an int type, but it is generally recommended to use INT_MAX since it is defined in a standard library header file and is therefore more portable.
INT_MAX is a macro that specifies that an integer variable cannot store any value beyond this limit.
INT_MIN specifies that an integer variable cannot store any value below this limit.
Values of INT_MAX and INT_MIN may vary
from compiler to compiler. Following are
typical values in a compiler where integers
are stored using 32 bits.
Value of INT_MAX is +2147483647.
Value of INT_MIN is -2147483648.
In the C programming language, INT_MAX is a macro that expands to the maximum value that can be stored in a variable of type int. This value is implementation-defined, meaning that it may vary depending on the specific C implementation being used. On most systems, int is a 32-bit data type and INT_MAX is defined as 2147483647, which is the maximum value that can be stored in a 32-bit, two's complement integer.
On the other hand, __INT_MAX__ is a predefined macro that represents the maximum value that can be stored in a variable of type int on the system where the C program is being compiled. Like INT_MAX, the value of __INT_MAX__ is implementation-defined and may vary depending on the specific C implementation being used. However, __INT_MAX__ is set by the compiler during compilation, whereas INT_MAX is typically defined in a header file (e.g., limits.h) and included in the program at runtime.
In general, it is recommended to use INT_MAX rather than __INT_MAX__ in C programs, as INT_MAX is portable and will work on any system, whereas __INT_MAX__ is specific to the system where the program is being compiled.
INT_MAX (macro) : It specifies that any integer variable cannot store values beyond the mentioned limit.
whereas
INT_MIN specifies that any integer variable cannot store some value that is below the mentioned limit.

Is there a gcc function to add two large numbers for C?

I am trying to add two numbers in C. My code is
#define type unsigned
type add(type a, type b) {
return a + b;
}
Code corresponding to above code in assembly makes use of a single add instruction (https://godbolt.org/ & ARM GCC 8.3.1). However when I changed the type to unsigned long long, code was bit obfuscated to understand; But, I believe it makes use of some ldm and then asks hardware to add complete vectors (or arrays). Similarly my next question was: is it possible to add two numbers where digits count in each number will be in the order of 1000s? It isn't hard to design a function and make it work, and I found many codes on internet which do this. But, I think compiler writes better code than us,
so are there any gcc built-in functions which can do this job?
In fact, does gcc provide such functions for all the 5 integer arithmetic operations?
No, there is no compiler support in GCC for arbitrary-precision arithmetic. You would need to use a library like GMP. If you can use C++ instead of C, you can get a more "natural" API (with arithmetic operators, etc.) by using a library like Boost Multiprecision.
GCC does support, as an extension, the types __int128 and unsigned __int128, which can be used like any other integral type, but these only provide capacity for 38 decimal digits.
Edit: Also, as an aside, don't use macros (like #define type unsigned) to rename types. Instead this should be written with the typedef keyword like so: typedef unsigned type;

Are there any well-established/standardized ways to use fixed-width integers in C89?

Some background:
the header stdint.h is part of the C standard since C99. It includes typedefs that are ensured to be 8, 16, 32, and 64-bit long integers, both signed and unsigned. This header is not part of the C89 standard, though, and I haven't yet found any straightforward way to ensure that my datatypes have a known length.
Getting to the actual topic
The following code is how SQLite (written in C89) defines 64-bit integers, but I don't find it convincing. That is, I don't think it's going to work everywhere. Worst of all, it could fail silently:
/*
** CAPI3REF: 64-Bit Integer Types
** KEYWORDS: sqlite_int64 sqlite_uint64
**
** Because there is no cross-platform way to specify 64-bit integer types
** SQLite includes typedefs for 64-bit signed and unsigned integers.
*/
#ifdef SQLITE_INT64_TYPE
typedef SQLITE_INT64_TYPE sqlite_int64;
typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
#elif defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 sqlite_int64;
typedef unsigned __int64 sqlite_uint64;
#else
typedef long long int sqlite_int64;
typedef unsigned long long int sqlite_uint64;
#endif
typedef sqlite_int64 sqlite3_int64;
typedef sqlite_uint64 sqlite3_uint64;
So, this is what I've been doing so far:
Checking that the "char" data type is 8 bits long, since it's not guaranteed to be. If the preprocessor variable "CHAR_BIT" is not equal to 8, compilation fails
Now that "char" is guaranteed to be 8 bits long, I create a struct containing an array of several unsigned chars, which correspond to several bytes in the integer.
I write "operator" functions for my datatypes. Addition, multiplication, division, modulo, conversion from/to string, etc.
I have abstracted this process in a header file, which is the best I can do with what I know, but I wonder if there is a more straightforward way to achieve this.
I'm asking because I want to write a portable C library.
First, you should ask yourself whether you really need to support implementations that don't provide <stdint.h>. It was standardized in 1999, and even many pre-C99 implementations are likely to provide it as an extension.
Assuming you really need this, Doug Gwyn, a member of the ISO C standard committee, created an implementation of several of the new headers for C9x (as C99 was then known), compatible with C89/C90. The headers are in the public domain and should be reasonably portable.
http://www.lysator.liu.se/(nobg)/c/q8/index.html
(As I understand it, the name "q8" has no particular meaning; he just chose it as a reasonably short and unique search term.)
One rather nasty quirk of integer types in C stems from the fact that many "modern" implementations will have, for at least one size of integer, two incompatible signed types of that size with the same bit representation and likewise two incompatible unsigned types. Most typically the types will be 32-bit "int" and "long", or 64-bit "long" and "long long". The "fixed-sized" types will typically alias to one of the standard types, though implementations are not consistent about which one.
Although compilers used to assume that accesses to one type of a given size might affect objects of the other, the authors of the Standard didn't mandate that they do so (probably because there would have been no point ordering people to do things they would do anyway and they couldn't imagine any sane compiler writer doing otherwise; once compilers started doing so, it was politically difficult to revoke that "permission"). Consequently, if one has a library which stores data in a 32-bit "int" and another which reads data from a 32-bit "long", the only way to be assured of correct behavior is to either disable aliasing analysis altogether (probably the sanest choice while using gcc) or else add gratuitous copy operations (being careful that gcc doesn't optimize them out and then use their absence as an excuse to break code--something it sometimes does as of 6.2).

SELECTED_REAL_KIND in C

Is there any equivalent of SELECTED_REAL_KIND (in Fortran) in C language ?
SELECTED_REAL_KIND is a standard Fortran mechanism for choosing at build time a real data type that meets or exceeds specified parameters for numeric representation. In particular, it is used to select a data type by precision and / or exponent range and / or radix.
Standard C does not have a built-in parameterized facility such as that for designating data types. It does have standard macros whose values describe the properties of the implementations of the standard floating-point types, float, double, and long double. Their joint radix, their precisions in both decimal digits and implementation-radix digits, and their minimum and maximum exponent values (also in both decimal and implementation-radix forms) are all available via these macros. These are defined in the standard header float.h. (The link is to POSIX, which is formally aligned with the C standard here.)
It is possible to use the C preprocessor conditionals and these macros to define macros or typedefs for types that meet your specific requirements, which you can then use throughout your code. This is not as tidy as Fortran's approach, but it gets the job done.

How to Declare a 32-bit Integer in C

What's the best way to declare an integer type which is always 4 byte on any platforms? I don't worry about certain device or old machines which has 16-bit int.
#include <stdint.h>
int32_t my_32bit_int;
C doesn't concern itself very much with exact sizes of integer types, C99 introduces the header stdint.h , which is probably your best bet. Include that and you can use e.g. int32_t. Of course not all platforms might support that.
Corey's answer is correct for "best", in my opinion, but a simple "int" will also work in practice (given that you're ignoring systems with 16-bit int). At this point, so much code depends on int being 32-bit that system vendors aren't going to change it.
(See also why long is 32-bit on lots of 64-bit systems and why we have "long long".)
One of the benefits of using int32_t, though, is that you're not perpetuating this problem!
You could hunt down a copy of Brian Gladman's brg_types.h if you don't have stdint.h.
brg_types.h will discover the sizes of the various integers on your platform and will create typedefs for the common sizes: 8, 16, 32 and 64 bits.
You need to include inttypes.h instead of stdint.h because stdint.h is not available on some platforms such as Solaris, and inttypes.h will include stdint.h for you on systems such as Linux.
If you include inttypes.h then your code is more portable between Linux and Solaris.
This link explains what I'm saying:
HP link about inttypes.h
And this link has a table showing why you don't want to use long or int if you have an intention of a certain number of bits being present in your data type.
IBM link about portable data types
C99 or later
Use <stdint.h>.
If your implementation supports 2's complement 32-bit integers then it must define int32_t.
If not then the next best thing is int_least32_t which is an integer type supported by the implementation that is at least 32 bits, regardless of representation (two's complement, one's complement, etc.).
There is also int_fast32_t which is an integer type at least 32-bits wide, chosen with the intention of allowing the fastest operations for that size requirement.
ANSI C
You can use long, which is guaranteed to be at least 32-bits wide as a result of the minimum range requirements specified by the standard.
If you would rather use the smallest integer type to fit a 32-bit number, then you can use preprocessor statements like the following with the macros defined in <limits.h>:
#define TARGET_MAX 2147483647L
#if SCHAR_MAX >= TARGET_MAX
typedef signed char int32;
#elif SHORT_MAX >= TARGET_MAX
typedef short int32;
#elif INT_MAX >= TARGET_MAX
typedef int int32;
#else
typedef long int32;
#endif
#undef TARGET_MAX
If stdint.h is not available for your system, make your own. I always have a file called "types.h" that have typedefs for all the signed/unsigned 8, 16, and 32 bit values.
You can declare 32 bits with signed or unsigned long.
int32_t variable_name;
uint32_t variable_name;
also depending on your target platforms you can use autotools for your build system
it will see if stdint.h/inttypes.h exist and if they don't will create appropriate typedefs in a "config.h"
stdint.h is the obvious choice, but it's not necessarily available.
If you're using a portable library, it's possible that it already provides portable fixed-width integers.
For example, SDL has Sint32 (S is for “signed”), and GLib has gint32.

Resources