2023 2024 Student Forum > Management Forum > Main Forum

 
  #2  
25th November 2014, 11:01 AM
Super Moderator
 
Join Date: Apr 2013
Re: C Language Basics - C Interview Questions and Answers

Below I am providing you some of the questions from the question paper of C Language Basics - C Interview Questions and Answers and attaching a PDF attachment which has detail information regarding this that you can down load for free:

C Language Basics - C Interview Questions and Answers

What is a local block?

A local block is any portion of a C program that is enclosed by the left brace ({) and the right brace (}). A C function contains left and right braces, and therefore anything between the two braces is contained in a local block. An if statement or a switch statement can also contain braces, so the portion of code between these two braces would be considered a local block.

Additionally, you might want to create your own local block without the aid of a C function or keyword construct. This is perfectly legal. Variables can be declared within local blocks, but they must be declared only at the beginning of a local block. Variables declared in this manner are visible only within the local block. Duplicate variable names declared within a local block take precedence over variables with the same name declared outside the local block. Here is an example of a program that uses local blocks:

This example program produces the following output:

Test variable before the if statement: 10

Test variable within the if statement: 5

Test variable within the independent local block: 0

Test variable after the if statement: 10

Notice that as each test_var was defined, it took precedence over the previously defined test_var. Also notice that when the if statement local block had ended, the program had reentered the scope of the original test_var, and its value was 10.

C Language Basics - C Interview Questions and Answers

1. What is a local block?

A local block is any portion of a C program that is enclosed by the left brace ({) and the right brace (}). A C function contains left and right braces, and therefore anything between the two braces is contained in a local block. An if statement or a switch statement can also contain braces, so the portion of code between these two braces would be considered a local block.

Additionally, you might want to create your own local block without the aid of a C function or keyword construct. This is perfectly legal. Variables can be declared within local blocks, but they must be declared only at the beginning of a local block. Variables declared in this manner are visible only within the local block. Duplicate variable names declared within a local block take precedence over variables with the same name declared outside the local block. Here is an example of a program that uses local blocks:


#include <stdio.h>
void main(void);
void main()
{
/* Begin local block for function main() */
int test_var = 10;
printf("Test variable before the if statement: %d\n", test_var);
if (test_var > 5)
{
/* Begin local block for "if" statement */
int test_var = 5;
printf("Test variable within the if statement: %d\n",
test_var);
{
/* Begin independent local block (not tied to
any function or keyword) */
int test_var = 0;
printf(
"Test variable within the independent local block:%d\n",
test_var);
}
/* End independent local block */
}
/* End local block for "if" statement */
printf("Test variable after the if statement: %d\n", test_var);
}
/* End local block for function main() */

This example program produces the following output:

Test variable before the if statement: 10

Test variable within the if statement: 5

Test variable within the independent local block: 0

Test variable after the if statement: 10

Notice that as each test_var was defined, it took precedence over the previously defined test_var. Also notice that when the if statement local block had ended, the program had reentered the scope of the original test_var, and its value was 10.

2. Should variables be stored in local blocks?

The use of local blocks for storing variables is unusual and therefore should be avoided, with only rare exceptions. One of these exceptions would be for debugging purposes, when you might want to declare a local instance of a global variable to test within your function. You also might want to use a local block when you want to make your program more readable in the current context.

Sometimes having the variable declared closer to where it is used makes your program more readable. However, well-written programs usually do not have to resort to declaring variables in this manner, and you should avoid using local blocks.

3. When is a switch statement better than multiple if statements?

A switch statement is generally best to use when you have more than two conditional expressions based on a single variable of numeric type. For instance, rather than the code

if (x == 1)
printf("x is equal to one.\n");
else if (x == 2)
printf("x is equal to two.\n");
else if (x == 3)
printf("x is equal to three.\n");
else
printf("x is not equal to one, two, or three.\n");

the following code is easier to read and maintain:

switch (x)
{
case 1: printf("x is equal to one.\n");
break;
case 2: printf("x is equal to two.\n");
break;
case 3: printf("x is equal to three.\n");
break;
default: printf("x is not equal to one, two, or three.\n");
break;
}

Notice that for this method to work, the conditional expression must be based on a variable of numeric type in order to use the switch statement. Also, the conditional expression must be based on a single variable. For instance, even though the following if statement contains more than two conditions, it is not a candidate for using a switch statement because it is based on string comparisons and not numeric comparisons:

char* name = "Lupto";
if (!stricmp(name, "Isaac"))
printf("Your name means 'Laughter'.\n");
else if (!stricmp(name, "Amy"))
printf("Your name means 'Beloved'.\n ");
else if (!stricmp(name, "Lloyd"))
printf("Your name means 'Mysterious'.\n ");
else
printf("I haven't a clue as to what your name means.\n");

4. Is a default case necessary in a switch statement?

No, but it is not a bad idea to put default statements in switch statements for error- or logic-checking purposes. For instance, the following switch statement is perfectly normal:

