C interview questions, your interviewer might ask

c interview questions

You are looking for C interview questions or tricky C interview questions, then you are at the right place. Here I have tried to create a collection of good C Interview questions. I have spent many hours to create these C interview questions. So I hope you will enjoy these tricky C interview questions and you will learn new concepts of programming in C interview questions. All the best for your C interview.

Q) What is the difference between declaration and definition of a variable?

Ans:

Declaration of a variable in C

A variable declaration only provides sureness to the compiler at the compile time that variable exists with the given type and name, so that compiler proceeds for further compilation without needing all detail of this variable. In C language, when we declare a variable, then we only give the information to the compiler, but there is no memory reserve for it. It is only a reference, through which we only assure the compiler that this variable may be defined within the function or outside of the function.

Note: We can declare a variable multiple times but defined only once.
eg,

extern int data;
extern int foo(int, int);
int fun(int, char); // extern can be omitted for function declarations

 

Definition of a variable in c

The definition is action to allocate storage to the variable. In other words, we can say that variable definition is the way to say the compiler where and how much to create the storage for the variable generally definition and declaration occur at the same time but not almost.

eg,

int data;
int foo(int, int) { }

 

Note: When you define a variable then there is no need to declare it but vice versa is not applicable.

 

Q) What is the difference between global and static global variables?

Ans:

Global and static global variables have different linkages. It is the reason global variables can be accessed outside of the file but the static global variable only accesses within the file in which it is declared.

A static global variable            ===>>>  internal linkage.
A non-static global variable  ===>>>  external linkage.

For more details, you can see below-mentioned articles,

 

Q) What are storage classes in C language?

Ans:

The storage classes decide the extent (lifetime) and scope (visibility) of a variable or function within the program. Every variable gets some location in the memory where the variable’s value is stored in the form of bits. The storage classes decide where these variable values will store like in CPU register, stack memory, BSS or DS.

There are four storage classes available in C programming.

  1. auto.
  2. static.
  3. extern.
  4. register

For more details, you can see below-mentioned articles,

 

Q) Differentiate between an internal static and external static variable?

Ans:

In C language, the external static variable has the internal linkage and the internal static variable has no linkage. It is the reason they have a different scope but both will alive throughout the program.

A external static variable  ===>>>  internal linkage.
A internal static variable   ===>>>  none .

 

Q) What is the difference between typedef & Macros?

Ans:

Let’s see the short description of the typedef and macro to understand the difference between them.

typedef:

The C language provides a very important keyword typedef for defining a new name for existing types. The typedef is the compiler directive mainly use with user-defined data types (structure, union or enum) to reduce their complexity and increase code readability and portability.

Syntax,

typedef type NewTypeName;

 

 

Let’s take an example,

typedef unsigned int UnsignedInt;

Now UnsignedInt is a new type and using it, we can create a variable of unsigned int. So in the below example, Mydata is unsigned int variable.

UnsignedInt Mydata;

 

Note: A typedef creates synonyms or a new name for existing types it does not create new types.

Macro:

A macro is a pre-processor directive and it replaces the value before compiling the code. One of the major problems with the macro is that there is no type checking. Generally, the macro is used to create the alias, in C language. A macro is also used as a file guard in C and C++.

Syntax,

#define  MACRO_NAME  MACRO_VALUE

eg,

#define VALUE 10

 

Now VALUE becomes 10 in your program. You can use the VALUE in place of the 10.

For more details, you can see below-mentioned articles,

 

Q) What is the output of the below C code?

#include<stdio.h>

int main()
{
    typedef auto int myAutoInt;

    myAutoInt data = 4;

    printf("%d",data);
    return 0;
}

Ans:

compiler error.

Explanation: 

typedef already consider as partial storage class, so you can not mix two storage classes at a time.

 

Q) What is the variable in C?

Ans:

A variable in C defines a location name where you can put value and you can use these values whenever required in the program. In other words, you can say that variable is a name (or identifier) which indicates some physical address in the memory, where data store in the form of bits of the string.

In C language, every variable has a specific data types (pre-defined or user-defined) that determine the size and memory layout of the variable.

Note: Each variable bind with two important properties, scope, and extent.

 

