Exforsys

H I D E

Home arrow Technical Training arrow C Tutorials

C Programming - Data Types : Part 1

Page 1 of 4
Author: Exforsys Inc.     Published on: 7th Mar 2006    |   Last Updated on: 21st Aug 2011

C language provides various data types for holding different kinds of values. There are several integral data types, a character data type, floating point data types for holding real numbers and more. In addition you can define your own data types using aggregations of the native types.

The C standard gives detailed specifications on the language; implementations of C must conform to the standard. An "implementation" is basically the combination of the compiler, and the hardware platform. As you will see, the C standard usually does not specify exact sizes for the native types, preferring to set a basic minimum that all conforming implementations of C must meet. Implementations are free to go above these minimum requirements.

This means that different implementations can have different sizes for the same type. For example a C compiler from the fictitious company ABC running on a 64-bit Intel processor might define an int to be 64 bits, while another C compiler from the fictitious XYZ organization for a 16-bit TI embedded processor might define an int to be 16 bits. They both meet the minimum requirements so both are valid.

The next sections look at C types in detail, starting with the smallest.

Boolean type

The _Bool keyword denotes a value that can hold either zero or one. If another numeric or pointer type is assigned to a boolean the value stored is 0 if the numeric or pointer value evaluates to 0, otherwise it is one. Let's see an example:

Sample Code
  1. #include <stdio.h>
  2.    
  3.     void main()
  4.     {
  5.            int a = 3944;
  6.            long b = -199020930;
  7.            double c = 7.534e-10;
  8.            double * d = &c;
  9.    
  10.           _Bool ba = a;
  11.           _Bool bb = b;
  12.           _Bool bc = c;
  13.           _Bool bd = d;
  14.           _Bool be = ( 1 == 2 );
  15.  
  16.           printf( "ba = %d\n", ba );
  17.           printf( "bb = %d\n", bb );
  18.           printf( "bc = %d\n", bc );
  19.           printf( "bd = %d\n", bd );
  20.           printf( "be = %d\n", be );
  21.   }
Copyright exforsys.com


The output of this program is:

ba = 1 bb = 1 bc = 1 bd = 1 be = 0

As you can see, any value that is not 0 is considered 1. On line 14 be is assigned to the value of the equality expression. Recall from the operators tutorial that relational operators return an int with the value 0 if false or 1 if true.

Integer types

C provides several standard integer types, from small magnitude to large magnitude numbers: char, short int, int, long int, long long int. Each type can be signed or unsigned. Signed types can represent positive and negative numbers while unsigned can represent zero and positive numbers. As mentioned above, the standard does not specify exact sizes for these types, and the only says that a larger type's range shall be at least as big as the smaller type. For example the range of an int variable is at least as big as the range of a short int.

C defines a minimum set of characters that need to be supported on a system where C programs are written and run (more on this in the next tutorial). Each character is given a numeric value such as A = 65, B = 66, etc. A char is an integer number big enough to at least hold the maximum value in this set, though in typical implementations it is bigger. C does not specify whether a plain 'char' refers to a signed or unsigned number - that is implementation defined. If you need to be sure your char variable is signed or unsigned, specify it in the declaration like this: unsigned char c.

The short int is a signed small integer. C allows abbreviated or longer names for the same type: short, signed short, signed short int. For the unsigned version use one of these: unsigned short, unsigned short int.

A signed integer may be declared as: int, signed, signed int. An unsigned integer may be declared as: unsigned, unsigned int.

A signed long int may be declared using one of these names: long, signed long, ,long int, signed long int. An unsigned version may be declared as: unsigned long, unsigned long int.

A signed long long can be declared like this: long long, singed long long, long long int, signed long long int. An unsigned can be declared as: unsigned long long, unsigned long long int.

This table defines the minimum ranges allowed for these integer types. An implementation is free to define these types to hold greater ranges than the ones given here.

Type

Minimum Value

Maximum Value

signed char

-127

127

unsigned char

0

255

short

-32767

32767

unsigned short

0

65535

int

-32767

32767

unsigned int

0

65535

long

-2147483647

2147483647

unsigned long

0

4294967295

signed long long

-9223372036854775807

9223372036854775807

unsigned long long

0

18446744073709551615

If you want to know the actual minimum and maximum values an implementation uses they are defined in the limits.h header file. It defines various constants like SCHAR_MIN, SCHAR_MAX, etc. that give the values for this implementation of C. The following example shows the limits of this implementation:

Sample Code
  1. #include <stdio.h>
  2.    #include <limits.h>
  3.    
  4.    void main()
  5.    {
  6.           printf("Signed char minimum value: %d\n", SCHAR_MIN );
  7.           printf("Signed char maximum value: %d\n", SCHAR_MAX );
  8.           printf("Unsigned char minimum value: %d\n", 0 );
  9.           printf("Unsigned char maximum value: %d\n", UCHAR_MAX );
  10.           printf("Char minimum value: %d\n", CHAR_MIN );
  11.           printf("Char maximum value: %d\n", CHAR_MAX );
  12.           printf("Signed short minimum value: %d\n", SHRT_MIN );
  13.           printf("Signed short maximum value: %d\n", SHRT_MAX );
  14.           printf("Unsigned short minimum value: %d\n", 0 );
  15.           printf("Unsigned short maximum value: %d\n", USHRT_MAX );
  16.           printf("Signed int minimum value: %d\n", INT_MIN );
  17.           printf("Signed int maximum value: %d\n", INT_MAX );
  18.           printf("Unsigned int minimum value: %u\n", 0 );
  19.           printf("Unsigned int maximum value: %u\n", UINT_MAX );
  20.           printf("Signed long minimum value: %ld\n", LONG_MIN );
  21.           printf("Signed long maximum value: %ld\n", LONG_MAX );
  22.           printf("Unsigned long minimum value: %lu\n", 0 );
  23.           printf("Unsigned long maximum value: %lu\n", ULONG_MAX );
  24.           printf("Signed long long minimum value: %lld\n", LLONG_MIN );
  25.           printf("Signed long long maximum value: %lld\n", LLONG_MAX );
  26.           printf("Unsigned long long minimum value: %lu\n", 0 );
  27.           printf("Unsigned long long maximum value: %llu\n", ULLONG_MAX );
  28.   }
Copyright exforsys.com


The output of this program is :

Signed char minimum value: -128 Signed char maximum value: 127 Unsigned char minimum value: 0 Unsigned char maximum value: 255 Char minimum value: -128 Char maximum value: 127 Signed short minimum value: -32768 Signed short maximum value: 32767 Unsigned short minimum value: 0 Unsigned short maximum value: 65535 Signed int minimum value: -2147483648 Signed int maximum value: 2147483647 Unsigned int minimum value: 0 Unsigned int maximum value: 4294967295 Signed long minimum value: -2147483648 Signed long maximum value: 2147483647 Unsigned long minimum value: 0 Unsigned long maximum value: 4294967295 Signed long long minimum value: -9223372036854775808 Signed long long maximum value: 9223372036854775807 Unsigned long long minimum value: 0 Unsigned long long maximum value: 18446744073709551615

As you can see this implementation keeps close to the minimums allowed except for ints. The output lines 5-6 for char types also shows that in this implementation chars are signed (otherwise the minimum and maximum values would be the same as for unsigned char).

An enumerated type is an integer type that allows you to give names to certain values. Here is an example of an enumeration:

Sample Code
  1. enum language { english, french, spanish = 4, german, chinese };
Copyright exforsys.com


This declares language as an integral type that can have one of 5 values. Each of the members of the enumeration are assigned an integer value. If a value is given, as for the spanish member above, that value is used; otherwise the value is 1 more than the previous member's value. For the first member if a value is not given it is assigned 0. Following these rules we can see that the values for the members would be english = 0, french = 1, spanish = 4, german = 5, chinese = 6.

Here is an example of how to use a variable of this enumerated type:

Sample Code
  1. enum language lang = spanish;
  2.  
  3. if ( lang == english )
  4.         printf( "I speak english\n" );
  5. else if ( lang == spanish )
  6.         printf( "Yo hablo espanol\n" );
  7. else
  8.         printf( "I don't speak that language\n" );
Copyright exforsys.com


This declares lang as having the enumeration type language and assigns it the spanish member of the enumeration. Then it compares lang with the english and spanish members of the enumeration to print the appropriate message.

Since the members of an enumerated type have integer values you can compare them to other numbers. But generally you want to avoid comparing them to hardcoded values like if ( lang == 5 ) to check for the german value because any change in the members of the type can possibly change their values. Suppose the language enumeration was changed to add a new russian value after the spanish value and before the german value. Now russian has the value 5, not german, so the statement if ( lang == 5 ) will be true for the wrong language.

The C standard does not define specific sizes for the integer types discussed so far. However, it does require the the implementation to define integer types that have at least a certain number of bits. It also allows an implementation to define integer types that have a specific size in bits. These types are defined in the stdint.h header file. The types int_leastN_t and uint_leastN_t define integer types that are at least N bits wide. For example int_least8_t defines a signed integer that is at least 8 bits, and a uint_least64_t defines an unsigned integer that is at least 64 bits. In addition, an implementation might provide intN_t and uintN_t types that a exactly N bits wide.

Ads

Sample Code
  1. #include <stdio.h>
  2.    #include <stdint.h>
  3.    
  4.    void main()
  5.    {
  6.            int_least8_t  l_eight;
  7.            uint32_t      thirtytwo;
  8.    
  9.            printf("l_eight is %d bytes\n", sizeof( l_eight ));
  10.           printf("thirtytwo is %d bytes\n", sizeof( thirtytwo ));
  11.   }
Copyright exforsys.com


l_eight is 1 bytes thirtytwo is 4 bytes

This shows that the int_least8_t type is 8 bits (1 byte) and thirtytwo is 32 bits (4 bytes).

In addition to all the types discussed above, an implementation may define its own integer types. Consult the implementation's documentation for details about these types.

Read Next: C Programming - Operators


 
This tutorial is part of a C Tutorials tutorial series. Read it from the beginning and learn yourself.

C Tutorials

 

Comments