switch (char_code)
{
case 'Y':
case 'y': printf("You answered YES!\n");
break;
case 'N':
case 'n': printf("You answered NO!\n");
break;
}

Consider, however, what would happen if an unknown character code were passed to this switch statement. The program would not print anything. It would be a good idea, therefore, to insert a default case where this condition would be taken care of:

...
default: printf("Unknown response: %d\n", char_code);
break;
...

Additionally, default cases come in handy for logic checking. For instance, if your switch statement handled a fixed number of conditions and you considered any value outside those conditions to be a logic error, you could insert a default case which would flag that condition. Consider the following example:

void move_cursor(int direction)
{
switch (direction)
{
case UP: cursor_up();
break;
case DOWN: cursor_down();
break;
case LEFT: cursor_left();
break;
case RIGHT: cursor_right();
break;
default: printf("Logic error on line number %ld!!!\n",
__LINE__);
break;
}
}

5. Can the last case of a switch statement skip including the break?

Even though the last case of a switch statement does not require a break statement at the end, you should add break statements to all cases of the switch statement, including the last case. You should do so primarily because your program has a strong chance of being maintained by someone other than you who might add cases but neglect to notice that the last case has no break statement.

This oversight would cause what would formerly be the last case statement to "fall through" to the new statements added to the bottom of the switch statement. Putting a break after each case statement would prevent this possible mishap and make your program more "bulletproof." Besides, most of today's optimizing compilers will optimize out the last break, so there will be no performance degradation if you add it.

6. Other than in a for statement, when is the comma operator used?

The comma operator is commonly used to separate variable declarations, function arguments, and expressions, as well as the elements of a for statement. Look closely at the following program, which shows some of the many ways a comma can be used:

#include <stdio.h>
#include <stdlib.h>
void main(void);
void main()
{
/* Here, the comma operator is used to separate
three variable declarations. */
int i, j, k;
/* Notice how you can use the comma operator to perform
multiple initializations on the same line. */
i = 0, j = 1, k = 2;
printf("i = %d, j = %d, k = %d\n", i, j, k);
/* Here, the comma operator is used to execute three expressions
in one line: assign k to i, increment j, and increment k.
The value that i receives is always the rightmost expression. */
i = (j++, k++);
printf("i = %d, j = %d, k = %d\n", i, j, k);
/* Here, the while statement uses the comma operator to
assign the value of i as well as test it. */
while (i = (rand() % 100), i != 50)
printf("i is %d, trying again...\n", i);
printf("\nGuess what? i is 50!\n");
}

Notice the line that reads

i = (j++, k++);

This line actually performs three actions at once. These are the three actions, in order:

1. Assigns the value of k to i. This happens because the left value (lvalue) always evaluates to the rightmost argument. In this case, it evaluates to k. Notice that it does not evaluate to k++, because k++ is a postfix incremental expression, and k is not incremented until the assignment of k to i is made. If the expression had read ++k, the value of ++k would be assigned to i because it is a prefix incremental expression, and it is incremented before the assignment is made.

2. Increments j.

3. Increments k.

Also, notice the strange-looking while statement:

while (i = (rand() % 100), i != 50)
printf("i is %d, trying again...\n");

Here, the comma operator separates two expressions, each of which is evaluated for each iteration of the while statement. The first expression, to the left of the comma, assigns i to a random number from 0 to 99.

The second expression, which is more commonly found in a while statement, is a conditional expression that tests to see whether i is not equal to 50. For each iteration of the while statement, i is assigned a new random number, and the value of i is checked to see that it is not 50. Eventually, i is randomly assigned the value 50, and the while statement terminates.

7. How can you tell whether a loop ended prematurely?

Generally, loops are dependent on one or more variables. Your program can check those variables outside the loop to ensure that the loop executed properly. For instance, consider the following example:

#define REQUESTED_BLOCKS 512
int x;
char* cp[REQUESTED_BLOCKS];
/* Attempt (in vain, I must add...) to
allocate 512 10KB blocks in memory. */
for (x=0; x< REQUESTED_BLOCKS; x++)
{
cp[x] = (char*) malloc(10000, 1);
if (cp[x] == (char*) NULL)
break;
}
/* If x is less than REQUESTED_BLOCKS,
the loop has ended prematurely. */
if (x < REQUESTED_BLOCKS)
printf("Bummer! My loop ended prematurely!\n");

Notice that for the loop to execute successfully, it would have had to iterate through 512 times. Immediately following the loop, this condition is tested to see whether the loop ended prematurely. If the variable x is anything less than 512, some error has occurred.

8. What is the difference between goto and long jmp( ) and setjmp()?

A goto statement implements a local jump of program execution, and the longjmp() and setjmp() functions implement a nonlocal, or far, jump of program execution. Generally, a jump in execution of any kind should be avoided because it is not considered good programming practice to use such statements as goto and longjmp in your program.

A goto statement simply bypasses code in your program and jumps to a predefined position. To use the goto statement, you give it a labeled position to jump to. This predefined position must be within the same function. You cannot implement gotos between functions. Here is an example of a goto statement:

void bad_programmers_function(void)
{
int x;
printf("Excuse me while I count to 5000...\n");
x = 1;
while (1)
{
printf("%d\n", x);
if (x == 5000)
goto all_done;
else
x = x + 1;
}
all_done:
printf("Whew! That wasn't so bad, was it?\n");
}

This example could have been written much better, avoiding the use of a goto statement. Here is an example of an improved implementation:

void better_function(void)
{
int x;
printf("Excuse me while I count to 5000...\n");
for (x=1; x<=5000; x++)
printf("%d\n", x);
printf("Whew! That wasn't so bad, was it?\n");
}

As previously mentioned, the longjmp() and setjmp() functions implement a nonlocal goto. When your program calls setjmp(), the current state of your program is saved in a structure of type jmp_buf. Later, your program can call the longjmp() function to restore the program's state as it was when you called setjmp(). Unlike the goto statement, the longjmp() and setjmp() functions do not need to be implemented in the same function.

However, there is a major drawback to using these functions: your program, when restored to its previously saved state, will lose its references to any dynamically allocated memory between the longjmp() and the setjmp(). This means you will waste memory for every malloc() or calloc() you have implemented between your longjmp() and setjmp(), and your program will be horribly inefficient. It is highly recommended that you avoid using functions such as longjmp() and setjmp() because they, like the goto statement, are quite often an indication of poor programming practice.

Here is an example of the longjmp() and setjmp() functions:

#include <stdio.h>
#include <setjmp.h>
jmp_buf saved_state;
void main(void);
void call_longjmp(void);
void main(void)
{
int ret_code;
printf("The current state of the program is being saved...\n");
ret_code = setjmp(saved_state);
if (ret_code == 1)
{
printf("The longjmp function has been called.\n");
printf("The program's previous state has been restored.\n");
exit(0);
}
printf("I am about to call longjmp and\n");
printf("return to the previous program state...\n");
call_longjmp();
}
void call_longjmp(void)
{
longjmp(saved_state, 1);
}

9. What is an lvalue?

An lvalue is an expression to which a value can be assigned. The lvalue expression is located on the left side of an assignment statement, whereas an rvalue is located on the right side of an assignment statement. Each assignment statement must have an lvalue and an rvalue. The lvalue expression must reference a storable variable in memory. It cannot be a constant. For instance, the following lines show a few examples of lvalues:

int x;
int* p_int;
x = 1;
*p_int = 5;

The variable x is an integer, which is a storable location in memory. Therefore, the statement x = 1 qualifies x to be an lvalue. Notice the second assignment statement, *p_int = 5. By using the * modifier to reference the area of memory that p_int points to, *p_int is qualified as an lvalue. In contrast, here are a few examples of what would not be considered lvalues:

#define CONST_VAL 10
int x;
/* example 1 */
1 = x;
/* example 2 */
CONST_VAL = 5;

In both statements, the left side of the statement evaluates to a constant value that cannot be changed because constants do not represent storable locations in memory. Therefore, these two assignment statements do not contain lvalues and will be flagged by your compiler as errors.

10. Can an array be an lvalue?

Is an array an expression to which we can assign a value? The answer to this question is no, because an array is composed of several separate array elements that cannot be treated as a whole for assignment purposes. The following statement is therefore illegal:

int x[5], y[5];

x = y;

You could, however, use a for loop to iterate through each element of the array and assign values individually, such as in this example:

int i;
int x[5];
int y[5];
...
for (i=0; i<5; i++)
x[i] = y[i]
...

Additionally, you might want to copy the whole array all at once. You can do so using a library function such as the memcpy() function, which is shown here:

memcpy(x, y, sizeof(y));

It should be noted here that unlike arrays, structures can be treated as lvalues. Thus, you can assign one structure variable to another structure variable of the same type, such as this:

typedef struct t_name
{
char last_name[25];
char first_name[15];
char middle_init[2];
} NAME;
...
NAME my_name, your_name;
...
your_name = my_name;
...

In the preceding example, the entire contents of the my_name structure were copied into the your_name structure. This is essentially the same as the following line:

memcpy(your_name, my_name, sizeof(your_name));

11. What is an rvalue?

rvalue can be defined as an expression that can be assigned to an lvalue. The rvalue appears on the right side of an assignment statement.

Unlike an lvalue, an rvalue can be a constant or an expression, as shown here:

int x, y;
x = 1; /* 1 is an rvalue; x is an lvalue */
y = (x + 1); /* (x + 1) is an rvalue; y is an lvalue */

An assignment statement must have both an lvalue and an rvalue. Therefore, the following statement would not compile because it is missing an rvalue:
int x; x = void_function_call() /* the function void_function_call() returns nothing */

If the function had returned an integer, it would be considered an rvalue because it evaluates into something that the lvalue, x, can store.

12. Is left-to-right or right-to-left order guaranteed for operator precedence?