Q) Using the variable p write down some declaration

  1. An integer variable.
  2. An array of five integers.
  3. A pointer to an integer.
  4. An array of ten pointers to integers.
  5. A pointer to a pointer to an integer.
  6. A pointer to an array of three integers.
  7. A pointer to a function that takes a pointer to a character as an argument and returns an integer.
  8. An array of five pointers to functions that take an integer argument and return an integer.

Ans:

1. int p; // An integer

2. int p[5]; // An array of 5 integers

3. int *p; // A pointer to an integer

4. int *p[10]; // An array of 10 pointers to integers

5. int **p; // A pointer to a pointer to an integer

6. int (*p)[3]; // A pointer to an array of 3 integers

7. int (*p)(char *); // A pointer to a function a that takes an integer

8. int (*p[5])(int); // An array of 5 pointers to functions that take an integer argument and return an integer

 

 

Q) What are the data types in C?

Ans:

A data type is a classification of data that tells the compiler or interpreter how the programmer intends to use the data. In other words, you can say that it defines the size (BYTE) and the range of a variable.

Classification of the data types in C language

1. Pre-define data types (int, char, float, etc)
2. User-define data types ( struct, union, enum)

In C language, different data types have different ranges. The range varies from compiler to compiler. In the below table, I have listed some data types with there ranges and format specifier as per the 32-bit GCC compiler.

Data Type             Memory (bytes)          Range                      Format Specifier

short int                   2          -32,768 to 32,767                       %hd
unsigned short int          2           0 to 65,535                            %hu
unsigned int                4           0 to 4,294,967,295                     %u
int                         4          -2,147,483,648 to 2,147,483,647         %d
long int                    4          -2,147,483,648 to 2,147,483,647         %ld
unsigned long int           4           0 to 4,294,967,295                     %lu
long long int               8          -(2^63) to (2^63)-1                     %lld
unsigned long long int      8           0 to 18,446,744,073,709,551,615        %llu
signed char                 1          -128 to 127                             %c 
unsigned char               1           0 to 255                               %c
float                       4               -                                  %f
double                      8               -                                  %lf
long double                 12              -                                  %Lf

 

For more details, you can see below-mentioned articles,

 

Q) Some Questions related to declaration for you

  1. int* (*fpData)(int , char, int (*paIndex)[3]);
  2. int* (*fpData)(int , int (*paIndex)[3] , int (* fpMsg) (const char *));
  3. int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
  4. int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
  5. int* (*(*fpData)(const char *))(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));

 

If you love online courses, I recommend you to see this video course, 10 days trial is free.

C tutorial

 

Q) What are the uses of the keyword static?

Ans:

In C language, the static keyword has a lot of importance. If we have used the static keyword with a variable or function, then only internal or none linkage is worked. I have described some simple use of a static keyword.

1.  A static variable only initializes once, so a variable declared static within the body of a function maintains its prior value between function invocations.

2.  A global variable with static keyword has internal linkage, so it only accesses within the translation unit (.c). It is not accessible by another translation unit. The static keyword protects your variable to access from another translation unit.

3. By default in C language, the linkage of the function is external that it means it is accessible by the same or another translation unit. With the help of the static keyword, we can make the scope of the function local, it only accesses by the translation unit within it is declared.

 

Q) What are the different types of linkage?

Ans:

The C language has three types of linkage, External Linkage, Internal Linkage, and None Linkage.

 

Q) Can static variables be declared in a header file?

Ans:

Yes, we can declare the static variables in a header file.

 

Q) Size of the integer depends on what?

Ans:

The C standard is explained that the minimum size of the integer should be 16 bits. Some programing language is explained that the size of the integer is implementation-dependent but portable programs shouldn’t depend on it.

Primarily the size of integer depends on the type of the compiler which has written by the compiler writer for the underlying processor. You can see compilers merrily changing the size of integer according to convenience and underlying architectures. So it is my recommendation to use the C99 integer data types ( uin8_t, uin16_t, uin32_t ..) in place of standard int.

 

Q) Are integers signed or unsigned?

Ans:

In standard C language, the integer data type is by default signed. So if you create an integer variable, it can store both positive and negative value.

For more details on signed and unsigned integer, check out:
A closer look at signed and unsigned integers in C

 

Q) What is a difference between unsigned int and signed int in C?

Ans:

The signed and unsigned integer type has the same storage (according to the standard at least 16 bits) and alignment but still, there is a lot of difference them, in bellows lines, I am describing some difference between the signed and unsigned integer.

  • A signed integer can store the positive and negative value both but beside it unsigned integer can only store the positive value.
  • The range of nonnegative values of a signed integer type is a sub-range of the corresponding unsigned integer type.
    For example,
    Assuming the size of the integer is 2 bytes.
    signed int -32768 to +32767
    unsigned int 0 to 65535
  • When computing the unsigned integer, it never gets overflow because if the computation result is greater than the largest value of the unsigned integer type, it is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
    For example,
    Computational Result % (Largest value of the unsigned integer+1)
  • The overflow of the signed integer type is undefined.
  • If Data is signed type negative value, the right shifting operation of Data is implementation-dependent but for the unsigned type, it would be Data/ 2pos.
  • If Data is signed type negative value, the left shifting operation of Data shows the undefined behavior but for the unsigned type, it would be Data x 2pos.




Q) What is the difference between a macro and a function?

Ans:

macro VS function

 

 

Q) What is the output of the below C code?

#include <stdio.h>

#define PRINT(var,data) do {\
                            if(var < data)\
                                {\
                                    printf("Aticleworld");\
                                    ++var;\
                                }\
                            }while(1);

int main()
{
    PRINT(0,2);

    return 0;
}

Output:  compiler Error.

Explanation: When macro will be expanded, var will be replaced with 0 (Rvalue). Because you are trying to increment the Rvalue, you will get a compiler error. You can read this article for more detail, post, and pre-increment operators.

 

 

Q) What do you mean by enumeration in C?

Ans:

An enum in C is a user-defined data type. It consists set of named constant integers. Using the enum keyword, we can declare an enumeration type by using the enumeration tag (optional) and a list of named integer.

Basically, we used the enum to increase the code readability and with enum easy to debug the code as compared to symbolic constant (macro). The most important property of enum is that it follows the scope rule and the compiler automatically assigns the value to its member constant.

Note: A variable of enumeration type stores one of the values of the enumeration list defined by that type.

Syntax of enum,

enum Enumeration_Tag { Enumeration_List };

 

The Enumeration_Tag specifies the enumeration type name.

The Enumeration_List is a comma-separated list of named constant.

Example,

enum FLASH_ERROR { DEFRAGMENT_ERROR, BUS_ERROR};

 

For more details, you can see below-mentioned articles,

 

Q) What does the keyword const mean?

Ans:

The const qualifier only gives the direction to the compiler that the value of qualify object cannot be changed. In simple words, const means not modifiable (cannot assign any value to the object at the run time).

Syntax:

const DataType Identifier = Value;
e.g.
const int iData = 0;

 

const

 

For more details, you can see below-mentioned articles,

 

 

Q) When should we use const in a C program?

Ans:

There are the following places where we need to use the const keyword in the programs.

  • In the call by reference function argument, if you don’t want to change the actual value which has passed in function.
    int PrintData ( const char *pcMessage);
  • In some places, const is better than macro because const handled by the compiler and have a type checking.
    const int ciData = 100;
  • In the case of the I/O and memory-mapped register, const is used with the volatile qualifier for efficient access.
    const volatile uint32_t *DEVICE_STATUS = (uint32_t *) 0x80102040;
  • When you don’t want to change the value of an initialized variable.

 

Q) What is the meaning of the below declarations?

1. const int a;
2. int const a;
3. const int *a;
4. int * const a;
5. int const * a const;

 

Ans:

  1. The “a” is a constant integer.
  2. Similar to first, “a” is a constant integer.
  3. Here “a” is a pointer to a const integer, the value of the integer is not modifiable, but the pointer is modifiable.
  4. Here “a” is a const pointer to an integer, the value of the pointed integer is modifiable, but the pointer is not modifiable.
  5. Here “a” is a const pointer to a const integer that means the value of the pointed integer and pointer both are not modifiable.

 

Q) What is the output of the below C program?

#include <stdio.h>

int main()
{
    int pos = 14;
    float data = 1.2;

    printf("%*f",pos,data);
    
    return 0;
}

Ans:

The output of the above code will be 1.200000 with 6 space.

Explanation:

Here 1.200000 is printing with, 6 spaces, because by giving * in printf we can specify an additional width parameter, here ‘pos’ is the width and ‘data’ is the value. if the number is smaller than the width then rest is filled with spaces.

 

Q) Differentiate between a constant pointer and pointer to a constant?

Ans:

