Author: saqibkhan

  • Type Casting in C

    The term “type casting” refers to converting one datatype into another. It is also known as “type conversion”. There are certain times when the compiler does the conversion on its own (implicit type conversion), so that the data types are compatible with each other.

    On other occasions, the C compiler forcefully performs the typecasting (explicit type conversion), which is caused by the typecasting operator. For example, if you want to store a ‘long’ value into a simple integer then you can type cast ‘long’ to ‘int’.

    You can use the typecasting operator to explicitly convert the values from one type to another −

    (type_name) expression
    

    Example 1

    Consider the following example −

    #include <stdio.h>intmain(){int sum =17, count =5;double mean;
    
       mean =  sum / count;printf("Value of mean: %f\n", mean);}

    Output

    Run the code and check its output −

    Value of mean: 3.000000
    

    While we expect the result to be 17/5, that is 3.4, it shows 3.000000, because both the operands in the division expression are of int type.

    Example 2

    In C, the result of a division operation is always in the data type with a larger byte length. Hence, we have to typecast one of the integer operands to float.

    The cast operator causes the division of one integer variable by another to be performed as a floating-point operation −

    #include <stdio.h>intmain(){int sum =17, count =5;double mean;
    
       mean =(double) sum / count;printf("Value of mean: %f\n", mean);}

    Output

    When the above code is compiled and executed, it produces the following result −

    Value of mean: 3.400000
    

    It should be noted here that the cast operator has precedence over division, so the value of sum is first converted to type double and finally it gets divided by count yielding a double value.

    Type conversions can be implicit which is performed by the compiler automatically, or it can be specified explicitly through the use of the cast operator. It is considered good programming practice to use the cast operator whenever type conversions are necessary.

    Rules of Type Promotions

    While performing the implicit or automatic type conversions, the C compiler follows the rules of type promotions. Generally, the principle followed is as follows −

    • Byte and short values − They are promoted to int.
    • If one operand is a long − The entire expression is promoted to long.
    • If one operand is a float − The entire expression is promoted to float.
    • If any of the operands is double − The result is promoted to double.

    Integer Promotion in C

    Integer promotion is the process by which values of integer type “smaller” than int or unsigned int are converted either to int or unsigned int.

    Example

    Consider an example of adding a character with an integer −

    #include <stdio.h>intmain(){int i =17;char c ='c';/* ascii value is 99 */int sum;
    
       sum = i + c;printf("Value of sum : %d\n", sum);}

    Output

    When the above code is compiled and executed, it produces the following result −

    Value of sum: 116
    

    Here, the value of sum is 116 because the compiler is doing integer promotion and converting the value of ‘c’ to ASCII before performing the actual addition operation.

    Usual Arithmetic Conversion

    The usual arithmetic conversions are not performed for the assignment operators nor for the logical operators && and ||.

    Example

    Let us take the following example to understand the concept −

    #include <stdio.h>intmain(){int i =17;char c ='c';/* ascii value is 99 */float sum;
    
       sum = i + c;printf("Value of sum : %f\n", sum);}

    Output

    When the above code is compiled and executed, it produces the following result −

    Value of sum: 116.000000
    

    Here, it is simple to understand that first c gets converted to an integer, but as the final value is double, usual arithmetic conversion applies and the compiler converts i and c into ‘float’ and adds them yielding a ‘float’ result.

  • Type Conversion in C

    The C compiler attempts data type conversion, especially when dissimilar data types appear in an expression. There are certain times when the compiler does the conversion on its own (implicit type conversion) so that the data types are compatible with each other. On other occasions, the C compiler forcefully performs the conversion (explicit type conversion), which is carried out by the type cast operator.

    Implicit Type Conversion in C

    In C, implicit type conversion takes place automatically when the compiler converts the type of one value assigned to a variable to another data type. It typically happens when a type with smaller byte size is assigned to a “larger” data type. In such implicit data type conversion, the data integrity is preserved.

    While performing implicit or automatic type conversions, the C compiler follows the rules of type promotions. Generally, the principle followed is as follows −

    • Byte and short values: They are promoted to int.
    • If one operand is a long: The entire expression is promoted to long.
    • If one operand is a float: The entire expression is promoted to float.
    • If any of the operands is double: The result is promoted to double.

    Integer Promotion

    Integer promotion is the process by which values of integer type “smaller” than int or unsigned int are converted either to int or unsigned int.

    Example

    Consider an example of adding a character with an integer −

    #include <stdio.h>intmain(){int  i =17;char c ='c';/* ascii value is 99 */int sum;
       sum = i + c;printf("Value of sum: %d\n", sum);return0;}
    Output

    When you run this code, it will produce the following output −

    Value of sum: 116
    

    Here, the value of sum is 116 because the compiler is doing integer promotion and converting the value of “c” to ASCII before performing the actual addition operation.

    Usual Arithmetic Conversion

    Usual arithmetic conversions are implicitly performed to cast their values to a common type. The compiler first performs integer promotion; if the operands still have different types, then they are converted to the type that appears highest in the following hierarchy −

    Long Double

    Example

    Here is another example of implicit type conversion −

    #include <stdio.h>intmain(){char a ='A';float b = a +5.5;printf("%f", b);return0;}

    Output

    Run the code and check its output −

    70.500000
    

    When the above code runs, the char variable “a” (whose int equivalent value is 70) is promoted to float, as the other operand in the addition expression is a float.

    Explicit Type Conversion in C

    When you need to covert a data type with higher byte size to another data type having lower byte size, you need to specifically tell the compiler your intention. This is called explicit type conversion.

    C provides a typecast operator. You need to put the data type in parenthesis before the operand to be converted.

    type2 var2 =(type1) var1;

    Note that if type1 is smaller in length than type2, then you dont need such explicit casting. It is only when type1 is greater in length than type2 that you should use the typecast operator.

    Typecasting is required when we want to demote a greater data type variable to a comparatively smaller one or convert it between unrelated types like float to int.

    Example

    Consider the following code −

    #include <stdio.h>intmain(){int x =10, y =4;float z = x/y;printf("%f", z);return0;}

    Output

    On running this code, you will get the following output −

    2.000000
    

    While we expect the result to be 10/4 (that is, 2.5), it shows 2.000000. It is because both the operands in the division expression are of int type. In C, the result of a division operation is always in the data type with larger byte length. Hence, we have to typecast one of the integer operands to float, as shown below −

    Example

    Take a look at this example −

    #include <stdio.h>intmain(){int x =10, y =4;float z =(float)x/y;printf("%f", z);return0;}

    Output

    Run the code and check its output −

    2.500000
    

    If we change the expression such that the division itself is cast to float, the result will be different.

    Typecasting Functions in C

    The standard C library includes a number of functions that perform typecasting. Some of the functions are explained here −

    The atoi() Function

    The atoi() function converts a string of characters to an integer value. The function is declared in the stdlib.h header file.

    Example

    The following code uses the atoi() function to convert the string “123” to a number 123 −

    #include <stdio.h>#include <stdlib.h>intmain(){char str[]="123";int num =atoi(str);printf("%d\n", num);return0;}
    Output

    Run the code and check its output −

    123
    

    The itoa() Function

    You can use the itoa() function to convert an integer to a null terminated string of characters. The function is declared in the stdlib.h header file.

    Example

    The following code uses itoa() function to convert an integer 123 to string “123” −

    #include <stdio.h>#include <stdlib.h>intmain(){int num =123;char str[10];itoa(num,str,10);printf("%s\n", str);return0;}
    Output

    Run the code and check its output −

    123
    

    Other examples of using typecasting include the following −

    The malloc() Function − The malloc() function is a dynamic memory allocation function.

    Int *ptr =(int*)malloc(n *sizeof(int));

    In function arguments and return values − You can apply the typecast operator to formal arguments or to the return value of a user-defined function.

    Example

    Here is an example −

    #include <stdio.h>#include <stdlib.h>floatdivide(int,int);intmain(){int x =10, y =4;float z =divide(x, y);printf("%f", z);return0;}floatdivide(int a,int b){return(float)a/b;}
    Output

    When you run this code, it will produce the following output −

    2.500000 
    

    Employing implicit or explicit type conversion in C helps in type safety and improved code readability, but it may also lead to loss of precision and its complicated syntax may be confusing.

  • Character Arithmetic

    In C, character arithmetic means performing arithmetic operations like addition, subtraction, multiplication, and division on characters. Characters in C are stored as numbers using the ASCII system.

    The ASCII system represents each character, digit, or symbol using numbers. For example, ‘A’ is stored as 65, ‘B’ as 66, ‘a’ as 97, and so on

    Character Arithmetic Operations

    To perform arithmetic operations on a character, we should know that a character takes 1 byte of memory. A signed char has a range from -128 to 127, and an unsigned char has a range from 0 to 255.

    Checking Character Values

    Let’s first see a character and its ASCII value. In the below example, we print the character ‘A‘ using %c and its ASCII value using %d.

    #include <stdio.h>intmain(){char ch ='A';printf("Character: %c\n", ch);printf("ASCII Value: %d\n", ch);return0;}

    After running the program, we can see the character and its ASCII value-

    Character: A
    ASCII Value: 65
    

    Adding Two Characters

    We can add characters just like numbers because each character is stored as a number.

    #include <stdio.h>intmain(){char a ='A';char b ='B';printf("a = %c\n", a);printf("b = %c\n", b);printf("a + b = %c\n", a + b);printf("a + b (as number) = %d\n", a + b);return0;}

    Here’s the output of the above program after adding the characters –

    a = A
    b = B
    a + b = â
    a + b (as number) = 131
    

    In this program, the characters and b are declared and assigned with values ‘A‘ and ‘B‘. When we add a and b, the result is the character Ã¢. The ASCII value of A is 65 and B is 66, so adding them gives 65 + 66 = 131. The character with ASCII value 131 is Ã¢.

    Shifting and Subtracting Characters

    We can shift a character forward or backward by adding or subtracting a number. For example, ‘A’ + 1 gives ‘B’ and ‘C’ – 1 gives ‘B’. We can also find the difference between characters using subtraction, like ‘C’ – ‘A’, which gives 2 because the ASCII value of ‘C’ is 67 and ‘A’ is 65, so 67 – 65 = 2.

    #include <stdio.h>intmain(){char c1 ='A'+1;char c2 ='C'-1;int diff ='C'-'A';printf("A + 1 = %c\n", c1);printf("C - 1 = %c\n", c2);printf("C - A = %d\n", diff);return0;}

    Here’s the output of the program after shifting and subtracting the characters –

    A + 1 = B
    C - 1 = B
    C - A = 2
    

    Comparing Two Characters

    We can compare characters directly using comparison operators like <><=>=, ==, and != to check the order or equality of characters. In the program below, we check if the character ‘a’ comes before ‘z’. Since the ASCII value of ‘a’ is 97 and ‘z’ is 122, so ‘a’ < ‘z’ is true.

    #include <stdio.h>intmain(){if('a'<'z'){printf("'a' comes before 'z'\n");}return0;}

    Here’s the output that shows which character comes first.

    'a' comes before 'z'
    

    Increment and Decrement Operators on Characters

    Characters in C can be incremented (++) or decremented () like numbers. Incrementing moves a character forward in the ASCII table, and decrementing moves it backward. In the below program, chracter ch starts as ‘A‘. After ch++, it becomes ‘B‘, and after ch– it becomes ‘A‘ again.

    #include <stdio.h>intmain(){char ch ='A';printf("Original character: %c\n", ch);
    
    
    ch++;// Incrementprintf("After increment: %c\n", ch);
    ch--;// Decrementprintf("After decrement: %c\n", ch);return0;}</code></pre>

    Following is the output of the above program-

    Original character: A
    After increment: B
    After decrement: A
    

    Converting to Uppercase and Lowercase

    In ASCII, the difference between uppercase and lowercase letters is 32. To convert an uppercase letter to lowercase, we add 32 to it. For example, 'M' + 32 becomes 'm'. Similarly, to convert a lowercase letter to uppercase, we subtract 32 from it. For example, 'm' - 32 becomes 'M'.

    #include <stdio.h>intmain(){char upper ='M';char lower = upper +32;// Convert uppercase to lowercasechar small ='m';char capital = small -32;// Convert lowercase to uppercaseprintf("Original Uppercase: %c\n", upper);printf("Converted to Lowercase: %c\n", lower);printf("Original Lowercase: %c\n", small);printf("Converted to Uppercase: %c\n", capital);return0;}

    Here is the output of the above program that shows the original characters and their converted form.

    Original Uppercase: M
    Converted to Lowercase: m
    Original Lowercase: m
    Converted to Uppercase: M
    

    In this chapter, we covered how to perform different types of arithmetic operations on characters in C. It is possible to perform such arithmetic operations on characters directly because the computer stores each character as a number, which allows us to add, subtract, compare and so on.

  • Integer Promotions in C

    The C compiler promotes certain data types to a higher rank for the sake of achieving consistency in the arithmetic operations of integers.

    In addition to the standard int data type, the C language lets you work with its subtypes such as char, short int, long int, etc. Each of these data types occupy a different amount of memory space. For example, the size of a standard int is 4 bytes, whereas a char type is 2 bytes of length. When an arithmetic operation involves integer data types of unequal length, the compiler employs the policy of integer promotion.

    Integer Promotions

    As a general principle, the integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int.

    One must understand the concept of integer promotion to write reliable C code, and avoid unexpected problems related to the size of data types and arithmetic operations on smaller integer types.

    Example

    In this example, the two variables a and b seem to be storing the same value, but they are not equal.

    #include <stdio.h>intmain(){char a =251;unsignedchar b = a;printf("a = %c", a);printf("\nb = %c", b);if(a == b)printf("\n Same");elseprintf("\n Not Same");return0;}

    Output

    When you run this code, it will produce the following output −

    a = 
    b = 
    Not Same
    

    You get this output because “a” and “b” are treated as integers during comparison. “a” is a signed char converted to int as -5, while “b” is an unsigned char converted to int as 251.

    Example: Mechanism of Integer Promotions

    Let us try to understand the mechanism of integer promotions with this example −

    #include <stdio.h>intmain(){char a ='e', b ='2', c ='M';char d =(a * b)/ c;printf("d as int: %d as char: %c", d, d);return0;}

    Output

    Run the code and check its output −

    d as int: 65 as char: A
    

    When Integer Promotion is Applied?

    In the arithmetic expression “(a * b) / c”, the bracket is solved first. All the variables are of signed char type, which is of 2 byte length and can store integers between -128 to 127. Hence the multiplication goes beyond the range of char but the compiler doesn’t report any error.

    The C compiler applies integer promotion when it deals with arithmetic operations involving small types like char. Before the multiplication of these char types, the compiler changes them to int type. So, in this case, (a * b) gets converted to int, which can accommodate the result of multiplication, i.e., 1200.

    Example

    Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators. Take a look at the following example −

    #include <stdio.h>intmain(){char a =10;int b = a >>3;printf("b as int: %d as char: %c", b, b);return0;}

    Output

    When you run this code, it will produce the following output −

    b as int: 1 as char: 
    

    In the above example, shifting the bit structure of “a” to the left by three bits still results in its value within the range of char (a << 3 results in 80).

    Example

    In this example, the rank of the char variable is prompted to int so that its left shift operation goes beyond the range of char type.

    #include <stdio.h>intmain(){char a =50;int b = a <<2;printf("b as int: %d as char: %c", b, b);return0;}

    Output

    Run the code and check its output −

    b as int: 200 as char: 
    

    Integer Promotion Rules

    Promotion rules help the C compiler in maintaining consistency and avoiding unexpected results. The fundamental principle behind the rules of promotion is to ensure that the expression’s type is adjusted to accommodate the widest data type involved, preventing data loss or truncation.

    Here is a summary of promotion rules as per C11 specifications −

    • The integer types in C are char, short, int, long, long long and enum. Booleans are also treated as an integer type when it comes to type promotions.
    • No two signed integer types shall have the same rank, even if they have the same representation.
    • The rank of a signed integer type shall be greater than the rank of any signed integer type with less precision.
    • The rank of long int > the rank of int > the rank of short int > the rank of signed char.
    • The rank of char is equal to the rank of signed char and unsigned char.
    • Whenever a small integer type is used in an expression, it is implicitly converted to int which is always signed.
    • All small integer types, irrespective of sign, are implicitly converted to (signed) int when used in most expressions.

    In short, we have the following integer promotion rules −

    • Byte and short values − They are promoted to int.
    • If one operand is a long − The entire expression is promoted to long.
    • If one operand is a float − The entire expression is promoted to float.
    • If any of the operands is double − The result is promoted to double.

    Example

    Here, the variables x and y are of char data type. When the division operation is performed on them, they automatically get promoted to int and the resultant value is stored in z.

    #include <stdio.h> intmain(){char x =68;char y =34;printf("The value of x is: %d", x);printf("\nThe value of y is: %d", y);char z = x/y;printf("\nThe value of z: %d", z);return0;}

    Output

    When you run this code, it will produce the following output −

    The value of x is: 68
    The value of y is: 34
    The value of z: 2
    
  • Booleans in C

    Unlike the intchar or float types, the ANSI C standard doesnt have a built-in or primary Boolean type. A Boolean or bool data generally refers to the one that can hold one of the two binary values: true or false (or yes/no, on/off, etc.). Even if the bool type is not available in C, you can implement the behaviour of Booleans with the help of an enum type.

    The new versions of C compilers, complying with the C99 standard or later, support the bool type, which has been defined in the header file stdbool.h.

    Using enum to Implement Boolean Type in C

    The enum type assigns user-defined identifiers to integral constants. We can define an enumerated type with true and false as the identifiers with the values 1 and 0.

    Example

    1 or any other number that is not 0 represents true, whereas 0 represents false.

    #include <stdio.h>intmain(){enumbool{false, true};enumbool x = true;enumbool y = false;printf("%d\n", x);printf("%d\n", y);}

    Output

    Run the code and check its output −

    1
    0
    

    typedef enum as BOOL

    To make it more concise, we can use the typedef keyword to call enum bool by the name BOOL.

    Example 1

    Take a look at the following example −

    #include <stdio.h>intmain(){typedefenum{false, true} BOOL;
    
       BOOL x = true;
       BOOL y  = false;printf("%d\n", x);printf("%d\n", y);}

    Here too, you will get the same output −

    Output

    1
    0
    

    Example 2

    We can even use the enumerated constants in the decision-making or loop statements −

    #include <stdio.h>intmain(){typedefenum{false, true} BOOL;int i =0;while(true){
    
      i++;printf("%d\n", i);if(i &gt;=5)break;}return0;}</code></pre>

    Output

    When you run this code, it will produce the following output −

    1
    2
    3
    4
    5
    

    Boolean Values with #define

    The #define preprocessor directive is used to define constants. We can use this to define the Boolean constants, FALSE as 0 and TRUE as 1.

    Example

    Take a look at the following example −

    #include <stdio.h>#define FALSE 0#define TRUE 1intmain(){printf("False: %d \n True: %d", FALSE, TRUE);return0;}

    Output

    Run the code and check its output −

    False: 0 
     True: 1
    

    Boolean Type in stdbool.h

    The C99 standard of C has introduced the stdbool.h header file. It contains the definition of bool type, which actually is a typedef alias for _bool type. It also defines the macros true which expands to 1, and false which expands to 0.

    Example 1

    We can use the bool type as follows −

    #include <stdio.h>#include <stdbool.h>intmain(){
    
       bool a = true;
       bool b = false;printf("True: %d\n", a);printf("False: %d", b);return0;}

    Output

    On executing this code, you will get the following output −

    True: 1
    False: 0
    

    Example 2

    We can use bool type variables in logical expressions too, as shown in the following example −

    #include <stdio.h>#include <stdbool.h>intmain(){
      
       bool x;
       x =10>5;if(x)printf("x is True\n");elseprintf("x is False\n");
    
    bool y;int marks =40; y = marks >50;if(y)printf("Result: Pass\n");elseprintf("Result: Fail\n");}

    Output

    Run the code and check its output −

    x is True
    Result: Fail
    

    Example 3

    Let us implement a while loop with the help of a bool variable −

    #include <stdio.h>#include <stdlib.h>#include <stdbool.h>intmain(void){
    
       bool loop = true;int i =0;while(loop){
    
      i++;printf("i: %d \n", i);if(i &gt;=5)
         loop = false;}printf("Loop stopped!\n");return EXIT_SUCCESS;}</code></pre>

    Output

    When you run this code, it will produce the following output −

    i: 1
    i: 2
    i: 3
    i: 4
    i: 5
    Loop stopped!
    
  • Escape Sequence in C

    Escape Sequence in C

    An escape sequence in C is a literal made up of more than one character put inside single quotes. Normally, a character literal consists of only a single character inside single quotes. However, the escape sequence attaches a special meaning to the character that appears after a backslash character (\).

    The \ symbol causes the compiler to escape out of the string and provide meaning attached to the character following it.

    Look at \n as an example. When put inside a string, the \n acts as a newline character, generating the effect of pressing the Enter key. The following statement −

    printf(" Hello \n World ");

    Will produce this output −

    Hello
    World
    

    The new line is an unprintable character. The \n escape sequence is useful to generate its effect. Similarly, the escape sequence \t is equivalent to pressing the Tab key on the keyboard.

    An escape sequence is a sequence of characters that does not represent itself when used inside a character or string literal but is translated into another character or a sequence of characters that may be difficult or impossible to represent directly.

    All Escape Sequences in C

    In C, all escape sequences consist of two or more characters, the first of which is the backslash \ (called the “Escape character”); the remaining characters have an interpretation of the escape sequence as per the following table.

    Here is a list of escape sequences available in C −

    Escape sequenceMeaning
    \\\ character
    \’‘ character
    \”” character
    \?? character
    \aAlert or bell
    \bBackspace
    \fForm feed
    \nNewline
    \rCarriage return
    \tHorizontal tab
    \vVertical tab
    \oooOctal number of one to three digits
    \xhh . . .Hexadecimal number of one or more digits

    Let us understand how these escape sequences work with the help of a set of examples.

    Newline Escape Sequence (\n)

    The newline character, represented by the escape sequence \n in C, is used to insert the effect of carriage return on the output screen. You would use this escape sequence to print text in separate lines and improve the readability of output.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("Hello.\nGood morning.\nMy name is Ravi");}
    Output

    On running this code, you will get the following output −

    Hello.
    Good morning.
    My name is Ravi
    

    Tab Escape Sequence (\t)

    The tab character (\t) represents the Tab key on the keyboard. When the tab character is encountered in a string, it causes the cursor to move to the next horizontal tab stop. Horizontal tab stops are usually set at intervals of eight characters.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("Name:\tRavi\tMarks:\t50");}
    Output

    Run the code and check its output −

    Name:   Ravi    Marks:  50
    

    Backslash Escape Sequence (\\)

    To add backslash character itself as a part of a string, it must precede by another backslash. First backslash escapes out of the string, and the second one takes the effect.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("Directory in Windows: C:\\users\\user");}
    Output

    On running this code, you will get the following output −

    Directory in Windows: C:\users\user
    

    Double and Single Quotes Escape Sequences (\” and \’)

    These characters have a special meaning in C since ” and ‘ symbols are used for the representation of a character literal and a string literal respectively. Hence, to treat these characters as a part of the string, they must be escaped with an additional backslash preceding them.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("Welcome to \"TutorialsPoint\"\n");printf("\'Welcome\' to TutorialsPoint");}
    Output

    Run the code and check its output −

    Welcome to "TutorialsPoint"
    'Welcome' to TutorialsPoint
    

    Backspace Escape Sequence (\b)

    The escape sequence “\b”, represents the backspace character. It is used erase a character or a specific portion of a text that has already been printed on the screen.

    Example

    Check the following example code −

    #include <stdio.h>intmain(){printf("Welcome to\b TutorialsPoint");}
    Output

    Run the code and check its output −

    Welcome t TutorialsPoint
    

    Note that o from to has been erased.

    C also has a \r escape sequence. The newline escape sequence (\n) moves the cursor to the beginning of the next line, while the carriage return escape sequence (\r) moves the cursor to the beginning of the current line.

    Octal Number Escape Sequence (\ooo)

    This escape sequence is used for Octal numbers of one to three digits. An octal escape sequence is a backslash followed by one, two, or three octal digits (0-7). It matches a character in the target sequence with the value specified by those digits.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("%c",'\141');return0;}
    Output

    When you run this code, it will produce the following output −

    a
    

    Hexadecimal Number Escape Sequence (\xhh)

    A hexadecimal escape sequence is a backslash followed by the letter “x” followed by two hexadecimal digits (0-9a-fA-F). It matches a character in the target sequence with the value specified by the two digits.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("%c",'\x41');return0;}
    Output

    Here, you will get the following output −

    A
    

    Alert or Bell Number Escape Sequence (\a)

    The escape sequence \a represents the alert or bell character. When executed, it produces a sound or visual alert depending on the terminal or console being used.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){printf("Hello \a world\n");return0;}
    Output

    Run the code and check its output −

    Hello  world
    

    Escape sequences are used widely in many other programming languages such as Java, PHP, C#, etc.

  • Literals

    The term “literal” in computer programming terminology refers to a textual representation of a value to be assigned to a variable.

    In C, you can assign a value to a variable in two ways −

    • Using literal representation
    • Using an expression

    The initialization of a variable in C is done as follows −

    int x =10;

    On the other hand, an indirect initialization of a variable by assigning it the result of an expression is as follows −

    int x =10;int y = x*2;

    In the first case, 10 is an integer literal assigned to “x”. In the second case, the result of “x*2” expression is assigned to “y”.

    A literal is thus a value of a certain data type represented directly into the source code. Normally, literals are used to set a value of a variable.

    On their own, literals dont form any of the programming element. Different notations are used to represent the values of different data types.

    Integer Literals in C

    In the above example, 10 is an integer literal. A positive or negative whole number represented with digits 0 to 9, without a fractional part is a decimal integer literal. It must be within the acceptable range for the given OS platform.

    Following examples assign decimal literals to int variables −

    int x =200;int y =-50;

    An integer literal can also have a suffix that is a combination of “U” and “L”, for “unsigned” and “long”, respectively. The suffix can be uppercase or lowercase and can be in any order.

    int c =89U;longint d =99998L;

    C allows you to represent an integer in octal and hexadecimal number systems. For a literal representation of an octal, prefix the number with 0 (ensure that the number uses octal digits only, from 0 to 7).

    For a hexadecimal literal, prefix the number with 0x or 0X. The hexadecimal number must have 0 to 9, and A to F (or a to f) symbols.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){int oct =025;int hex =0xa1;printf("Octal to decimal: %d\n", oct);printf("Hexadecimal to decimal: %d\n", hex);}

    Output

    On running this code, you will get the following output −

    Octal to decimal: 21
    Hexadecimal to decimal: 161
    

    Modern C compilers also let you represent an integer as a binary number, for which you need to add a 0b prefix.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){int x =0b00010000;printf("binary to decimal: %d", x);}

    Output

    Run the code and check its output −

    binary to decimal: 16
    

    Here are some examples of integer literals −

    212/* valid */215u/* valid */0xFeeL/* valid */078/* invalid: 8 is not an octal digit */032UU/* invalid: cannot repeat a suffix */

    Here are some other examples of various types of integer literals −

    85/* decimal */0213/* octal */0x4b/* hexadecimal */30/* int */30u/* unsigned int */30l/* long */30ul/* unsigned long */

    Floating-point Literals in C

    A floating-point literal in C is a real number with an integer part and a fractional part within the range acceptable to the compiler in use, and represented in digits, decimal point with an optional exponent symbol (e or E).

    A floating point literal is generally used for initializing or setting the value of a float or a double variable in C.

    Example

    The following assignment examples use floating point literals with a decimal point separating the integer and the fractional part −

    #include <stdio.h>intmain(){float x =10.55;float y =-1.333;printf("x and y are: %f, %f", x, y);}

    Output

    You will get the following output −

    x and y are: 10.550000, -1.333000
    

    Floating point literals with a high degree of precision can be stated with the exponentiation symbol “e” or “E”. This is called the scientific notation of a float literal.

    While representing decimal form, you must include the decimal point, the exponent, or both. While representing exponential form, you must include the integer part, the fractional part, or both.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){float x =100E+4;float y =-1.3E-03;printf("x: %f\n", x);printf("y: %f\n", y);}

    Output

    When you run this code, it will produce the following output −

    x: 1000000.000000
    y: -0.001300
    

    Here are some examples of floating-point literals −

    3.14159/* valid */314159E-5L/* valid */510E        /* invalid: incomplete exponent */210f/* invalid: no decimal or exponent */.e55        /* invalid: missing integer or fraction */

    Character Literals in C

    A character literal in C is a single character enclosed within single quote symbols. Note that C recognizes straight quotes only. Hence, use  to form a character literal and not ). Here is an example −

    char x ='I';

    Character literals are generally assigned to a char variable that occupies a single byte. Using the %c format specifier outputs the character. Use %d and youll obtain the ASCII value of the character.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){char x ='I';printf("x: %c\n", x);printf("x: %d\n", x);}

    Output

    Run the code and check its output −

    x: I
    x: 73
    

    Escape Sequences in C

    C defines a number of escape sequences as a sequence of characters starting with “\” and an alternate meaning attached to the following characters.

    Even though an escape sequence consists of more than one characters, it is put inside single quotes. An escape sequence produces the effect of a single non-printable character. For example, ‘\n’ is an escape sequence that represents a newline character, with the same effect as pressing the Enter key.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){char x ='I';char y ='J';printf("x: %c\ny: %c", x,y);}

    Output

    Here you will get this output −

    x: I
    y: J 
    

    We shall learn more about escape sequences in a later chapter.

    A character literal can also be a UNICODE representation of a character. Such a literal has /u at the beginning.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){char x ='\u09A9';printf("x: %c\n", x);printf("x: %d\n", x);}

    Output

    On running this code, you will get the following output −

    x: 
    y: -87
    

    String Literals in C

    A sequence of characters put inside double quotation symbols forms a string literal. C doesnt provide a string variable. Instead, we need to use an array of char type to store a string.

    Example

    Take a look at the following example −

    #include <stdio.h>intmain(){char arr[]="Hello World";printf("arr: %s", arr);}

    Output

    Run the code and check its output −

    arr: Hello World
    

    A string literal may contain plain characters, escape sequences, and Unicode characters. For example −

    char arr[]="Hello \
    World";

    You can also have a literal representation of an array by putting its elements inside the curly brackets { and }. For example:

    int arr[]={10,20,30,40};

    Similarly, the curly brackets can also be used for a literal representation of a struct value. For example −

    structmarks{int phy;int che;int math
    };structmarks m1 ={50,60,70};

    We shall learn about arrays and structures in detail later in this tutorial.

  • Data Types

    Data types in C refer to an extensive system used for declaring variables or functions of different types. The type of a variable determines how much space it occupies in storage and how the bit pattern stored is interpreted. In this chapter, we will learn about data types in C. A related concept is that of “variables”, which refer to the addressable location in the memory of the processor. The data captured via different input devices is stored in the computer memory. A symbolic name can be assigned to the storage location called variable name.

    C is a statically typed language. The name of the variable along with the type of data it intends to store must be explicitly declared before actually using it.

    C is also a strongly typed language, which means that the automatic or implicit conversion of one data type to another is not allowed.

    The types in C can be classified as follows −

    Sr.No.Types & Description
    1Basic TypesThey are arithmetic types and are further classified into: (a) integer types and (b) floating-point types.
    2Enumerated typesThey are again arithmetic types and they are used to define variables that can only assign certain discrete integer values throughout the program.
    3The type voidThe type specifier void indicates that no value is available.
    4Derived typesThey include (a) Pointer types, (b) Array types, (c) Structure types, (d) Union types and (e) Function types.

    The array types and structure types are referred collectively as the aggregate types. The type of a function specifies the type of the function’s return value. We will see the basic types in the following section, where as other types will be covered in the upcoming chapters.

    Integer Data Types in C

    The following table provides the details of standard integer types with their storage sizes and value ranges −

    TypeStorage sizeValue range
    char1 byte-128 to 127 or 0 to 255
    unsigned char1 byte0 to 255
    signed char1 byte-128 to 127
    int2 or 4 bytes-32,768 to 32,767 or -2,147,483,648 to 2,147,483,647
    unsigned int2 or 4 bytes0 to 65,535 or 0 to 4,294,967,295
    short2 bytes-32,768 to 32,767
    unsigned short2 bytes0 to 65,535
    long8 bytes-9223372036854775808 to 9223372036854775807
    unsigned long8 bytes0 to 18446744073709551615

    To get the exact size of a type or a variable on a particular platform, you can use the sizeof operator. The expressions sizeof(type) yields the storage size of the object or type in bytes.

    Example of Integer Data Types

    Given below is an example to get the size of various type on a machine using different constant defined in limits.h header file −

    #include <stdio.h>#include <stdlib.h>#include <limits.h>#include <float.h>intmain(int argc,char** argv){printf("CHAR_BIT    :   %d\n", CHAR_BIT);printf("CHAR_MAX    :   %d\n", CHAR_MAX);printf("CHAR_MIN    :   %d\n", CHAR_MIN);printf("INT_MAX     :   %d\n", INT_MAX);printf("INT_MIN     :   %d\n", INT_MIN);printf("LONG_MAX    :   %ld\n",(long) LONG_MAX);printf("LONG_MIN    :   %ld\n",(long) LONG_MIN);printf("SCHAR_MAX   :   %d\n", SCHAR_MAX);printf("SCHAR_MIN   :   %d\n", SCHAR_MIN);printf("SHRT_MAX    :   %d\n", SHRT_MAX);printf("SHRT_MIN    :   %d\n", SHRT_MIN);printf("UCHAR_MAX   :   %d\n", UCHAR_MAX);printf("UINT_MAX    :   %u\n",(unsignedint) UINT_MAX);printf("ULONG_MAX   :   %lu\n",(unsignedlong) ULONG_MAX);printf("USHRT_MAX   :   %d\n",(unsignedshort) USHRT_MAX);return0;}

    Output

    When you compile and execute the above program, it produces the following result on Linux−

    CHAR_BIT    :   8
    CHAR_MAX    :   127
    CHAR_MIN    :   -128
    INT_MAX     :   2147483647
    INT_MIN     :   -2147483648
    LONG_MAX    :   9223372036854775807
    LONG_MIN    :   -9223372036854775808
    SCHAR_MAX   :   127
    SCHAR_MIN   :   -128
    SHRT_MAX    :   32767
    SHRT_MIN    :   -32768
    UCHAR_MAX   :   255
    UINT_MAX    :   4294967295
    ULONG_MAX   :   18446744073709551615
    USHRT_MAX   :   65535
    

    Floating-Point Data Types in C

    The following table provides the details of standard floating-point types with storage sizes and value ranges and their precision −

    TypeStorage sizeValue rangePrecision
    float4 byte1.2E-38 to 3.4E+386 decimal places
    double8 byte2.3E-308 to 1.7E+30815 decimal places
    long double10 byte3.4E-4932 to 1.1E+493219 decimal places

    The header file “float.h” defines the macros that allow you to use these values and other details about the binary representation of real numbers in your programs.

    Example Floating-Point Data Types

    The following example prints the storage space taken by a float type and its range values −

    #include <stdio.h>#include <stdlib.h>#include <limits.h>#include <float.h>intmain(int argc,char** argv){printf("Storage size for float : %zu \n",sizeof(float));printf("FLT_MAX     :   %g\n",(float) FLT_MAX);printf("FLT_MIN     :   %g\n",(float) FLT_MIN);printf("-FLT_MAX    :   %g\n",(float)-FLT_MAX);printf("-FLT_MIN    :   %g\n",(float)-FLT_MIN);printf("DBL_MAX     :   %g\n",(double) DBL_MAX);printf("DBL_MIN     :   %g\n",(double) DBL_MIN);printf("-DBL_MAX     :  %g\n",(double)-DBL_MAX);printf("Precision value: %d\n", FLT_DIG );return0;}

    Output

    When you compile and execute the above program, it produces the following result on Linux −

    Storage size for float : 4 
    FLT_MAX      :   3.40282e+38
    FLT_MIN      :   1.17549e-38
    -FLT_MAX     :   -3.40282e+38
    -FLT_MIN     :   -1.17549e-38
    DBL_MAX      :   1.79769e+308
    DBL_MIN      :   2.22507e-308
    -DBL_MAX     :  -1.79769e+308
    Precision value: 6
    

    Note: “sizeof” returns “size_t”. The type of unsigned integer of “size_t” can vary depending on platform. And, it may not be long unsigned int everywhere. In such cases, we use “%zu” for the format string instead of “%d”.

    Earlier versions of C did not have Boolean data type. C99 standardization of ANSI C introduced _bool type which treats zero value as false and non-zero as true.

    User-defined Data Types in C

    There are two user-defined data types struct and union, that can be defined by the user with the help of the combination of other basic data types.

    Struct Data Type

    One of the unique features of C language is to store values of different data types in one variable. The keywords struct and union are provided to derive a user-defined data type. For example,

    structstudent{char name[20];int marks, age;};

    Union Data Type

    A union is a special case of struct where the size of union variable is not the sum of sizes of individual elements, as in struct, but it corresponds to the largest size among individual elements. Hence, only one of elements can be used at a time. Look at following example:

    union ab  {int a;float b;};

    We shall learn more about structure and union types in a later chapter.

    The void Data Type in C

    The void type specifies that no value is available. It is used in three kinds of situations −

    Sr.NoTypes & Description
    1Function returns as voidThere are various functions in C that do not return any value or you can say they return void. A function with no return value has the return type as void. For example, void exit (int status);
    2Function arguments as voidThere are various functions in C which do not accept any parameter. A function with no parameter can accept a void. For example, int rand(void);
    3Pointers to voidA pointer of type void * represents the address of an object, but not its type. For example, a memory allocation function void *malloc( size_t size ); returns a pointer to void which can be casted to any data type.

    Arrays Data Type in C

    An array is a collection of multiple values of same data type stored in consecutive memory locations. The size of array is mentioned in square brackets []. For example,

    int marks[5];

    Arrays can be initialized at the time of declaration. The values to be assigned are put in parentheses.

    int marks[]={50,56,76,67,43};

    C also supports multi-dimensional arrays. To learn more about arrays, refer to the chapter on Arrays in C.

    Pointers Data Type in C

    A pointer is a special variable that stores address or reference of another variable/object in the memory. The name of pointer variable is prefixed by asterisk (*). The type of the pointer variable and the variable/object to be pointed must be same.

    int x;int*y;  
    y =&x;

    Here, “y” is a pointer variable that stores the address of variable “x” which is of “int” type.

    Pointers are used for many different purposes. Text string manipulation and dynamic memory allocation are some of the processes where the use of pointers is mandatory. Later in this tutorial, you can find a detailed chapter on Pointers in C.

  • Internal and External Linkage

    In C, linkage is a concept that explains whether or not names or identifiers can refer to the same entity throughout the entire program or a single translation unit. It may sound similar to program scope but it is not so. To understand this concept better, let us dig deeper into the compilation process.

    Before learning the concept of linkage in C, we first need to understand what a translation unit is.

    What is a Translation Unit?

    A translation unit is a file that has source code, header files, and other dependencies. All of these sources are grouped together to form a single translation unit which can then be used by the compiler to produce one single executable objects.

    What is Linkage?

    Assume there is a C program with many source code files. Each source file is compiled sequentially. In the compilation process, the last stage is linking, where multiple machine code files are used to produce an executable object code. It is handled by a program called linker.

    Linkage is a property that describes how variables should be linked by the linker.

    Variable Linkage in C

    In C, the linkage can control whether a variable can be used only in the file where it is declared or it can also be used in other files of the program.

    Linkage tells us if a variable’s name is limited to one file or can be shared across multiple files, helping us manage how variables are connected in a program.

    Types of Linkage in C

    There are two types of Linkage in C −

    • Internal Linkage
    • External Linkage

    Let’s understand these two concepts in detail.

    Internal Linkage

    Internal linkage refers to everything only in the scope of a translation unit. An identifier that implements internal linkage is not accessible outside the translation unit in which it is declared. So, an identifier with internal linkage can be accessed only within the same file where it is declared.

    Internal Linkage is implemented using the static keyword, and its value is stored in RAM (either in the initialized or uninitialized).

    Let’s understand it through the following example. Let’s consider a source file items.c (identifier) −

    #include <stdio.h>// Variable with internal linkage
    Static int items =10;

    The above code implements static linkage on identifier items.

    Let’s consider another source file display.c which is located in the same translation unit.

    #include <stdio.h>#include "items.c"intmain(){printf("total item is: %d", items);return0;}

    Following is the output of the above code after executing the display.c −

    total item is: 10
    

    Suppose display.c is located in a different translation unit (meaning we are not including the items.c using #include). Then it gives the error “Each undeclared identifier is reported only once for each function it appears in.”

    External Linkage

    An identifier implementing external linkage exists beyond a particular translation unit and is accessible throughout the entire program, which is the combination of all translation units (or object files). It is the default linkage for globally scoped variables (without static) and functions.

    The extern keyword is used to implement external linkage. When we use the ‘extern’ keyword, we tell the compiler that the variable is defined in another file. Thus, the declaration of an external identifier doesn’t use any memory space.

    Extern identifiers are stored in RAM’s data (initialized/uninitialized) or code (text) segments.

    Let’s take an example to understand the concept better. Consider a source file: items.c (identifier). In the internal linkage we used the static keyword; here we create a source file without the extern keyword.

    #include <stdio.h>// Variable with internal linkageint items =10;

    As the variable items is declared globally, it is accessible to all the translational units. Now, consider the file display.c is in the different translational unit −

    #include <stdio.h>// tells the compiler that the variable// have external linkageexternint items;intmain(){printf("total item is: %d", items);return0;}

    Here is the output of the above code after executing the display.c −

    total item is: 10
    

    Conclusion

    Linkage in C defines whether variables and functions can be accessed only within a single file or across multiple files of a program. By using internal linkage (static) and external linkage (extern), we can control the scope and accessibility of identifiers. It ensures better program structure and modularity.

  • Const Qualifier

    The const qualifier in C is used to declare variables whose values should remain fixed throughout the program. It is used to declare a variable as a constant, whose value cannot be changed after initialization. Once a variable is declared as const, it becomes readonly, and the compiler prevents any accidental modifications.

    What is the Use of const Qualifier in C?

    Using the const qualifier, programmers can improve the safety, readability, and maintainability of their program codes. It helps programmers make their intentions clear by signaling which values should stay fixed throughout the program.

    For example, constants like mathematical values (PI, e, etc.), array sizes, or configuration values should not be altered at runtime. By declaring them as const, we protect these values from accidental changes.

    Example of Using const Qualifier in C

    Take a look at the following example. Here, we have used const to ensure the value of PI remains fixed throughout the program.

    #include <stdio.h>intmain(){// Defining a constant variableconstint PI =3.14;printf("Value of PI: %d\n", PI);// Trying to modify PI will cause an error// PI = 10; // Not allowed, PI is read-onlyreturn0;}

    Observe how the const variable (PI) prevents unwanted changes to constants. When we run this code, it will produce the following output –

    Value of PI: 3
    

    Using const Qualifer in Different Contexts

    Apart from defining constant variables, the const qualifier can also be used in different contexts to provide various behaviors. Here are some different scenarios where we can use the const qualifier:

    • Pointer to Constant
    • Constant pointer to variable
    • Constant pointer to constant

    In the subsequent sections of this chapter, we will cover each of these topics in detail.

    Pointer to Constant

    As its name suggests, a “pointer to a constant” points to a constant value which cannot be modified. However, the pointer itself can change because it’s a variable and it can point somewhere else.

    Let’s see its syntax −

    const type* name;

    Or,

    typeconst* name;

    A “pointer to a constant” means the pointer can point to different variables, but the value of the object being pointed to cannot be changed through this pointer.

    • The pointer itself is stored in the read-write area (such as a stack in this case).
    • The object being pointed to may reside either in the read-only area or in the read-write area.
    • Even if the object is stored in the writable location, you cannot alter its value using this pointer, since the pointer treats the object as a constant.

    Example: Pointer to Constant with an Integer

    In this example, we are using a pointer to constant with an integer −

    #include <stdio.h>intmain(){int x =10, y =20;// Pointer to constant integerconstint*ptr =&x;printf("Value pointed by ptr: %d\n",*ptr);// *ptr = 15;  // Not allowed (cannot change value through ptr)
       ptr =&y;// allowed (pointer can point to another variable)printf("Value pointed by ptr: %d\n",*ptr);return0;}

    Notice that we cannot change the value of the variable “x” though the pointer. On executing the code, you will get the following output −

    Value pointed by ptr: 10
    Value pointed by ptr: 20
    

    Example: Pointer to Constant with an Array

    In this example, we are using a pointer to constant with an array −

    #include <stdio.h>intmain(){int arr[]={1,2,3};// Pointer to constant integer (array base address)constint*ptr = arr;printf("First element: %d\n",*ptr);// *ptr = 5;  	// not allowed (cannot change array element via ptr)
       ptr++;// Allowed (can move pointer to next element)printf("Second element: %d\n",*ptr);return0;}

    When we run the above program, it will produce the following output −

    First element: 1
    Second element: 2
    

    Here, we cannot modify an element of the array using a pointer in a regular way. Notice the following commented line in the program −

    // *ptr = 5;

    Constant Pointer to Variable

    A constant pointer means the pointer itself is a constant variable; it means we cannot alter the pointer to point to another variable. Its syntax is as follows −

    int*const ptr;

    Let’s understand this concept using the following example. It demonstrates that the value of the object pointed by the constant pointer can be changed but the pointer cannot point to another variable.

    #include <stdio.h>intmain(void){int i =10;int j =20;/* constant pointer to integer */int*const ptr =&i;printf("ptr: %d\n",*ptr);*ptr =100;// change the pointer valueprintf("ptr: %d\n",*ptr);// ptr = &j; // pointer cannot point to another variablereturn0;}

    Here is the output of the above code −

    ptr: 10
    ptr: 100
    

    Notice the commented line −

    // ptr = &j; 	// pointer cannot point to another variable

    If we uncomment this line and run the code, then it will produce an error. Why? It’s because the constant pointer (ptr) is pointing to “i” and it cannot point to another variable “j”.

    Constant Pointer to Constant

    A “constant pointer to constant” is a type of constant pointer that points to a constant variable, which means we cannot alter the value pointed to by the pointer, also the pointer cannot point to other variables. Let’s see its syntax −

    constint*const ptr;

    The following example shows how you can use a “constant pointer to constant” in a C program −

    #include <stdio.h>intmain(void){int i =10;int j =20;/* constant pointer to constant integer */constint*const ptr =&i;printf("ptr: %d\n",*ptr);
    
       ptr =&j;// error*ptr =50;// errorreturn0;}

    Now, let’s run this code and check its output −

    ERROR!
    main.c: In function 'main':
    main.c:10:9: error: assignment of read-only variable 'ptr'
       10 |     ptr = &j; // error
    
      |         ^
    ERROR! main.c:11:10: error: assignment of read-only location '*(const int *)ptr' 11 | *ptr = 50; // error

    In the code, observe that we are trying to modify the pointer as well as the value it is point to. And, a “constant pointer to constant” denies both the actions, which is why we are getting an error in both the cases.

    Advantages of Const Qualifier

    Following are the advantages of using a const qualifier in a C program −

    • Helps prevent unintentional changes to variables
    • Reduces the risk of bugs and errors in your code; makes the code more reliable
    • Prevents functions from modifying arguments that should remain unchanged

    By using const qualifiers, we can avoid having to make a copy of their values, which can reduce the memory usage and improve performance.

    Conclusion

    The const qualifier in C is a powerful feature that improves code readability, safety, and reliability. It helps prevent accidental modification by clearly defining which values should not change. It supports compiler optimizations and makes programs error-free and easy to maintain.