The simple answer to this question is neither. The C language does not always evaluate left-to-right or right-to-left. Generally, function calls are evaluated first, followed by complex expressions and then simple expressions.

Additionally, most of today's popular C compilers often rearrange the order in which the expression is evaluated in order to get better optimized code. You therefore should always implicitly define your operator precedence by using parentheses.

For example, consider the following expression:

a = b + c/d / function_call() * 5

The way this expression is to be evaluated is totally ambiguous, and you probably will not get the results you want. Instead, try writing it by using implicit operator precedence:

a = b + (((c/d) / function_call()) * 5)

Using this method, you can be assured that your expression will be evaluated properly and that the compiler will not rearrange operators for optimization purposes.

13. What is the difference between ++var and var++?

The ++ operator is called the increment operator. When the operator is placed before the variable (++var), the variable is incremented by 1 before it is used in the expression. When the operator is placed after the variable (var++), the expression is evaluated, and then the variable is incremented by 1.

The same holds true for the decrement operator (--). When the operator is placed before the variable, you are said to have a prefix operation. When the operator is placed after the variable, you are said to have a postfix operation.

For instance, consider the following example of postfix incrementation:

int x, y;
x = 1;
y = (x++ * 5);

In this example, postfix incrementation is used, and x is not incremented until after the evaluation of the expression is done. Therefore, y evaluates to 1 times 5, or 5. After the evaluation, x is incremented to 2.

Now look at an example using prefix incrementation:

int x, y;
x = 1;
y = (++x * 5);

This example is the same as the first one, except that this example uses prefix incrementation rather than postfix. Therefore, x is incremented before the expression is evaluated, making it 2. Hence, y evaluates to 2 times 5, or 10.

14. What does the modulus operator do?

The modulus operator (%) gives the remainder of two divided numbers. For instance, consider the following portion of code:

x = 15/7

If x were an integer, the resulting value of x would be 2. However, consider what would happen if you were to apply the modulus operator to the same equation:

x = 15%7

The result of this expression would be the remainder of 15 divided by 7, or 1. This is to say that 15 divided by 7 is 2 with a remainder of 1.

The modulus operator is commonly used to determine whether one number is evenly divisible into another. For instance, if you wanted to print every third letter of the alphabet, you would use the following code:

int x;
for (x=1; x<=26; x++)
if ((x%3) == 0)
printf("%c", x+64);

The preceding example would output the string "cfilorux", which represents every third letter in the alphabet.
  #3  
22nd May 2015, 10:05 AM
Unregistered
Guest
 
Re: C Language Basics - C Interview Questions and Answers

Hi I want the Interview Questions and Answers of C Language Basics-C so can you please provide me?
  #4  
22nd May 2015, 10:06 AM
Super Moderator
 
Join Date: Apr 2013
Re: C Language Basics - C Interview Questions and Answers

Ok, as you want the Interview Questions and Answers of C Language Basics-C so here I am pro viding you.

C Language Basics - C Interview Questions


1. What is C language?

The C programming language is a standardized programming language developed in the early 1970s by Ken Thompson and Dennis Ritchie for use on the UNIX operating system. It has since spread to many other operating systems, and is one of the most widely used programming languages. C is prized for its efficiency, and is the most popular programming language for writing system software, though it is also used for writing applications.

2. What does static variable mean?

There are 3 main uses for the static.

1. If you declare within a function: It retains the value between function calls

2. If it is declared for a function name: By default function is extern..so it will be visible from other files if the function declaration is as static..it is invisible for the outer files

3. Static for global variables: By default we can use the global variables from outside files If it is static global..that variable is limited to with in the file.

#include <stdio.h>
int t = 10;
main(){
int x = 0;
void funct1();
funct1();
printf("After first call \n");
funct1();
printf("After second call \n");
funct1();
printf("After third call \n");
}
void funct1()
{
static int y = 0;
int z = 10;
printf("value of y %d z %d",y,z);
y=y+10;
}

value of y 0 z 10 After first call
value of y 10 z 10 After second call
value of y 20 z 10 After third call

3. What are the different storage classes in C?

C has three types of storage: automatic, static and allocated. Variable having block scope and without static specifier have automatic storage duration.

Variables with block scope, and with static specifier have static scope. Global variables (i.e, file scope) with or without the the static specifier also have static scope. Memory obtained from calls to malloc(), alloc() or realloc() belongs to allocated storage class.

4. What is hashing?

To hash means to grind up, and that’s essentially what hashing is all about. The heart of a hashing algorithm is a hash function that takes your nice, neat data and grinds it into some random-looking integer.

The idea behind hashing is that some data either has no inherent ordering (such as images) or is expensive to compare (such as images). If the data has no inherent ordering, you can’t perform comparison searches.

5. Can static variables be declared in a header file?

You can’t declare a static variable without defining it as well (this is because the storage class modifiers static and extern are mutually exclusive). A static variable can be defined in a header file, but this would cause each source file that included the header file to have its own private copy of the variable, which is probably not what was intended.

6. Can a variable be both constant and volatile?

