Size of Data Types in C

Data types are one of the most crucial features in the C programming language. We use the data types with functions and variables for defining what kind of data it typically holds. This data can be some type of character or value. There can also be various sets of characters or sets of values. The C language offers a very wide range of all the data types, and each of these may contain a unique data type with some certain range that is predefined.

In this article, we will take a closer look at the Size of Data Types in C according to the GATE Syllabus for CSE (Computer Science Engineering). Read ahead to know more.

Table of Contents

Types of Data Types in C

The C programming language has two basic data types:

  • Primary
  • Derived

Primary Data Types

The primary data types are basically standard data types that the C language defines. The language defines four of the basic data types in programming. These are:

char – these are single-byte in nature. The char data type can hold a single character in a local character set.

float – these are single-precision types of floating-point.

int – these are integers. They typically reflect the integer’s natural size on a host machine.

double – these are double-precision types of floating-point.

Apart from this, one can also apply various numbers of qualifiers to the basic data types. The long and short qualifiers applied to integers would turn out to be:

long int counter;

short int sh;

*Note that we can omit the word int in such types of declarations.

Size of Primary Data Types

Here is a list of all the primary data types:

Type Range Size (in bytes)
unsigned char 0 to 255 1
signed char or char -128 to +127 1
unsigned int 0 to 65535 2
signed int or int -32,768 to +32767 2
unsigned short int 0 to 65535 2
signed short int or short int -32,768 to +32767 2
unsigned long int 0 to +4,294,967,295 4
signed long int or long int -2,147,483,648 to +2,147,483,647 4
long double 3.4E-4932 to 1.1E+4932 10
double 1.7E-308 to 1.7E+308 8
float 3.4E-38 to 3.4E+38 4

The data type size and range depend a lot on the compiler. However, the code that the compiler compiles is targeted for some specific types of Microcontrollers or Microprocessors. One single compiler can provide support for multiple targets or processors. The compiler then defines the size for the available data types on the basis of the selected target. In simpler words, the size of any data type is directly dependent on the compiler along with the target processor (for which the code generation occurs using the compiler).

In the table mentioned above, we have assumed a 16-bit compiler. It means that the code generation of the compiler will be for a 16-bit target processor. The integer is, normally, the natural size for any processor or machine. In the table mentioned above, the integer is 16-bit or 2 bytes wide. Thus, the compiler is also 16-bit or 2 bytes wide. If the compiler was 32-bit wide, the int type size would have been about 32-bits or 4 bytes. However, this might not be the case every single time. It is also possible that the integer size is 32-bits or 4 bytes for a 64-bits processor. It entirely depends on the type of compiler.

Let us take a look at an example of an integer data type:

int temp; // the ‘temp’ variable is capable of holding the integer values

(both negative or positive)

temp = 50;

temp = -50;

signed int temp; // the ‘temp’ variable is capable of holding the integer values

(both negative or positive)

temp = 987654;

temp = -987654;

unsigned int temp; // the ‘temp’ variable is capable of holding the integer values

(only positive)

temp = 87654;

temp = -8; // The given assignment is invalid

Char Size

The size of both unsigned and signed char is 1 byte always, irrespective of what compiler we use. Here, a signed character is capable of holding negative values. Thus, the defined range here is -128 to +127. But the unsigned character is only capable of holding the positive values. Thus, the range for such characters is from 0 to 255. These character data types are capable of storing the ASCII characters or the numbers that are equivalent to the ASCII characters.

Short Integer Size

The size of both unsigned and signed integers is about 2 bytes in a majority of the compilers.

Long Integer Size

The size of both unsigned and signed long integers depends on the type of compiler that we use. The size is typically about 32-bits or 4 bytes on a 16/ 32-bit compiler. Yet, it varies depending on what compiler we are using.

There is no specification of the data types sizes according to the C standard, except the character. According to the definition by C:

Every compiler can choose an appropriate size for hardware of its own. It is only subjected to a single restriction that the longs are 32 bits at least, ints and shorts are 16 bits at least, the short is not longer than the int, and the int is not longer than the long.

What differentiates the range for unsigned and signed types?

