Top 26 Basic C Interview Questions You Must Prepare 19.Mar.2024

  • A const pointer is not the pointer to constant, it is the constant. For example, int* const ptr; indicates that ptr is a pointer, which is a constant. A pointer is preceded by ‘*’. In the above example it is not, Hence it is not the pointer to constant.
  • The ptr can not be used to point to another integer. The integer pointed by ptr can be changed. The const pointer can not be changed to point to other memory location, because the pointer is constant

The following are the differences between structures and arrays:

  • Array elements are homogeneous. Structure elements are of different data type. 
  • Array allocates static memory and uses index / subscript for accessing elements of the array. Structures allocate dynamic memory and uses (.) operator for accessing the member of a structure.
  • Array is a pointer to the first element of it. Structure is not a pointer
  • Array element access takes less time in comparison with structures.

The function main() calls / invokes other functions within it. The execution of the program always starts with main() function.

The main() function is :

  • The first function to start a program
  • Returns int value to the environment which called the program
  • It can be called recursively.
  • It is a user defined function, except the name
  • Like other functions, main(0 function can receive arguments. It has a) argument count and b) argument vector(string argument)

  • A programming technique in which a function may call itself. Recursive programming is especially well-suited to parsing nested markup structures 
  • Calling a function by itself is known as recursion. Any function can call any function including itself. In this scenario, if it happens to invoke a function by itself, it is recursion. One of the instructions in the function is a call to the function itself, usually the last statement. In some ways it is similar to looping. When the result of ‘one time call of a function is the input for the next time call of the function’, recursion is one of the best ways. For example, calculating factorial, in which the product of previous digit factorial is the input for the next digit’s factorial.
  • The process of calling a function by itself is known as recursion. Recursion is generally used when the result of the current function call is the input to the successive call of itself. For example, ‘factorial of a digit’. By definition, the factorial of the current digit is the factorial of its previous digit and the digit. In order to get the factorial of the previous digit, the same function should return the factorial.
  • Thus the result of the previous execution of the function is one of the inputs of the current execution. The process continues until an exit condition returns true.

  • A #define is used as immediate constant or as a macro. Where as the constant is a variable whose value can not change.
  • Pointer can be declared to a constant, but not for #define. 
  • #define can not define externally, and there is no way to use it for availability to the linker. Where as the constant can be global .

The function strcpy() will not allocate the memory space to copy. A pointer to the string to copy and a pointer to place to copy it to should be given.

The function strdup() will occupy / grab itself the memory space for copying the string to. This memory space needs to be freed up later when it is of no use anymore.

For char[] array, such size is not accepted by the compiler. If the size is specified, the following are the differences between char *a and char a[]:

  • The unary increment (++) or decrement (--) operators can not be used on arrays, where as they can be used in pointers (pointer arithmetic).
  • The address of an element of the array is constant; where as the address of an element of the pointer is not.
  • The variable *a is a constant pointer, where as a[] is not.
  • The array can not be assigned to another array, where as the pointer to char can be assigned to another char pointer.
  • The char array allocates equal to size of the string, where as the char pointer holds only the address of the first character of the string.

Static variable is available to a C application, throughout the life time. At the time of starting the program execution, static variables allocations takes place first. In a scenario where one variable is to be used by all the functions (which is accessed by main () function), then the variable need to be declared as static in a C program. The value of the variable is persisted between successive calls to functions. One more significant feature of static variable is that, the address of the variable can be passed to modules and functions which are not in the same C file.

static is an access qualifier that limits the scope but causes the variable to exist for the lifetime of the program. This me a static variable is one that is not seen outside the function in which it is declared but which remains until the program terminates. It also me that the value of the variable persists between successive calls to a function. The value of such a variable will remain and may be seen even after calls to a function. One more thing is that a declaration statement of such a variable inside a function will be executed only once.

A void pointer is pointer which has no specified data type. The keyword ‘void’ is preceded the pointer variable, because the data type is not specific. It is also known as a generic pointer. The void pointer can be pointed to any type. If needed, the type can be cast.

Ex: float *float_pointer; 

int *int_pointer;

void *void_pointer; 

. . . . . . . .

. . . . . . . .

void_pointer = float_pointer;