Yes. The const modifier means that this code cannot change the value of the variable, but that does not mean that the value cannot be changed by means outside this code.

The function itself did not change the value of the timer, so it was declared const. However, the value was changed by hardware on the computer, so it was declared volatile. If a variable is both const and volatile, the two modifiers can appear in either order.

7. Can include files be nested?

Yes. Include files can be nested any number of times. As long as you use precautionary measures, you can avoid including the same file twice. In the past, nesting header files was seen as bad programming practice, because it complicates the dependency tracking function of the MAKE program and thus slows down compilation. Many of today’s popular compilers make up for this difficulty by implementing a concept called precompiled headers, in which all headers and associated dependencies are stored in a precompiled state.

8. What is a null pointer?

There are times when it’s necessary to have a pointer that doesn’t point to anything. The macro NULL, defined in , has a value that’s guaranteed to be different from any valid pointer. NULL is a literal zero, possibly cast to void* or char*.

Some people, notably C++ programmers, prefer to use 0 rather than NULL.
The null pointer is used in three ways:
1) To stop indirection in a recursive data structure.
2) As an error value.
3) As a sentinel value.

9. What is the output of printf("%d") ?

When we write printf("%d",x); this means compiler will print the value of x. But as here, there is nothing after %d so compiler will show in output window garbage value.

10. What is the difference between calloc() and malloc() ?

calloc(...) allocates a block of memory for an array of elements of a certain size. By default the block is initialized to 0. The total number of memory allocated will be (number_of_elements * size).

malloc(...) takes in only a single argument which is the memory required in bytes. malloc(...) allocated bytes of memory and not blocks of memory like calloc(...).

malloc(...) allocates memory blocks and returns a void pointer to the allocated space, or NULL if there is insufficient memory available.

calloc(...) allocates an array in memory with elements initialized to 0 and returns a pointer to the allocated space. calloc(...) calls malloc(...) in order to use the C++ _set_new_mode function to set the new handler mode.

11. What is the difference between printf() and sprintf() ?

sprintf() writes data to the character array whereas printf(...) writes data to the standard output device.

12. How to reduce a final size of executable?

Size of the final executable can be reduced using dynamic linking for libraries.

13. Can you tell me how to check whether a linked list is circular?

Create two pointers, and set both to the start of the list. Update each as follows:

while (pointer1) {
pointer1 = pointer1->next;
pointer2 = pointer2->next;
if (pointer2) pointer2=pointer2->next;
if (pointer1 == pointer2) {
print ("circular");
}
}

If a list is circular, at some point pointer2 will wrap around and be either at the item just before pointer1, or the item before that. Either way, its either 1 or 2 jumps until they meet.

14. Advantages of a macro over a function?

Macro gets to see the Compilation environment, so it can expand __ __TIME__ __FILE__ #defines. It is expanded by the preprocessor.

For example, you can’t do this without macros
#define PRINT(EXPR) printf( #EXPR “=%d\n”, EXPR)
PRINT( 5+6*7 ) // expands into printf(”5+6*7=%d”, 5+6*7 );
You can define your mini language with macros:
#define strequal(A,B) (!strcmp(A,B))

15. What is the difference between strings and character arrays?

A major difference is: string will have static storage duration, whereas as a character array will not, unless it is explicity specified by using the static keyword.

Actually, a string is a character array with following properties:
* the multibyte character sequence, to which we generally call string, is used to initialize an array of static storage duration. The size of this array is just sufficient to contain these characters plus the terminating NUL character.
* it not specified what happens if this array, i.e., string, is modified.
* Two strings of same value[1] may share same memory area.

16. Write down the equivalent pointer expression for referring the same element a[i][j][k][l] ?

a[i] == *(a+i)
a[i][j] == *(*(a+i)+j)
a[i][j][k] == *(*(*(a+i)+j)+k)
a[i][j][k][l] == *(*(*(*(a+i)+j)+k)+l)

17. Which bit wise operator is suitable for checking whether a particular bit is on or off?

The bitwise AND operator. Here is an example:

enum {
KBit0 = 1,
KBit1,

KBit31,
};
if ( some_int & KBit24 )
printf ( “Bit number 24 is ON\n” );
else
printf ( “Bit number 24 is OFF\n” );

18. Which bit wise operator is suitable for turning off a particular bit in a number?

The bitwise AND operator, again. In the following code snippet, the bit number 24 is reset to zero.

some_int = some_int & ~KBit24;

19. Which bit wise operator is suitable for putting on a particular bit in a number?

The bitwise OR operator. In the following code snippet, the bit number 24 is turned ON:
some_int = some_int | KBit24;

20. Does there exist any other function which can be used to convert an integer or a float to a string?

Some implementations provide a nonstandard function called itoa(), which converts an integer to string.