Constant pointer:

A constant pointer is a pointer whose value (pointed address) is not modifiable. If you will try to modify the pointer value, you will get the compiler error.

A constant pointer is declared as follows :

Data_Type * const Pointer_Name;

eg,

int *const ptr; //constant pointer to integer

 

Let’s see the below example code when you will compile the below code to get the compiler error.

#include<stdio.h>

int main(void)
{
    int var1 = 10, var2 = 20;

    //Initialize the pointer
    int *const ptr = &var1;

    //Try to modify the pointer value
    ptr = &var2;

    printf("%d\n", *ptr);

    return 0;
}

 

Pointer to a constant:

In this scenario the value of the pointed address is constant that means we can not change the value of the address that is pointed by the pointer.

A constant pointer is declared as follows :

Data_Type  const*  Pointer_Name;

eg,

int const *ptr// pointer to const integer

 

Let’s take a small code to illustrate a pointer to a constant:

#include<stdio.h>

int main(void)
{
    int var1 = 100;
    // pointer to constant integer
    const int* ptr = &var1;
    
    //try to modify the value of pointed address
    *ptr = 10;
    
    printf("%d\n", *ptr);

    return 0;
}




Q) What are the post-increment and decrement operators?

Answer:

When we use a post-increment (++) operator on an operand then the result is the value of the operand and after getting the result, the value of the operand is incremented by 1. The working of the post-decrement (–) operator is similar to the post-increment operator but the difference is that the value of the operand is decremented by 1.

Note: incrementation and decrementation by 1 are the types specified.

 

Q) Which one is better: Pre-increment or Post increment?

Answer:

Nowadays compiler is enough smart, they optimize the code as per the requirements. The post and pre-increment both have their own importance we need to use them as per the requirements.

If you are reading a flash memory byte by bytes through the character pointer then here you have to use the post-increment, either you will skip the first byte of the data. Because we already know that in the case of pre-increment pointing address will be increment first and after that, you will read the value.

Let’s take an example of the better understanding,
In the below example code, I am creating a character array and using the character pointer I want to read the value of the array. But what will happen if I used the pre-increment operator? The answer to this question is that ‘A’ will be skipped and B will be printed.

#include <stdio.h>

int main(void)
{
    char acData[5] = {'A','B','C','D','E'};
    char *pcData = NULL;

    pcData = acData;

    printf("%c ",*++pcData);

    return 0;
}

Output:  B

But in place of pre-increment if we use post-increment then the problem is getting solved and you will get A as the output.

#include <stdio.h>

int main(void)
{
    char acData[5] = {'A','B','C','D','E'};
    char *pcData = NULL;

    pcData = acData;

    printf("%c ",*pcData++);

    return 0;
}

Output:  A

Besides that, when we need a loop or just only need to increment the operand then pre-increment is far better than post-increment because in case of post increment compiler may have created a copy of old data which takes extra time. This is not 100% true because nowadays the compiler is so smart and they are optimizing the code in a way that makes no difference between pre and post-increment. So it is my advice, if post-increment is not necessary then you have to use the pre-increment.

Note: Generally post-increment is used with array subscript and pointers to read the data, otherwise if not necessary then use pre in place of post-increment. Some compiler also mentioned that to avoid to use post-increment in looping condition.
iLoop = 0.

while (a[iLoop ++] != 0)
{
// Body statements
}




Q) Are the expressions *ptr++ and ++*ptr same?

Ans:

Both expressions are different. Let’s see a sample code to understand the difference between both expressions.

#include <stdio.h>

int main(void)
{
    int aiData[5] = {100,200,30,40,50};
    
    int *ptr = aiData;
    
    *ptr++;
    
    printf("aiData[0] = %d, aiData[1] = %d, *piData = %d", aiData[0], aiData[1], *ptr);
    
    return 0;
}

Output: 100, 200, 200

Explanation:

In the above example, two operators are involved and both have different precedence. The precedence of post ++ is higher than the *, so first post ++ will be executed and above expression, *p++ will be equivalent to *(p++). In another word you can say that it is post-increment of address and output is 100, 200, 200.

#include <stdio.h>

int main(void)
{
    int aiData[5] = {100,200,300,400,500};

    int *ptr = aiData;

    ++*ptr;

    printf("aiData[0] = %d, aiData[1] = %d, *ptr = %d", aiData[0], aiData[1], *ptr);

    return 0;
}