Although the size of any unsigned as well as the signed data type is all the same, they both possess different ranges of values to be stored in any variable. Why? It is because the representation of the signed numbers is in 2’s complement form in any processor or machine. For instance, the representation of the number -23 in the form of 2’s complement would be:

(Decimal) 23 <-> (Binary) 10111

The 1’s complement

The 1’s complement of 10111 will be – 1111111111111111111111111111111111111111111111111111111111101000

Here, the total number of 1s that are added before the actual number depends a lot on the size of the machine or that of the target processor. Since the machine we are dealing with here is a 64-bit machine, we have added these many 1s, so that the final number also becomes a 64-bit number.

In simpler words, the 1’s complement is basically an inverted version of the actual number. The 0s get converted to 1s and the 1s get converted to 0s.

The 2’s complement

The 2’s complement is basically 1’s complement + 1, i.e.,

1111111111111111111111111111111111111111111111111111111111101000 + 1:

1111111111111111111111111111111111111111111111111111111111101001 <-> (decimal) -23

Some calculations on the computer would help you verify this result here.

Let us take a look at an example of a signed character that is capable of storing numbers that fall between -128 to +127. Now, we all know that both unsigned and signed char are capable of storing just 8-bits of data in them.

So, if we assume that we are trying to store a number, -190, in an 8-bits wide variable character, then the processor would handle the number as follows:

(Decimal) 190 <-> (Binary) 10111110 : 8-bits

1’s complement of the value 190: (Binary) 01000001 : 8-bits

2’s complement of the value 190: (Binary) 01000010 : 8-bits

(Binary) 01000010 <-> (Decimal) 66

The interpretation of the character numbers by the computer would be as follows:

(1) MSB bit: The sign of the number [0: Positive, 1: Negative], 7-0 Bits: 1000010: [66] Actual data

It means that whenever we try to store a number that is greater than the defined range, the number will ultimately get rounded down. Thus, we got the result of 256-190 to be 66. Here, 256 is basically the maximum value that an unsigned character number can keep stored.

Now, let us take a look at another example of how we can store the number -126 in a variable of char data type.

(Decimal) 126 <-> (Binary) 01111110

1’s complement of 126: (Binary) 10000001 : 8-bits

2’s complement of 126: (Binary) 10000010 : 8-bits

(Binary) 10000010 <-> (Decimal) -126

If you want to verify the obtained results, you can perform reverse calculations. Here, the number is negative since the MSB is 1. Also, 0000010 are the other 7 bits. Thus, the number’s 2’s complement would be: ~0000010 = 1111101 = (Decimal) 126

If we combine the number and the sign here, we will obtain the result to be: (Decimal) -126

The very same concept goes well with both unsigned as well as signed integer data types.

In a brief conclusion, both unsigned and signed numbers have the very same definition for data size in C. However, the representation of the signed numbers is in the 2’s complement form, and the binary number’s most significant bit represents that number’s sign. Since binary 1 (extra 1 bit) is there to identify this given number as negative, the overall range of the signed numbers is much less than that of the unsigned numbers.

Your processor handles the negative numbers, and thus, you don’t have to take care of them separately. Just make sure that you assign a valid number to the signed variable that falls in the defined range. In case you fail to do this, the assigned number will ultimately get truncated.

The Floating Point Data Types

The C language specifies two of the primary data types for storing the fractional numbers or the floating-point. These are double or float. One can easily apply the long qualifiers on the double. Thus, we get another type, which is the long double.

In a computer system, the IEEE-754 format represents the floating-point numbers. A majority of modern processors and processors adopt this format. It has two major representations:

1. 32-bit single precision

2. 64-bit double precision

The representation of the floating numbers has further classifications. These are:

1. The Normalised Form

We will take a look at an example to understand this better.

Assume that the 32-bit type of pattern is

1 1000 0001 011 0000 0000 0000 0000 0000, where:

F = 011 0000 0000 0000 0000 0000

E = 1000 0001

S = 1

In a normalised form, the mantissa or the actual fraction is normalised using an implicit that leads 1, which is in the form of 1.F. For instance, in the example mentioned here, the actual fraction would be 1.011 0000 0000 0000 0000 0000 = 1 + 1×2^-2 + 1×2^-3 = 1.375D.