#include
char *itoa(int value, char *string, int radix);
DESCRIPTION
The itoa() function constructs a string representation of an integer.
PARAMETERS
value: Is the integer to be converted to string representation.
string: Points to the buffer that is to hold resulting string.
The resulting string may be as long as seventeen bytes.
radix: Is the base of the number; must be in the range 2 - 36.
A portable solution exists. One can use sprintf():
char s[SOME_CONST];
int i = 10;
float f = 10.20;
sprintf ( s, “%d %f\n”, i, f );

21. Why does malloc(0) return valid memory address ? What's the use?

malloc(0) does not return a non-NULL under every implementation. An implementation is free to behave in a manner it finds suitable, if the allocation size requested is zero. The implmentation may choose any of the following actions:

* A null pointer is returned.
* The behavior is same as if a space of non-zero size was requested. In this case, the usage of return value yields to undefined-behavior.

Notice, however, that if the implementation returns a non-NULL value for a request of a zero-length space, a pointer to object of ZERO length is returned! Think, how an object of zero size should be represented

For implementations that return non-NULL values, a typical usage is as follows:
void
func ( void )
{
int *p; /* p is a one-dimensional array, whose size will vary during the the lifetime of the program */
size_t c;
p = malloc(0); /* initial allocation */
if (!p)
{
perror (”FAILURE” );
return;
}
/* … */
while (1)
{
c = (size_t) … ; /* Calculate allocation size */
p = realloc ( p, c * sizeof *p );
/* use p, or break from the loop */
/* … */
}
return;
}
Notice that this program is not portable, since an implementation is free to return NULL for a malloc(0) request, as the C Standard does not support zero-sized objects.

22. Difference between const char* p and char const* p

In const char* p, the character pointed by ‘p’ is constant, so u cant change the value of character pointed by p but u can make ‘p’ refer to some other location.

In char const* p, the ptr ‘p’ is constant not the character referenced by it, so u cant make ‘p’ to reference to any other location but u can change the value of the char pointed by ‘p’.

23. What is the result of using Option Explicit?

When writing your C program, you can include files in two ways. The first way is to surround the file you want to include with the angled brackets < and >. This method of inclusion tells the preprocessor to look for the file in the predefined default location. This predefined default location is often an INCLUDE environment variable that denotes the path to your include files.

For instance, given the INCLUDE variable
INCLUDE=C:\COMPILER\INCLUDE;S:\SOURCE\HEADERS; using the #include version of file inclusion, the compiler first checks the C:\COMPILER\INCLUDE directory for the specified file. If the file is not found there, the compiler then checks the S:\SOURCE\HEADERS directory. If the file is still not found, the preprocessor checks the current directory.

The second way to include files is to surround the file you want to include with double quotation marks. This method of inclusion tells the preprocessor to look for the file in the current directory first, then look for it in the predefined locations you have set up. Using the #include file version of file inclusion and applying it to the preceding example, the preprocessor first checks the current directory for the specified file. If the file is not found in the current directory, the C:COMPILERINCLUDE directory is searched. If the file is still not found, the preprocessor checks the S:SOURCEHEADERS directory.

The #include method of file inclusion is often used to include standard headers such as stdio.h or stdlib.h.

The #include file include nonstandard header files that you have created for use in your program. This is because these headers are often modified in the current directory, and you will want the preprocessor to use your newly modified version of the header rather than the older, unmodified version.



24. What is the benefit of using an enum rather than a #define constant?

The use of an enumeration constant (enum) has many advantages over using the traditional symbolic constant style of #define. These advantages include a lower maintenance requirement, improved program readability, and better debugging capability.
1) The first advantage is that enumerated constants are generated automatically by the compiler. Conversely, symbolic constants must be manually assigned values by the programmer.
2) Another advantage of using the enumeration constant method is that your programs are more readable and thus can be understood better by others who might have to update your program later.

3) A third advantage to using enumeration constants is that some symbolic debuggers can print the value of an enumeration constant. Conversely, most symbolic debuggers cannot print the value of a symbolic constant. This can be an enormous help in debugging your program, because if your program is stopped at a line that uses an enum, you can simply inspect that constant and instantly know its value. On the other hand, because most debuggers cannot print #define values, you would most likely have to search for that value by manually looking it up in a header file.



25. What is the quickest sorting method to use?

The answer depends on what you mean by quickest. For most sorting problems, it just doesn’t matter how quick the sort is because it is done infrequently or other operations take significantly more time anyway. There are three sorting methods in this author’s toolbox that are all very fast and that are useful in different situations. Those methods are quick sort, merge sort, and radix sort.

26. When should the volatile modifier be used?

The volatile modifier is a directive to the compiler’s optimizer that operations involving this variable should not be optimized in certain ways. There are two special cases in which use of the volatile modifier is desirable. The first case involves memory-mapped hardware (a device such as a graphics adaptor that appears to the computer’s hardware as if it were part of the computer’s memory), and the second involves shared memory (memory used by two or more programs running simultaneously).

27. When should the register modifier be used?

The register modifier hints to the compiler that the variable will be heavily used and should be kept in the CPU’s registers, if possible, so that it can be accessed faster.

28. How can you determine the size of an allocated portion of memory?