. . . . . . . . 

. . . . . . . . 

void_pointer = int_pointer;

A void pointer is generally used as function parameters, when the parameter or return type is unknown.

A bus error indicates an attempt to access memory in an illegal way,perhaps due to an unaligned pointer. 

A ‘bus error’ is certain undefined behavior result type. The cause for such error on a system could not be specified by the C language. The memory accessibility which CPU could not address physically, ‘bus error’ occurs. Also, any fault detected by a device by the computer system can also be a ‘bus error’. These errors caused by programs that generate undefined behavior which C language no longer specifies what can happen.

A macro is a name given to a block of C statements as a pre-processor directive. Being a pre-processor, the block of code is communicated to the compiler before entering into the actual coding (main () function). A macro is defined with the preprocessor directive, #define.

The advantage of using macro is the execution speed of the program fragment. When the actual code snippet is to be used, it can be substituted by the name of the macro. The same block of statements, on the other hand, need to be repeatedly hard coded as and when required.

The disadvantage of the macro is the size of the program. The reason is, the pre-processor will replace all the macros in the program by its real definition prior to the compilation process of the program.

Pass by value always invokes / calls the function or returns a value that is based on the value. This value is passed as a constant or a variable with value.

Pass by reference always invokes / calls the function by passing the address or a pointer to a memory location which contains the value. The memory location / pointer is populated with a value, so the function could look at the value through that location. The function can update the value available in the memory location by referencing the pointer. 

A string in C language is passed by reference.

The static identifier is used for initializing only once, and the value retains during the life time of the program / application. A separate memory is allocated for ‘static’ variables. This value can be used between function calls. 

The default value of an uninitialized static variable is zero. A function can also be defined as a static function, which has the same scope of the static variable.

The difference between arrays and linked lists are:

  • Arrays are linear data structures. Linked lists are linear and non-linear data structures. 
  • Linked lists are linear for accessing, and non-linear for storing in memory
  • Array has homogenous values. And each element is independent of each other positions. Each node in the linked list is connected with its previous node which is a pointer to the node. 
  • Array elements can be modified easily by identifying the index value. It is a complex process for modifying the node in a linked list.
  • Array elements can not be added, deleted once it is declared. The nodes in the linked list can be added and deleted from the list.

The scope and lifetime of a variable or / and function within a C program is defined by storage class. There are four storage classes in C

auto - It is the default storage class for all variables and / or functions.

register - Allows for defining variables to store in CPU register instead of RAM. Unary operator is not applied for register variable.

static – The static storage class allows the updated variable values available for the next time when the function, in which the variable is defined , is invoked for the next time.

extern - It allows a global variable to be visible to all the program files / external files ( C programs).

  • The auto variables are stored in the main memory of the system.
  • The keyword 'auto' is optional. 
  • Many of the variables used by the program or application are 'auto' variables, being the main memory is faster. 
  • These variables are stored in the memory runtime stack.
  • It is de-allocated at the completion of its block execution.
  • It is a local variable which is allocated and deallocated automatically when the program flow enters and leaves the variable's scope.

  • The fgets() function is safer to use.
  • It checks the bounds, i.e., the size of the buffer and does not cause overflow on the stack to occur. 
  • The gets() function does not check the bounds.
  • The gets() function is an insecure and careless use can lead to errors.

  • Volatile variables get special attention from the compiler. A variable declared with the volatile keyword may be modified externally from the declaring function.
  • If the keyword volatile is not used, the compiler optimization algorithms might consider this to be a case of infinite loop. Declaring a variable volatile indicates to a compiler that there could be external processes that could possibly alter the value of that variable.

e.g.:

  • A variable that might be concurrently modified by multiple threads may be declared volatile. Variables declared to be volatile will not be optimized by the compiler. Compiler must assume that their values can change at any time. However, operations on a volatile variable are still not guaranteed to be atomic.

  • An unwanted increase in programs is referred to as a memory leak is C language.
  • The intake of the program increases in the memory by an unintentional consumption of the memory. 
  • If the program is getting corrupted and results in errors, it me the memory leak. 
  • In case there is a leak by any program, the function of the system may stop and violate operating system files.
  • It is the gradual loss of available computer memory when a program repeatedly fails to return memory that it has obtained for temporary use.
  • It becomes exhausted and the program becomes no longer to perform properly.
  • It is the result of a program bug.