Output: 101 , 200 , 101

Explanation:

In the above example, two operators are involved and both have the same precedence with a right to left associativity. So the above expression ++*p is equivalent to ++ (*p). In another word, we can say it is pre-increment of value and output is 101, 200, 101.

 

Q) Are the expressions *++ptr and ++*ptr same?

Ans:

Both expressions are different. Let’s see a sample code to understand the difference between both expressions.

#include <stdio.h>

int main(void)
{
    int aiData[5] = {100,200,30,40,50};

    int *piData = aiData;

    ++*piData;

    printf("aiData[0] = %d, aiData[1] = %d, *piData = %d", aiData[0], aiData[1], *piData);

    return 0;
}

Output: 101 , 200 , 101

Explanation:
In the above example, two operators are involved and both have the same precedence with a right to left associativity. So the above expression ++*p is equivalent to ++ (*p). In other words, we can say it is pre-increment of value and output is 101, 200, 101.

#include <stdio.h>

int main(void)
{
    int aiData[5] = {100,200,30,40,50};

    int *piData = aiData;

    *++piData;

    printf("aiData[0] = %d, aiData[1] = %d, *piData = %d", aiData[0], aiData[1], *piData);

    return 0;
}

Output: 100, 200, 200

Explanation:
In the above example, two operators are involved and both have the same precedence with the right to left associativity. So the above expression *++p is equivalent to *(++p). In other words, you can say it is pre-increment of address and output is 100, 200,200.


Go C Interview Questions PART-2

 

Go C Interview Questions PART-3

 

Recommended Articles for you:

125 comments

  1. ultimate questions….thank Q soo much .

    but a small question>>> |||| find below

    write a program to ciunt set bits..??

    plsz explain this logic…. 🙂 🙂

    unsigned int NumberSetBits(unsigned int n)
    {
    unsigned int CountSetBits= 0;
    while (n)
    {
    CountSetBits += n & 1; // im not understan how this logic works to catuch the set bits.
    n >>= 1;
    }
    return CountSetBits;
    }

    1. In the below code,

      while (n)
      {
      CountSetBits += n & 1;
      n >>= 1;
      }

      Suppose n =2, that means in binary (0000000000000010) if the size of n is 2 byte.

      initialy CountSetBits = 0;

      Now,

      In first iteration:

      while (0000000000000010)
      {
      CountSetBits += 0000000000000010 & 1;

      0000000000000010 >>= 1; //shift 1 position right
      }

      After the first iteration the value of CountSetBits will be 0 because CountSetBits += 0000000000000010 & 1;

      become CountSetBits += 0;

      In second iteration:

      while (0000000000000001)
      {
      CountSetBits += 0000000000000001 & 1;

      0000000000000001 >>= 1; //shift 1 position right
      }

      After the second iteration the value of CountSetBits will be 1 because CountSetBits += 0000000000000001 & 1;

      become CountSetBits += 1;

      After the second iteration,

      while (0000000000000000) //false never executed
      {

      }

      So finally the value of CountSetBits is 1.

      I hope now you have understood.

  2. My question is how .obj file looks like after the compilation ?

    Can we load .asm file or .obj file inside the micro controller using loader? If not why?

      1. Hi Amlendra, I have a question about i2c and spi.Suppose i am having ADC,EEPROM,Flash,display now i want to interface this peripheral with my MCU .so please tell me which protocol (i2c or spi) is best?
        Ignore cost and number of pins

  3. Thanks bro.
    Helps to gain knowledge especially for interview preparation.
    Is there any blob for eeprom, rtos..

  4. Error:
    Steps 2:
    num = (((num & 0xcccccccc) >> 2) | ((num & 0x33333333) << 2));

    Above expression uses to swap the 2 bits of a nibble. Suppose num is 10 00, after the above expression, it will be 00 01.

    Corrected one:
    Above expression uses to swap the 2 bits of a nibble. Suppose num is 10 00, after the above expression, it will be 00 10.

  5. ” 3. Here “a” is a pointer to a const integer, the value of the integer is not modifiable, but the pointer is not modifiable.”

    Should it be
    “3. Here “a” is a pointer to a const integer, the value of the integer is not modifiable, but the pointer is modifiable.”

    its a minor typo i guess

Leave a Reply

Your email address will not be published. Required fields are marked *