You can’t, really. free() can , but there’s no way for your program to know the trick free() uses. Even if you disassemble the library and discover the trick, there’s no guarantee the trick won’t change with the next release of the compiler.

29. When does the compiler not implicitly generate the address of the first element of an array?

Whenever an array name appears in an expression such as
• array as an operand of the size of operator
• array as an operand of & operator
• array as a string literal initializer for a character array
Then the compiler does not implicitly generate the address of the address of the first element of an array.

30. Why n++ executes faster than n+1 ?

The expression n++ requires a single machine instruction such as INR to carry out the increment operation whereas, n+1 requires more instructions to carry out this operation.

31. Why doesn't the following statement work?

char str[ ] = "Hello" ;
strcat ( str, '!' ) ;

Answer: The string function strcat( ) concatenates strings and not a character. The basic difference between a string and a character is that a string is a collection of characters, represented by an array of characters whereas a character is a single character. To make the above statement work writes the statement as shown below:

strcat ( str, "!" ) ;

32. What is the benefit of using #define to declare a constant?

Using the #define method of declaring a constant enables you to declare a constant in one place and use it throughout your program. This helps make your programs more maintainable, because you need to maintain only the #define statement and not several instances of individual constants throughout your program.

For instance, if your program used the value of pi (approximately 3.14159) several times, you might want to declare a constant for pi as follows: #define PI 3.14159

Using the #define method of declaring a constant is probably the most familiar way of declaring constants to traditional C programmers. Besides being the most common method of declaring constants, it also takes up the least memory.

Constants defined in this manner are simply placed directly into your source code, with no variable space allocated in memory. Unfortunately, this is one reason why most debuggers cannot inspect constants created using the #define method.



33. What is the purpose of main( ) function ?

The function main( ) invokes other functions within it.It is the first function to be called when the program starts execution.

• It is the starting function
• It returns an int value to the environment that called the program
• Recursive call is allowed for main( ) also.
• It is a user-defined function
• Program execution ends when the closing brace of the function main( ) is reached.
• It has two arguments 1)argument count and 2) argument vector (represents strings passed).
• Any user-defined name can also be used as parameters for main( ) instead of argc and argv



34. How can I search for data in a linked list?

Unfortunately, the only way to search a linked list is with a linear search, because the only way a linked list’s members can be accessed is sequentially.
Sometimes it is quicker to take the data from a linked list and store it in a different data structure so that searches can be more efficient.



35. Why should we assign NULL to the elements (pointer) after freeing them?

This is paranoia based on long experience. After a pointer has been freed, you can no longer use the pointed-to data. The pointer is said to dangle; it doesn’t point at anything useful.

If you NULL out or zero out a pointer immediately after freeing it, your program can no longer get in trouble by using that pointer. True, you might go indirect on the null pointer instead, but that’s something your debugger might be able to help you with immediately.

Also, there still might be copies of the pointer that refer to the memory that has been deallocated; that’s the nature of C. Zeroing out pointers after freeing them won’t solve all problems.



36. What is a null pointer assignment error? What are bus errors, memory faults, and core dumps?

These are all serious errors, symptoms of a wild pointer or subscript. Null pointer assignment is a message you might get when an MS-DOS program finishes executing. Some such programs can arrange for a small amount of memory to be available “where the NULL pointer points to (so to speak). If the program tries to write to that area, it will overwrite the data put there by the compiler.

When the program is done, code generated by the compiler examines that area. If that data has been changed, the compiler-generated code complains with null pointer assignment. This message carries only enough information to get you worried. There’s no way to tell, just from a null pointer assignment message, what part of your program is responsible for the error. Some debuggers, and some compilers, can give you more help in finding the problem.

Bus error: core dumped and Memory fault: core dumped are messages you might see from a program running under UNIX. They’re more programmer friendly. Both mean that a pointer or an array subscript was wildly out of bounds. You can get these messages on a read or on a write. They aren’t restricted to null pointer problems. The core dumped part of the message is telling you about a file, called core, that has just been written in your current directory. This is a dump of everything on the stack and in the heap at the time the program was running. With the help of a debugger, you can use the core dump to find where the bad pointer was used. That might not tell you why the pointer was bad, but it’s a step in the right direction. If you don’t have write permission in the current directory, you won’t get a core file, or the core dumped message



37. Predict the output or error(s) for the following programmes:

void main()
{
int const * p=5;
printf("%d",++(*p));
}

Answer: Compiler error: Cannot modify a constant value.
Explanation: p is a pointer to a "constant integer". But we tried to change the value of the "constant integer".

38. main()
{
char s[ ]="man";
int i;
for(i=0;s[ i ];i++)
printf("\n%c%c%c%c",s[ i ],*(s+i),*(i+s),i[s]);
}

Answer:
mmm
aaaa
nnnn

Explanation: s[i], *(i+s), *(s+i), i[s] are all different ways of expressing the same idea. Generally array name is the base address for that array. Here s is the base address. i is the index number/ displacement from the base address. So, indirecting it with * is same as s[i]. i[s] may be surprising. But in the case of C it is same as s[i].



