Range of char type values in C - c

Is it possible to store more than a byte value to a char type?
Say for example char c; and I want to store 1000 in c. is it possible to do that?

Technically, no, you can't store more than a byte value to a char type. In C, a char and a byte are the same size, but not necessarily limited to 8 bits. Many standards bodies tend to use the term "octet" for an exactly-8-bit value.
If you look inside limits.h (from memory), you'll see the CHAR_BIT symbol (among others) telling you how many bits are actually used for a char and, if this is large enough then, yes, it can store the value 1000.

The range of values you can store in a C type depends on its size, and that is not specified by C, it depends on the architecture. A char type has a minimum of 8 bits. And typically (almost universally) that's also its maximum (you can check it in your limits.h).
Hence, in a char you will be able to store from -128 to 127, or from 0 to 255 (signed or unsigned).

The minimum size for a char in C is 8 bits, which is not wide enough to hold more than 256 values. It may be wider in a particular implementation such as a word-addressable architecture, but you shouldn't rely on that.

Include limits.h and check the value of CHAR_MAX.

Probably not. The C standard requires that a char can hold at least 8 bits, so you can't depend on being able to store a value longer than 8 bits in a char portably.
(* In most commonly-used systems today, chars are 8 bits).

Char's width is system-dependent. But assuming you're using something reasonably C99-compatible, you should have access to a header stdint.h, which defines types of the formats intN_t and uintN_t where N=8,16,32,64. These are guaranteed to be at least N bits wide. So if you want to be certain to have a type with a certain amount of bits (regardless of system), those are the guys you want.
Example:
#include <stdint.h>
uint32_t foo; /* Unsigned, 32 bits */
int16_t bar; /* Signed, 16 bits */

Related

Difference between uint8_t and unsigned char

I'm using mplabX 4.20, and xc8 compiler. I'm trying to understand which is the difference between uint8_t and unsigned char. Both of them have size from 0 till 255.
Both of can hold characters and numbers. But which is better to use, and for which case?
Example if i want to create a buffer for holding a string.
uint8_t buffer[20]="Hello World";
unsigned char buffer[20]="Hello World";
In most cases i need to hold characters. Which is the best practise for this action?
I'm using mplabX 4.20, and xc8 compiler. I'm trying to understand
which is the difference between uint8_t and unsigned char. Both of
them have size from 0 till 255. Both of can hold characters and
numbers. But which is better to use, and for which case?
unsigned char is the unsigned integer type corresponding to signed char. Its representation does not use any padding bits. Both of these occupy the same amount of storage as type char, which is at least 8 bits, but may be more. The macro CHAR_BIT tells you how many it comprises in your implementation. Every conforming C implementation provides all of these types.
uint8_t, if available, is an unsigned integer data type exactly 8 bits wide and with no padding bits. On an implementation having CHAR_BIT defined as 8, this is the same type as unsigned char. On such systems you may use the two types interchangeably wherever the declarations provided by stdint.h are in scope. On other systems, uint8_t will not be declared at all.
Example if i want to create a buffer for holding a string.
If you want to declare a buffer for holding a string then as a matter of style, you should use type char, not either of the other two:
char buffer[20] = "Hello World";
Although either of the other two, or signed char, can also be used for string data (provided in the case of uint8_t that the type is defined at all), type char is the conventional one to use for character data. Witness, for example, that that's the type in terms of which all the string.h functions are declared.
You should use uint8_t where and only where you need an integer type with exactly its properties: unsigned, 8 value bits, no padding bits.
You should use unsigned char where you want the smallest unsigned integer type available, but you don't care whether it is exactly 8 bits wide, or where you want to emphasize that it is the same size as a char -- the smallest discrete unit of storage available.
You should use signed char where you want the smallest signed integer type available but don't care about the exact size or representation.
You should use int8_t where you want a signed integer type with exactly 7 value bits, one sign bit, and no padding bits, expressed in two's complement representation.
You should remain mindful that uint8_t and int8_t are not guaranteed to be available from every C implementation, and that where they are available, their use requires inclusion of stdint.h. Furthermore, this header and these types were not part of C90 at all, so you should not use them if compatibility with legacy C implementations is important to you.
difference between uint8_t and unsigned char
If you're on a some exotic system where CHAR_BIT > 8, then uint8_t isn't going to be defined at all.
Otherwise (if CHAR_BIT == 8) there is no difference between unsigned char and uint8_t.
i need to hold characters
Then use plain char.
Functions that operate in strings usually have [const]char * parameters, and you won't be able to pass your unsigned char arrays to them.