The keyword typedef is used for defining user defined data types. A new definition of existing data types is created by using typedef. It is used to define user defined identifiers which can be used in substitution of type specifiers such as int, float etc. It does not reserve memory space. The names defined by typedef are synonyms for the data types.

For example typedef int integer;

Instead of int the new definition integer can be used for better readability.

A set of named integer constants is known as an enumeration. The enumeration type declaration includes the name of the enumeration tag and the definition of a set of named integers. 

Ex: enum CITY { Mumbai, Bangalore, Chennai, NewDelhi } metros ;

Variables of enumeration type persists one of the existing values of the enumeration set. The enum type variables could be utilized in indexing expressions, as operands of all arithmetic and relational operators. ANSI C enum expressions are always have int type, which occupies the memory space that occupied by the int type. 

Example: 

enum DAY /* Defines an enumeration type */

{

saturday, /* Names day and declares a */

sunday = 0, /* variable named workday with */ 

monday, /* that type */

tuesday,

wednesday, /* wednesday is associated with 3 */

thursday,

friday

} workday;

saturday in the above example is associated with value 0 by default. The identifier sunday is explicitly assigned with @The remaining identifiers are given values 1 through 5 by default.

A segmentation violation usually indicates an attempt to access memory which doesn't even exist. 

Segmentation violation usually occurs at the time of a program’s attempt for accessing memory location, which is not allowed to access. The following code should create segmentation violation.

main() {

char *hello = “Hello World”;

*hello = ‘h’;

}

At the time of compiling the program, the string “hello world” is placed in the binary mark of the program which is read-only marked. When loading, the compiler places the string along with other constants in the read-only segment of the memory. While executing a variable *hello is set to point the character ‘h’ , is attempted to write the character ‘h’ into the memory, which cause the segmentation violation. And, compiler does not check for assigning read only locations at compile time.

  • It is possible to specify variable field width in a scanf() format string by using %s control string.
  • The %s reads a string of variable field width up to the first white space character.

Example:

scanf("%s", name);   // where name is a character array

  • The scanf() stores the results away in variables which you provide in the argument list and reads the data from the console or from a FILE stream and parses it.

Static Memory Allocation: Memory is allocated for the declared variable by the compiler. The address can be obtained by using ‘address of’ operator and can be assigned to a pointer. The memory is allocated during compile time. Since most of the declared variables have static memory, this kind of assigning the address of a variable to a pointer is known as static memory allocation.

Dynamic Memory Allocation: Allocation of memory at the time of execution (run time) is known as dynamic memory allocation. The functions calloc() and malloc() support allocating of dynamic memory. Dynamic allocation of memory space is done by using these functions when value is returned by functions and assigned to pointer variables.

The storage allocation / class determine the memory part where the storage space is allocated for variables, functions and how long the allocation of storage continues to exist. 

The scope of a variable is specified by its storage allocation. This is specified by the keywords – auto, extern, static and register.

  • ‘auto’ variables stores in the memory storage. Majority of the variables in a program / application are of type ‘auto’. Their scope might be local or global.
  • ‘extern’ variables are of global variables and can be declared in another source file which could be external / outside the current program scope,
  • ‘register’ variables are allocated in the CPU registers. These variables storage and accessibility is much faster than other variables, being they are stored in CPU itself. The variables of repeated usage or access time is critical, can be declared as register variables.
  • ‘static’ variables provides a lifetime over the program, and provides a way for limiting the scope of such variables. These variables are automatically initialized to zero and could be specified for ‘auto’ and ‘extern’ variables. The values are retained, even though they are declared in local scope, between the repeated function calls to the same function.

  • The variables of 'register' type modifier inform the compiler for storing the variables in a register of the CPU.
  • These variables are stored in the registers, so the speed of processing is become more than the normal variables.

Advantages of Register variable:

  • Access optimization and speed of program execution: The operations of these variables are faster by orders of magnitude.
  • It is useful when you want to refer a variable frequently.
  • It allocates fast memory in the form of a register.
  • It helps to speed up program execution.