Here, the sign bit basically represents the number’s sign, where S=1 is a negative number and S=0 is a positive number. In the example mentioned above, the S=1. Thus, the number is negative. It means that the number would be -1.375D.

The actual exponent in the normalised form would be E-127 (it is the so-called bias-127 or excess-127). It is because a person needs to represent both negative and positive exponents. In the case of an 8-bit E that ranges from 0 to 255, the actual exponent of the numbers -127 to 128 could be provided by the excess -127 scheme. For instance, in the mentioned example, E-127=129-127=2D.

2. The De-Normalised Form

The normalised form has some serious problems. For instance, it uses an implicit that leads 1 for a fraction. Thus, the normalised form cannot represent zero as a number that would start with 1. The de-normalised form is basically devised for representing the number zero as well as the other numbers. These numbers are in a de-normalised form for the E=0. An implicit that leads 0 and not 1 would be used for a fraction. The actual exponent here is always -126. Thus, we can represent the number 0 using an F=0 and an E=0, because 0.0×2^-126 = 0.

A person can easily represent very small negative and positive numbers in a de-normalised form using an E=0. For instance, if F=011 0000 0000 0000 0000 0000, E=0, and S=1, the actual fraction would be 0.011 = 1×2^-2+1×2^-3 = 0.375D. Now since S=1, the given number is actually negative. Now with E=0, -126 would be the actual exponent. Thus, the number here is -0.375 × 2^ – 126 = -4.4×10^ – 39. Now, this is an extremely small number that is negative (very close to the number 0).

Summary:

The calculation of the value N would be:

(a) For 1 ≤ E ≤ 254, N = (-1)^S × 1.F × 2^(E-127).

The numbers here are in a normalised form. The sign of the number here is represented by the sign-bit. The implicit that leads 1 normalises the fractional part, that is 1.F. The exponent here is in excess (or bias) of 127 for representing both negative and positive exponents. The overall range of the exponents here would be -126 to +127.

(b) In the case of E = 0, N = (-1)^S × 0.F × 2^(-126).

All of these numbers are in the de-normalised form. Thus, the exponent of the value 2^-126 would then evaluate as a number that is very small. We need to represent the denormalised form using E=0 and F=0. These can also represent extremely negative and positive numbers that are close to the value of zero.

(c) In the case of E = 255, some special values would be represented, for instance, NaN (it refers to not a number) and ±INF (the negative and positive infinity).

The Derived Data Types

These are also known as user-defined types. This data type is derived out of the primary data type, thus known as the derived data types. But these are capable of storing a set of various values instead of storing one single value. Unions, structures, arrays, and enum are some of the most common ones in the C language.

Practice Problems on Size of Data Types in C

1. The size of char is 1 byte when the char is:

A. Signed

B. Unsigned

C. Both

D. None. It is more than 1 byte.

Answer – C. Both

2. The int data type reflects the natural size of a _________ on a _____________.

A. integer, program

B. integer, host machine

C. floating-point, host machine

D. floating-point, program

Answer – B. integer, host machine

3. The range and size of a data type range between various:

A. Compilers

B. Operating Systems

C. Both

D. None

Answer – C. Both


FAQs

What differentiates the range for unsigned and signed types?

Although the size of any unsigned as well as the signed data type is all the same, they both possess different ranges of values to be stored in any variable. Why? It is because the representation of the signed numbers is in 2’s complement form in any processor or machine. For instance, the representation of the number -23 in the form of 2’s complement would be:
(Decimal) 23 <-> (Binary) 10111

Why do we use the floating data types?

The C language specifies two of the primary data types for storing the fractional numbers or the floating-point. These are double or float. One can easily apply the long qualifiers on the double. Thus, we get another type, which is the long double.
In a computer system, the IEEE-754 format represents the floating-point numbers. A majority of modern processors and processors adopt this format. It has two major representations:
1. 32-bit single precision
2. 64-bit double precision

Keep learning and stay tuned to get the latest updates on GATE Exam along with GATE Eligibility CriteriaGATE 2023GATE Admit CardGATE Syllabus for CSE (Computer Science Engineering)GATE CSE NotesGATE CSE Question Paper, and more.

Also Explore,

Leave a Comment

Your Mobile number and Email id will not be published.

*

*