How to declare different size variables

Hi I want to declare a 12 bit variable in C or any "unconventional" size variable (a variable that is not in the order of 2^n). how would I do that. I looked everywhere and I couldn't find anything. If that is not possible how would you go about saving certain data in its own variable.
Use a bitfield:
struct {
unsigned int twelve_bits: 12;
} wrapper;
Unlike Ada, C has no way to specify types with a limited range of values. C relies on predefined types with implementation defined characteristics, but with certain guarantees:
Types short and int are guaranteed by the standard to hold at least 16 bits, you can use either one to hold your 12 bit values, signed or unsigned.
Similarly, type long is guaranteed to hold at least 32 bits and type long long at least 64 bits. Choose the type that is large enough for your purpose.
Types int8_t, int16_t, int32_t, int64_t and their unsigned counterparts defined in <stdint.h> have more precise semantics but might not be available on all systems. Types int_least8_t, int_least16_t, int_least32_t and int_least64_t are guaranteed to be available, as well as similar int_fastXX_t types, but they are not used very often, probably because the names are somewhat cumbersome.
Finally, you can use bit-fields for any bit counts from 1 to 64, but these are only available as struct members. bit-fields of size one should be declared as unsigned.
Data is always stored in groups of bytes (8 bits each).
In C, variables can be declared of 1 byte (a "char" or 8 bits), 2 bytes (a "short" int on many computers is 16 bits), and 4 bytes (a "long" int on many computers is 32 bits).
On a more advanced level, you are looking for "bitfields".
See this perhaps: bitfield discussion

What's the smallest data type in C that can store the number 10,000,000?

