I want to use a u_int64_t variable as search key.
Is u_int64_t available on 32-bit machine?
If not, do I have to divide this variable into two variables? Then as a search key, it is a bit more troublesome.
Are there any workarounds for this?
An unsigned 64-bit integral type is not guaranteed by the C standard, but is typically available on 32-bit machines, and on virtually all machines running Linux. When present, the type will be named uint64_t (note one less underscore) and declared in the <stdint.h> header file.
Yes 64 bit integer datatype is supported on a 32 bit machine.
In C89 Standard , long long (≥ 64, ≥ size of long) type is supported as a GNU extension.
In C99 standard, there is native support for long long(≥ 64, ≥ size of long) integer.
as per some of the documentation or reading its not quite clear
__GLIBC_HAVE_LONG_LONG is the one that defines its presense in 32 bit architecture
aprobable solution for usage could be something similar to below
#include <sys/types.h>
#ifdef __GLIBC_HAVE_LONG_LONG
u_int64_t i;
#endif
Oh bythe way this is in linux
Related
Since C is a loosely typed language and stdint.h defines just typedefs (I assume), how can the widths of ints be guaranteed?
What I am asking is about the implementation rather than the library usage.
How can <stdint.h> types guarantee bit width?
C can't and C does not require it.
C does require minimum widths.
The below, individuality, are required only on systems that support them, without padding and 2's complement for sign types.
(u)int8_t, (u)int16_t, (u)int32_t, (u)int64_t
An implementation may optionally have other sizes like uint24_t
Below are required.
(u)int_least8_t, (u)int_least16_t, (u)int_least32_t, (u)int_least64_t
stdint.h is part of the C implementation, which defines the typedefs using whatever underlying types are appropriate for that implementation. It's not a portable file you can carry to any C implementation you like.
A C compiler eventually needs to compile to machine code. Machine code only has hard, fixed-width types like a 32-bit int, 64-bit int etc. (or rather, it has memory blocks of that size + operations that operate on memory of that size and either treat it as signed or unsigned)
So the people who create your compiler are the ones who define what your compiler actually uses under the hood when you ask it for an int, and the stdint.h header file is a file they write. It is basically documentation of what they did. They know that e.g. their long type is 64 bits in size, so add a typedef long int64_t; etc.
On a system where int is 16 bits and long is 32 bits, they could even have their compiler understand a special internal type and e.g. name it __int64 and then make stdint.h contain a typedef __int64 int64_t;.
The C standard just defines that there has to be a stdint.h header provided with your compiler, and that if you define int64_t in there, it has to map to a data type that is the right size.
Theoretically one could just build everything in stdint.h into the compiler instead (so instead of using an intermediate name like __int64 and typedefing it to int64_t, they could just use int64_t directly, but by using this approach, old code that was written before stdint.h existed and defined their own type named int64_t can just not include stdint and will thus keep compiling. Names starting with two underscores have been historically reserved for the compiler maker, so there is no chance of existing C code using the name __int64 already.
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).
From Using the FreeRTOS Real Time Kernel - Standard Edition, p143, I noticed that:
int types are never used – only long and short
I would like to know why, but I find no answer in its official site and no result after google.
Update 08/31:
Maybe my question is not so clear, in short, I just wonder that why FreeRTOS defines BaseType_t as long instead of int(and other FreeRTOS defined types are never use int, too). From its Coding-Standard-and-Style-Guide page, it said that:
BaseType_t
This is defined to be the most efficient, natural, type for the architecture. For example, on a 32-bit architecture BaseType_t will be defined to be a 32-bit type. On a 16-bit architecture BaseType_t will be defined to be a 16-bit type. If BaseType_t is define to char then particular care must be taken to ensure signed chars are used for function return values that can be negative to indicate an error.
From the above description, I think int is more suitable than long, since int is always conform to the architecture's word size.
The FreeRTOS coding standard disagrees with your reference.
The actual requirement is that you use typedefs that have been defined by RTOS, or the integer typedefs found in stdint.h, such as uint32_t. Normally, the types found in stdint.h are acceptable, because the size of those integers do not vary on different architectures.
Not an official answer by any means, by I would suppose they wanted to make sure their types are clearly defined, and therefore decided on 3 int types: char (uint8_t), short (unit16_t) and long (uint32_t). This way any confusion as to what's the size of int is avoided.
In Windows, it is "%I64d". In Linux and Solaris, it is "%lld".
If I want to write cross-platform printfs that prints long long values: what is good way of doing so ?
long long ll;
printf(???, ll);
There are a couple of approaches.
You could write your code in C99-conforming fashion, and then supply system-specific hacks when the compiler-writers let you down. (Sadly, that's rather common in C99.)
#include <stdint.h>
#include <inttypes.h>
printf("My value is %10" PRId64 "\n", some_64_bit_expression);
If one of your target systems has neglected to implement <inttypes.h> or has in some other way fiendishly slacked off because some of the type features are optional, then you just need a system-specific #define for PRId64 (or whatever) on that system.
The other approach is to pick something that's currently always implemented as 64-bits and is supported by printf, and then cast. Not perfect but it will often do:
printf("My value is %10lld\n", (long long)some_64_bit_expression);
MSVC supports long long and ll starting Visual Studio 2005.
You could check the value of the _MSC_VER macro (>= 1400 for 2005), or simply don't support older compilers.
It doesn't provide the C99 macros, so you will have to cast to long long rather than using PRId64.
This won't help if you're using older MSVC libraries with a non-MSVC compiler (I think mingw, at least, provides its own version of printf that supports ll)
No on linux and solaris it is only incidentally that this is lld for a 64bit type. C99 prescribes simple (but ugly) macros to make these things portable PRId64. Since some windows compilers don't follow the standard you might be out of luck, there, unfortunately.
Edit: In your example you are using a different thing than a 64bit integer, namely a long long. This could well be 128 on some architectures. Here C99 has typedefs that guarantee you the minimum or exact width of the type (if they are implemented on the platform). These types are found with the inttypes.h header, namely int64_t for a fixe-width 64 bit type represented in two's complement. Maybe or maybe not your windows compiler has this.
As alternative you can use code like this:
uint64_t currentTimeMs = ...;
printf("currentTimeMs = 0x%08x%08x\n",
(uint32_t)(currentTimeMs >> 32),
(uint32_t)(currentTimeMs & 0xFFFFFFFF)
);
Or maybe:
printf("currentTimeMs = %u%09u\n",
(uint32_t)(currentTimeMs / 1000000000),
(uint32_t)(currentTimeMs % 1000000000)
);
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.