39. main()
{
float me = 1.1;
double you = 1.1;
if(me==you)
printf("I love U");
else
printf("I hate U");
}

Answer: I hate U
Explanation: For floating point numbers (float, double, long double) the values cannot be predicted exactly. Depending on the number of bytes, the precession with of the value represented varies. Float takes 4 bytes and long double takes 10 bytes. So float stores 0.9 with less precision than long double.

Rule of Thumb: Never compare or at-least be cautious when using floating point numbers with relational operators (== , >, <, <=, >=,!= ) .



40. main()
{
static int var = 5;
printf("%d ",var--);

if(var)
main();
}

Answer: 5 4 3 2 1
Explanation: When static storage class is given, it is initialized once. The change in the value of a static variable is retained even between the function calls. Main is also treated like any other ordinary function, which can be called recursively.



41. main()
{
int c[ ]={2.8,3.4,4,6.7,5};
int j,*p=c,*q=c;
for(j=0;j<5;j++) {
printf(" %d ",*c);
++q; }
for(j=0;j<5;j++){
printf(" %d ",*p);
++p; }
}

Answer: 2 2 2 2 2 2 3 4 6 5

Explanation: Initially pointer c is assigned to both p and q. In the first loop, since only q is incremented and not c , the value 2 will be printed 5 times. In second loop p itself is incremented. So the values 2 3 4 6 5 will be printed.



42. main()
{
extern int i;
i=20;
printf("%d",i);
}

Answer: Linker Error : Undefined symbol '_i'

Explanation: extern storage class in the following declaration,
extern int i;
specifies to the compiler that the memory for i is allocated in some other program and that address will be given to the current program at the time of linking. But linker finds that no other variable of name i is available in any other program with memory space allocated for it. Hence a linker error has occurred .



43. main()
{
int i=-1,j=-1,k=0,l=2,m;
m=i++&&j++&&k++||l++;
printf("%d %d %d %d %d",i,j,k,l,m);
}

Answer: 0 0 1 3 1

Explanation: Logical operations always give a result of 1 or 0. And also the logical AND (&&) operator has higher priority over the logical OR (||) operator. So the expression ‘i++ && j++ && k++’ is executed first. The result of this expression is 0 (-1 && -1 && 0 = 0). Now the expression is 0 || 2 which evaluates to 1 (because OR operator always gives 1 except for ‘0 || 0’ combination- for which it gives 0). So the value of m is 1. The values of other variables are also incremented by 1.



44. main()
{
char *p;
printf("%d %d ",sizeof(*p),sizeof(p));
}

Answer: 1 2

Explanation: The sizeof() operator gives the number of bytes taken by its operand. P is a character pointer, which needs one byte for storing its value (a character). Hence sizeof(*p) gives a value of 1. Since it needs two bytes to store the address of the character pointer sizeof(p) gives 2.



45. main()
{
int i=3;
switch(i)
{
defaultrintf("zero");
case 1: printf("one");
break;
case 2rintf("two");
break;
case 3: printf("three");
break;
}
}

Answer : Three

Explanation: The default case can be placed anywhere inside the loop. It is executed only when all other cases doesn't match.



46. main()
{
printf("%x",-1<<4);

}

Answer: fff0

Explanation: -1 is internally represented as all 1's. When left shifted four times the least significant 4 bits are filled with 0's.The %x format specifier specifies that the integer value be printed as a hexadecimal value.



47. main()
{
char string[]="Hello World";
display(string);
}
void display(char *string)
{
printf("%s",string);
}

Answer: Compiler Error: Type mismatch in redeclaration of function display

Explanation: In third line, when the function display is encountered, the compiler doesn't know anything about the function display. It assumes the arguments and return types to be integers, (which is the default type). When it sees the actual function display, the arguments and type contradicts with what it has assumed previously. Hence a compile time error occurs.



48. main()
{
int c=- -2;
printf("c=%d",c);
}

Answer: c=2;

Explanation: Here unary minus (or negation) operator is used twice. Same maths rules applies, ie. minus * minus= plus.

Note: However you cannot give like --2. Because -- operator can only be applied to variables as a decrement operator (eg., i--). 2 is a constant and not a variable.



49. #define int char
main()
{
int i=65;
printf("sizeof(i)=%d",sizeof(i));
}

Answer: sizeof(i)=1

Explanation: Since the #define replaces the string int by the macro char

50. main()
{
int i=10;
i=!i>14;
Printf ("i=%d",i);
}

Answer: i=0

Explanation: In the expression !i>14 , NOT (!) operator has more precedence than ‘ >’ symbol. ! is a unary logical operator. !i (!10) is 0 (not of true is false). 0>14 is false (zero).


Quick Reply
Your Username: Click here to log in

Message:
Options




All times are GMT +5. The time now is 06:40 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
SEO by vBSEO 3.6.0 PL2

1 2 3 4