I'm trying to celebrate 10,000,000 questions on StackOverflow with a simple console application written in C, but I don't want to waste any memory. What's the most efficient way to store the number 10,000,000 in memory?
The type you're looking for is int_least32_t, from stdint.h, which will give you the smallest type with at least 32 bits. This type is guaranteed to exist on C99 implementations.
Exact-width typedefs such as int32_t are not guaranteed to exist, though you'd be hard pressed to find a platform without it.
The number 10000000 (ten million) requires 24 bits to store as an unsigned value.
Most C implementations do not have a 24-bit type. Any implementation that conforms to the 1999 C standard or later must provide the <stdint.h> header, and must define all of:
uint_least8_t
uint_least16_t
uint_least32_t
uint_least64_t
each of which is (an alias for) an unsigned integer type with at least the specified width, such that no narrower integer type has at least the specified width. Of these, uint_least32_t is the narrowest type that's guaranteed to hold the value 10000000.
On the vast majority of C implementations, uint_least32_t is the type you're looking for -- but on an implementation that supports 24-bit integers, there will be a narrower type that satisfies your requirements.
Such an implementation would probably define uint24_t, assuming that it's unsigned 24-bit type has no padding bits. So you could do something like this:
#include <stdint.h>
#ifdef UINT_24_MAX
typedef uint24_t my_type;
#else
typedef uint_least32_t my_type;
#endif
That's still not 100% reliable (for example if there's a 28-bit type but no 24-bit type, this would miss it). In the worst case, it would select uint_least32_t.
If you want to restrict yourself to the predefined types (perhaps because you want to support pre-C99 implementations), you could do this:
#include <limits.h>
#define TEN_MILLION 10000000
#if UCHAR_MAX >= TEN_MILLION
typedef unsigned char my_type;
#elif USHRT_MAX >= TEN_MILLION
typedef unsigned short my_type;
#elif UINT_MAX >= TEN_MILLION
typedef unsigned int my_type;
#else
typedef unsigned long my_type;
#endif
If you merely want the narrowest predefined type that's guaranteed to hold the value 10000000 on all implementations (even if some implementations might have a narrower type that can hold it), use long (int can be a narrow as 16 bits).
If you don't require using an integer type, you can simply define a type that's guaranteed to be 3 bytes wide:
typedef unsigned char my_type[3];
But actually that will be wider than you need of CHAR_BIT > 8:
typedef unsigned char my_type[24 / CHAR_BIT]
but that will fail if 24 is not a multiple of CHAR_BIT.
Finally, your requirement is to represent the number 10000000; you didn't say you need to be able to represent any other numbers:
enum my_type { TEN_MILLION };
Or you can define a 1-bit bitfield with the value 1 denoting 10000000 and the value 0 denoting not 10000000.
Technically a 24-bit integer can store that, but there are no 24-bit primitive types in C. You will have to use a 32-bit int, or a long.
For performance that would be the best approach, wasting 1 unused byte of memory is irrelevant.
Now, if for study purposes you really really want to store 10 million in the smallest piece of memory possible, and you are even willing to make your own data storage method to achieve that, you can store that in 1 byte, by customizing a storage method that follows the example of float. You only need 4 bits to represent 10, and other 3 bits to represent 7, and have in 1 byte all data you need to calculate pow(10, 7);. It even leaves you with an extra free bit you can use as sign.
The largest value that can be stored in an uint16_t is 0xFFFF, which is 65535 in decimal. That is obviously not large enough.
The largest value that can be stored in an uint32_t is 0xFFFFFFFF, which is 4294967295 in decimal. That is obviously large enough.
Looks like you'll need to use uint32_t.
If you want to store a number n > 0 in an unsigned integer data type, then you need at least ⌈lg (n+1)⌉ bits in your integer type. In your case, ⌈lg (10,000,000 + 1)⌉ = 24, so you'd need at least 24 bits in whatever data type you picked.
To the best of my knowledge, the C spec does not include an integer type that holds specifically 24 bits. The closest option would be to use something like uint32_t, but (as was mentioned in a comment) this type might not exist on all compilers. The type int_least32_t is guaranteed to exist, but it might be way larger than necessary.
Alternatively, if you just need it to work on one particular system, your specific compiler may have a compiler-specific data type for 24-bit integers. (Spoiler: it probably doesn't. ^_^)
The non-smart-alecky answer is uint32_t or int32_t.
But if you're really low on memory,
uint8_t millions_of__questions;
But only if you are a fan of fixed-point arithmetic and are willing to deal with some error (or are using some specialized numerical representation scheme). Depends on what you're doing with it after you store it and what other numbers you want to be storable in your "datatype".
struct {
uint16_t low; // Lower 16 bits
uint8_t high; // Upper 8 bits
} my_uint24_t;
This provides 24-bits of storage and can store values up to 16,777,215. It's not a native type and would need to special accessor functions, but it takes less space than a 32-bit integer on most platforms (packing may be required).
uint32_t from <stdint.h> would probably be your go-to data type. Since uint16_t would only be able to store 2^16-1=65535, the next available type is uint32_t.
Note that uint32_t stores unsigned values; use int32_t if you want to store signed numbers as well. You can find more info, e.g., here: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html

Is there a C99 data type guaranteed to be at least two bytes?

To determine the endianness of a system, I plan to store a multi-byte integer value in a variable and access the first byte via an unsigned char wrapped in a union; for example:
union{
unsigned int val;
unsigned char first_byte;
} test;
test.val = 1; /* stored in little-endian system as "0x01 0x00 0x00 0x00" */
if(test.first_byte == 1){
printf("Little-endian system!");
}else{
printf("Big-endian system!");
}
I want to make this test portable across platforms, but I'm not sure if the C99 standard guarantees that the unsigned int data type will be greater than one byte in size. Furthermore, since a "C byte" does not technically have to be 8-bits in size, I cannot use exact width integer types (e.g. uint8_t, uint16_t, etc.).
Are there any C data types guaranteed by the C99 standard to be at least two bytes in size?
P.S. Assuming an unsigned int is in fact greater than one byte, would my union behave as I'm expecting (with the variable first_byte accessing the first byte in variable val) across all C99 compatible platforms?
Since int must have a range of at least 16 bits, int will meet your criterion on most practical systems. So would short (and long, and long long). If you want exactly 16 bits, you have to look to see whether int16_t and uint16_t are declared in <stdint.h>.
If you are worried about systems where CHAR_BIT is greater than 8, then you have to work harder. If CHAR_BIT is 32, then only long long is guaranteed to hold two characters.
What the C standard says about sizes of integer types
In a comment, Richard J Ross III says:
The standard says absolutely nothing about the size of an int except that it must be larger than or equal to short, so, for example, it could be 10 bits on some systems I've worked on.
On the contrary, the C standard has specifications on the lower bounds on the ranges that must be supported by different types, and a system with 10-bit int would not be conformant C.
Specifically, in ISO/IEC 9899:2011 §5.2.4.2.1 Sizes of integer types <limits.h>, it says:
¶1 The values given below shall be replaced by constant expressions suitable for use in #if
preprocessing directives. Moreover, except for CHAR_BIT and MB_LEN_MAX, the
following shall be replaced by expressions that have the same type as would an
expression that is an object of the corresponding type converted according to the integer
promotions. Their implementation-defined values shall be equal or greater in magnitude
(absolute value) to those shown, with the same sign.
— number of bits for smallest object that is not a bit-field (byte)
CHAR_BIT 8
[...]
— minimum value for an object of type short int
SHRT_MIN -32767 // −(215 − 1)
— maximum value for an object of type short int
SHRT_MAX +32767 // 215 − 1
— maximum value for an object of type unsigned short int
USHRT_MAX 65535 // 216 − 1
— minimum value for an object of type int
INT_MIN -32767 // −(215 − 1)
— maximum value for an object of type int
INT_MAX +32767 // 215 − 1
— maximum value for an object of type unsigned int
UINT_MAX 65535 // 216 − 1
GCC provides some macros giving the endianness of a system: GCC common predefined macros
example (from the link supplied):
/* Test for a little-endian machine */
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
Of course, this is only useful if you use gcc. Furthermore, conditional compilation for endianness can be considered harmful. Here is a nice article about this: The byte order fallacy.
I would prefer to do this using regular condtions to let the compiler check the other case. ie:
if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
...
No, nothing is guaranteed to be larger than one byte -- but it is guaranteed that no (non-bitfield) type is smaller than one byte and that one byte can hold at 256 distinct values, so if you have an int8_t and an int16_t, then it's guaranteed that int8_t is one byte, so int16_t must be two bytes.
The C standard guarantees only that the size of char <= short <= int <= long <= long long [and likewise for unsigned]. So, theoretically, there can be systems that have only one size for all of the sizes.
If it REALLY is critical that this isn't going wrong on some particular architecture, I would add a piece of code to do something like if (sizeof(char) == sizeof(int)) exit_with_error("Can't do this...."); to the code.
In nearly all machines, int or short should be perfectly fine. I'm not actually aware of any machine where char and int are the same size, but I'm 99% sure that they do exist. Those machines may also have it's native byte != 8 bits, such as 9 or 14 bits, and words that are 14, 18 or 36 or 28 bits...
Take a look at the man page of stdint.h (uint_least16_t for 2 bytes)
At least according to http://en.wikipedia.org/wiki/C_data_types -- the size of an int is guaranteed to be two "char"s long. So, this test should work, although I'm wondering if there is a more appropriate solution. For one, with rare exception, most architectures would have their endianness set compile-time, and not runtime. There are a few architectures that can switch endianness, though (I believe ARM and PPC are configurable, but ARM is traditionally LE, and PPC is mostly BE).
A conforming implementation can have all its fundamental types of size 1 (and hold at least 32 bits worth of data). For such an implementation, however, the notion of endianness is not applicable.
Nothing forbids a conforming implementation to have, say, little-endian shorts and big-endian longs.
So there are three possible outcomes for each integral type: it could be big-endian, little-endian, or of size 1. Check each type separately for maximum theoretical portability. In practice this probably never happens.
Middle-endian types, or e.g. big-endian stuff on even-numbered pages only, are theoretically possible, but I would refrain from even thinking about such an implementation.
While the answer is basically "no", satisfying the interface requirements for the stdio functions requires that the range [0,UCHAR_MAX] fit in int, which creates an implicit requirement that sizeof(int) is greater than 1 on hosted implementations (freestanding implementations are free to omit stdio, and there's no reason they can't have sizeof(int)==1). So I think it's fairly safe to assume sizeof(int)>1.

Is the size of C "int" 2 bytes or 4 bytes?

Does an Integer variable in C occupy 2 bytes or 4 bytes? What are the factors that it depends on?
Most of the textbooks say integer variables occupy 2 bytes.
But when I run a program printing the successive addresses of an array of integers it shows the difference of 4.
I know it's equal to sizeof(int). The size of an int is really compiler dependent. Back in the day, when processors were 16 bit, an int was 2 bytes. Nowadays, it's most often 4 bytes on a 32-bit as well as 64-bit systems.
Still, using sizeof(int) is the best way to get the size of an integer for the specific system the program is executed on.
EDIT: Fixed wrong statement that int is 8 bytes on most 64-bit systems. For example, it is 4 bytes on 64-bit GCC.
This is one of the points in C that can be confusing at first, but the C standard only specifies a minimum range for integer types that is guaranteed to be supported. int is guaranteed to be able to hold -32767 to 32767, which requires 16 bits. In that case, int, is 2 bytes. However, implementations are free to go beyond that minimum, as you will see that many modern compilers make int 32-bit (which also means 4 bytes pretty ubiquitously).
The reason your book says 2 bytes is most probably because it's old. At one time, this was the norm. In general, you should always use the sizeof operator if you need to find out how many bytes it is on the platform you're using.
To address this, C99 added new types where you can explicitly ask for a certain sized integer, for example int16_t or int32_t. Prior to that, there was no universal way to get an integer of a specific width (although most platforms provided similar types on a per-platform basis).
There's no specific answer. It depends on the platform. It is implementation-defined. It can be 2, 4 or something else.
The idea behind int was that it was supposed to match the natural "word" size on the given platform: 16 bit on 16-bit platforms, 32 bit on 32-bit platforms, 64 bit on 64-bit platforms, you get the idea. However, for backward compatibility purposes some compilers prefer to stick to 32-bit int even on 64-bit platforms.
The time of 2-byte int is long gone though (16-bit platforms?) unless you are using some embedded platform with 16-bit word size. Your textbooks are probably very old.
The answer to this question depends on which platform you are using.
But irrespective of platform, you can reliably assume the following types:
[8-bit] signed char: -127 to 127
[8-bit] unsigned char: 0 to 255
[16-bit]signed short: -32767 to 32767
[16-bit]unsigned short: 0 to 65535
[32-bit]signed long: -2147483647 to 2147483647
[32-bit]unsigned long: 0 to 4294967295
[64-bit]signed long long: -9223372036854775807 to 9223372036854775807
[64-bit]unsigned long long: 0 to 18446744073709551615
C99 N1256 standard draft
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
The size of int and all other integer types are implementation defined, C99 only specifies:
minimum size guarantees
relative sizes between the types
5.2.4.2.1 "Sizes of integer types <limits.h>" gives the minimum sizes:
1 [...] Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown [...]
UCHAR_MAX 255 // 2 8 − 1
USHRT_MAX 65535 // 2 16 − 1
UINT_MAX 65535 // 2 16 − 1
ULONG_MAX 4294967295 // 2 32 − 1
ULLONG_MAX 18446744073709551615 // 2 64 − 1
6.2.5 "Types" then says:
8 For any two integer types with the same signedness and different integer conversion rank
(see 6.3.1.1), the range of values of the type with smaller integer conversion rank is a
subrange of the values of the other type.
and 6.3.1.1 "Boolean, characters, and integers" determines the relative conversion ranks:
1 Every integer type has an integer conversion rank defined as follows:
The rank of long long int shall be greater than the rank of long int, which
shall be greater than the rank of int, which shall be greater than the rank of short
int, which shall be greater than the rank of signed char.
The rank of any unsigned integer type shall equal the rank of the corresponding
signed integer type, if any.
For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has
greater rank than T3, then T1 has greater rank than T3
Does an Integer variable in C occupy 2 bytes or 4 bytes?
That depends on the platform you're using, as well as how your compiler is configured. The only authoritative answer is to use the sizeof operator to see how big an integer is in your specific situation.
What are the factors that it depends on?
Range might be best considered, rather than size. Both will vary in practice, though it's much more fool-proof to choose variable types by range than size as we shall see. It's also important to note that the standard encourages us to consider choosing our integer types based on range rather than size, but for now let's ignore the standard practice, and let our curiosity explore sizeof, bytes and CHAR_BIT, and integer representation... let's burrow down the rabbit hole and see it for ourselves...
sizeof, bytes and CHAR_BIT
The following statement, taken from the C standard (linked to above), describes this in words that I don't think can be improved upon.
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand.
Assuming a clear understanding will lead us to a discussion about bytes. It's commonly assumed that a byte is eight bits, when in fact CHAR_BIT tells you how many bits are in a byte. That's just another one of those nuances which isn't considered when talking about the common two (or four) byte integers.
Let's wrap things up so far:
sizeof => size in bytes, and
CHAR_BIT => number of bits in byte
Thus, Depending on your system, sizeof (unsigned int) could be any value greater than zero (not just 2 or 4), as if CHAR_BIT is 16, then a single (sixteen-bit) byte has enough bits in it to represent the sixteen bit integer described by the standards (quoted below). That's not necessarily useful information, is it? Let's delve deeper...
Integer representation
The C standard specifies the minimum precision/range for all standard integer types (and CHAR_BIT, too, fwiw) here. From this, we can derive a minimum for how many bits are required to store the value, but we may as well just choose our variables based on ranges. Nonetheless, a huge part of the detail required for this answer resides here. For example, the following that the standard unsigned int requires (at least) sixteen bits of storage:
UINT_MAX 65535 // 2¹⁶ - 1
Thus we can see that unsigned int require (at least) 16 bits, which is where you get the two bytes (assuming CHAR_BIT is 8)... and later when that limit increased to 2³² - 1, people were stating 4 bytes instead. This explains the phenomena you've observed:
Most of the textbooks say integer variables occupy 2 bytes. But when I run a program printing the successive addresses of an array of integers it shows the difference of 4.
You're using an ancient textbook and compiler which is teaching you non-portable C; the author who wrote your textbook might not even be aware of CHAR_BIT. You should upgrade your textbook (and compiler), and strive to remember that I.T. is an ever-evolving field that you need to stay ahead of to compete... Enough about that, though; let's see what other non-portable secrets those underlying integer bytes store...
Value bits are what the common misconceptions appear to be counting. The above example uses an unsigned integer type which typically contains only value bits, so it's easy to miss the devil in the detail.
Sign bits... In the above example I quoted UINT_MAX as being the upper limit for unsigned int because it's a trivial example to extract the value 16 from the comment. For signed types, in order to distinguish between positive and negative values (that's the sign), we need to also include the sign bit.
INT_MIN -32768 // -(2¹⁵)
INT_MAX +32767 // 2¹⁵ - 1
Padding bits... While it's not common to encounter computers that have padding bits in integers, the C standard allows that to happen; some machines (i.e. this one) implement larger integer types by combining two smaller (signed) integer values together... and when you combine signed integers, you get a wasted sign bit. That wasted bit is considered padding in C. Other examples of padding bits might include parity bits and trap bits.
As you can see, the standard seems to encourage considering ranges like INT_MIN..INT_MAX and other minimum/maximum values from the standard when choosing integer types, and discourages relying upon sizes as there are other subtle factors likely to be forgotten such as CHAR_BIT and padding bits which might affect the value of sizeof (int) (i.e. the common misconceptions of two-byte and four-byte integers neglects these details).
The only guarantees are that char must be at least 8 bits wide, short and int must be at least 16 bits wide, and long must be at least 32 bits wide, and that sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) (same is true for the unsigned versions of those types).
int may be anywhere from 16 to 64 bits wide depending on the platform.
Is the size of C “int” 2 bytes or 4 bytes?
The answer is "yes" / "no" / "maybe" / "maybe not".
The C programming language specifies the following: the smallest addressable unit, known by char and also called "byte", is exactly CHAR_BIT bits wide, where CHAR_BIT is at least 8.
So, one byte in C is not necessarily an octet, i.e. 8 bits. In the past one of the first platforms to run C code (and Unix) had 4-byte int - but in total int had 36 bits, because CHAR_BIT was 9!
int is supposed to be the natural integer size for the platform that has range of at least -32767 ... 32767. You can get the size of int in the platform bytes with sizeof(int); when you multiply this value by CHAR_BIT you will know how wide it is in bits.
While 36-bit machines are mostly dead, there are still platforms with non-8-bit bytes. Just yesterday there was a question about a Texas Instruments MCU with 16-bit bytes, that has a C99, C11-compliant compiler.
On TMS320C28x it seems that char, short and int are all 16 bits wide, and hence one byte. long int is 2 bytes and long long int is 4 bytes. The beauty of C is that one can still write an efficient program for a platform like this, and even do it in a portable manner!
Mostly it depends on the platform you are using .It depends from compiler to compiler.Nowadays in most of compilers int is of 4 bytes.
If you want to check what your compiler is using you can use sizeof(int).
main()
{
printf("%d",sizeof(int));
printf("%d",sizeof(short));
printf("%d",sizeof(long));
}
The only thing c compiler promise is that size of short must be equal or less than int and size of long must be equal or more than int.So if size of int is 4 ,then size of short may be 2 or 4 but not larger than that.Same is true for long and int. It also says that size of short and long can not be same.
This depends on implementation, but usually on x86 and other popular architectures like ARM ints take 4 bytes. You can always check at compile time using sizeof(int) or whatever other type you want to check.
If you want to make sure you use a type of a specific size, use the types in <stdint.h>
#include <stdio.h>
int main(void) {
printf("size of int: %d", (int)sizeof(int));
return 0;
}
This returns 4, but it's probably machine dependant.
Is the size of C “int” 2 bytes or 4 bytes?
Does an Integer variable in C occupy 2 bytes or 4 bytes?
C allows "bytes" to be something other than 8 bits per "byte".
CHAR_BIT number of bits for smallest object that is not a bit-field (byte) C11dr §5.2.4.2.1 1
A value of something than 8 is increasingly uncommon. For maximum portability, use CHAR_BIT rather than 8. The size of an int in bits in C is sizeof(int) * CHAR_BIT.
#include <limits.h>
printf("(int) Bit size %zu\n", sizeof(int) * CHAR_BIT);
What are the factors that it depends on?
The int bit size is commonly 32 or 16 bits. C specified minimum ranges:
minimum value for an object of type int INT_MIN -32767
maximum value for an object of type int INT_MAX +32767
C11dr §5.2.4.2.1 1
The minimum range for int forces the bit size to be at least 16 - even if the processor was "8-bit". A size like 64 bits is seen in specialized processors. Other values like 18, 24, 36, etc. have occurred on historic platforms or are at least theoretically possible. Modern coding rarely worries about non-power-of-2 int bit sizes.
The computer's processor and architecture drive the int bit size selection.
Yet even with 64-bit processors, the compiler's int size may be 32-bit for compatibility reasons as large code bases depend on int being 32-bit (or 32/16).
This is a good source for answering this question.
But this question is a kind of a always truth answere "Yes. Both."
It depends on your architecture. If you're going to work on a 16-bit machine or less, it can't be 4 byte (=32 bit). If you're working on a 32-bit or better machine, its length is 32-bit.
To figure out, get you program ready to output something readable and use the "sizeof" function. That returns the size in bytes of your declared datatype. But be carfull using this with arrays.
If you're declaring int t[12]; it will return 12*4 byte. To get the length of this array, just use sizeof(t)/sizeof(t[0]).
If you are going to build up a function, that should calculate the size of a send array, remember that if
typedef int array[12];
int function(array t){
int size_of_t = sizeof(t)/sizeof(t[0]);
return size_of_t;
}
void main(){
array t = {1,1,1}; //remember: t= [1,1,1,0,...,0]
int a = function(t); //remember: sending t is just a pointer and equal to int* t
print(a); // output will be 1, since t will be interpreted as an int itselve.
}
So this won't even return something different. If you define an array and try to get the length afterwards, use sizeof. If you send an array to a function, remember the send value is just a pointer on the first element. But in case one, you always knows, what size your array has. Case two can be figured out by defining two functions and miss some performance. Define function(array t) and define function2(array t, int size_of_t). Call "function(t)" measure the length by some copy-work and send the result to function2, where you can do whatever you want on variable array-sizes.

Resources