Você está na página 1de 111

1

C Quiz - Week 1
1)What is the output of following program? main() { int x = -10; printf("%d\n", ~x+1); } a)-11 b)-9 c)10 d)Size of the integer is required to findout the answer. The correct answer is c. ~x is one's compliment of x. ~x+1 is two complement of x. Since negative numbers are represented in 2's complement form, (~x+1) would always evaluate to the negative of a given integer. 2)What is the output of following program? main() { printf("%c\n", '1' + 1); } a)ASCII value of '1' is required to find out the answer b)2 c)50 d)Syntax Error The correct answer is b. '1' + 1 is evaluated as 0x31 + 1. Which is nothing but the ASCII value of '2'. 3)What is the output of following program? main() { char x = 0x80; int y = x; printf("%d\n", y); } a)0 b)128 c)-128 d)Unpredictable

2 The correct answer is c. x is defined as a signed character. With 8 bits, data range that can be represented is -128 to +127. So, 0x80 represents -128. When assigned to an integer, -128 remains as is. Since the MSB is the sign bit, when value of signed char is 0x80, sign bit is set. When this value is assigned to a signed integer, the sign bit would get extended. Internally the value stored in y would be 0xFFFFFF80 which is the value of -128. Note that sign extension happens only for signed data tyes. The value would show up as 128 if y was declared as unsigned. 4)What is the output of following program in a little endian machine? main() { int x = 0xdeadbeef; char y = x; printf("%x\n", y); } a)de b)ef c)0 d)Unpredictable The correct answer is b. In Little endian machines, the least significant byte occupies the lower most address. The higher order bytes follow. 5)What is the output of following program? main() { char y[10] = "abcdefghi"; char *p = y; p = p + 9; printf("%c\n",*p); } a)i b)Program will have runtime error c)Unpredictable d)No visible output The correct answer is d. To begin with p points to first character. Adding 9 to it, makes it point to '0' since the string is terminated by a NULL value. So when 9 is added to p which is a char pointer it points to an empty string and hence no output will be printed on the screen. 6)What is the output of following program? main() {

3 int y[2][2] = { {1,2}, {3,4} }; int *p = &y[1]; p = p + 1; printf("%d\n",*p); } a)4 b)3 c)The program doesn't compile d)Output is unpredicatable The correct answer is a. Note that array indexing starts with 0. So, &y[1] points to 3. After incrementing the integer pointer p by 1, it would point to 4. 7) typedef struct date { int day; int month; int year; } MYDATE; Given the above the typedefinition, which of the following statements are correct declarations? 1. date x; 2. MYDATE x; 3. struct date x; 4. struct MYDATE x; a)2 & 3 b)1 & 2 c)3 & 4 d)1 & 4 The correct answer is a. This type defintion equates struct date to MYDATE. So, you can either use MYDATE x or without this aliasing, use struct date x. 8) main() { printf("%d\n",f1(10,10)); } Assuming f1 is defined in another file, which of the following statements are acceptable by compiler as function prototype of f1. 1. extern int f1(); 2. extern f1(int, int);

4 3. extern f1(); 4. extern int f1(int, int); a)All of them b)4 c)3 d)1 & 4 The correct answer is a. To keep compiler happy, just an extern f1() is enough. However, it is good practice to give complete prototype extern int f1(int, int). 9)What is output of following program? int y = 10; main() { int x = 10; int y = 20; x = x + y; if (x >= 30) { int y = 30; x = x + y; } else { int y = 40; x = x + y; } printf("%d\n", x); } a)40 b)50 c)60 d)70 The correct answer is c. To begin with, value of x is 10. After x = x + y, it value becomes 30. Control will then get into the if block since x is 30. Within the if block, value of y is 30 and hence x becomes 60. 10)What is output of following program? main() { int x = 10; int y = 20; if (x & y)

5 if(x | y) x = 20; else x = 30; printf("%d\n", x); } a)10 b)20 c)30 d)Unpredictable The correct answer is a. Note that else belongs to second if. It is always a good practice to put even single line blocks also within braces to avoid such confusion. Also, appropriate indentation would enhance readability significantly giving lesser scope to misinterpretation of code. 11)What is output of following program? main() { int x = 1; int y = 2; switch(x | y) { case 1: x = 2; case 2: x = 3; case 3: x = 4; case 4: x = 5; default:x = 6; } printf("%d\n", x); } a)6 b)4 c)5 d)3 The correct answer is a. There are no break statements so, irrespective of the value of x, last case (default) will be executed. This is an example of fall-through situation. 12) #define MAKEDOUBLE(x) x+x a = MAKEDOUBLE(4) * 3; VALUE OF a a)24

6 b)16 c)8 d)None The correct answer is b. MAKEDOUBLE(4) * 3 translates 4 + 4 * 3. Since, * has higher precedence than +, it becomes 4 + 12, i.e 16. To avoid such problems, the macro should be defined as MAKEDOUBLE(x) ((x) + (x)) 13)What happens when the following code segment is executed? main() { int i = 8; i = i++; } a)i takes value 8 b)i takes value 9 c)response is compiler dependent and hence unpredictable d)syntax is invalid The correct answer is c. A post increment or decrement means that update will be performed sometime before expression evaluation is complete. However, value of i is changing twice within the expression. So, the sequence in which i will be incremented is unknown. Some compilers will give 8 or 9 or something else, but as per C grammar, such statements are undefined and behaviour is left to the compiler. 14)Consider the following C code segment: void function(int *ip) { static int myValue = 100; ip = &myValue; } main() { int *myPointer; function(myPointer); } What happens when the following call is made: a)myPointer value remains unchanged b)myPointer gets modified to point to address of myValue c)Response is compiler dependent d)Code does not compile

7 The correct answer is a. Note that the pointer is passed to function using call by value only. Only for the contents pointed by pointer, it is equvalent to call by reference. 15)What is the output of the following program? int x[100]; main() { printf("%d\n",x[99]); } a)Unpredicatable b)Runtime error c)0 d)99 The correct answer is c. In C, it is guaranteed that all the uninitialised global variables are initialised to 0. 16)What is the output of the following program? main() { printf("%d\n", 100 / 10 / 10); } a)1 b)100 c)10 d)0 The correct answer is a. For most of operators in C, the order of evaluation is from left to right. (exceptions: unary, ternary and assignment operators). So, 100/10/10 is evaluated as (100/10)/10 which is equal to 1. 17) main() { int a=5; if (a=1) { printf("%d", a); } } In the above code a)The printf statement will never get executed

8 b)The printf statement will always get executed and the value of a will be printed as 5 c)The program will encounter syntax error d)The printf statement will always get executed and the value of a will be printed as 1 The correct answer is d. In C, the assignment operation also evaluates to the RHS of the assignment operator. The expression (a=1) assigns 1 to a and also returns 1. So, the if condition is successful and value of a is printed as 1. 18) int main() { int a[10]; int i; for (i=0; i<10; i++) a[i] = i; printf("%d", a[-1]); } The above program a)Will encounter a compilation error b)Will encounter segmentation violation when run c)Will have unpredictable behavior d)Will get into infinite loop The correct answer is c. The array a[10] is in stack. So, a[-1] will point to some location within stack and its content is unpredicatable. 19)What is the output of the following program? main() { int a=3, b=5, c=1; int x=8; x = a < (b < c); printf("%d", x); } a)1 b)8 c)Will encounter run time error d)0 The correct answer is d. The expression (b < c) is evaluated first. It is equivalent to (5 < 1) and this expression will return 0. So, the next part of expression will become a < 0 which is equivalent to 3 < 0 and hence result is 0. This result is assigned to x and hence value of x becomes 0.

9 20)What is the octal equivalent of the binary number 10111000 a)b8 b)560 c)270 d)None of the above The correct answer is c. The binary number 10111000 is equivalent to decimal number 184 (2**7+2**5+2**4+2**3). When 184 is converted to octal it becomes 270. Alternately, we can also compute directly from the binary number by taking 3 bits at a time from the LSB. So the bits in the binary number 10111000, put in groups of 3 bits would be (10)(111)(000) which is 270 in octal 21)How many times is "Hello world" is printed in following program. main() { unsigned int i = 5; while (--i >= 0) { printf("Hello World\n"); } } a)5 b)6 c)Infinite d)Program will not compile The correct answer is c. Being an unsigned number, value of i cannot be less than 0. So, the statement i >= 0 will be always true. Hence, this program goes into an infinite loop. When i becomes 0 and decremented further, it wraps around and becomes MAXINT. 22)What would be the Output of the following program? main() { extern int change(float); int x; x = change(5.42); printf("%d\n", x); } int change(float x) {

10 return ((int)x); } a)0 b)5 c)5.42 d)None of the above The correct answer is b. In the return statement, x is cast to int and hence it will lose its decimal part. So, value of x in the main function will become 5. 23)Binary equivalent of 5.375 is a)101.101110111 b)101.011 c)101011 d)None of the above The correct answer is b. To convert 5 to binary number, repeated division by 2 is done and remainders are arranged to form the number 101. For the decimal part, you got to multiply by 2 and store the non-decimal part, until decimal part becomes zero. i.e 0.375 * 2 = 0.750 (first digit 0) 0.750 * 2 = 1.50 (second digit 1) 0.5 * 2 = 1.0 (third digit 1) So the final value is 101.011 24)The preprocessor can trap simple errors like missing declarations, nested comments or mismatch of braces a)True b)False c)Depends on the compiler d)None of the above The correct answer is b. The only function of pre-processor is to expand macros. They can be thought of as intelligent text processors. Only compilers have the capability to perform syntax checking. 25)What is the output of the following program. main() { char str[7] = "Strings"; printf("%s", str); }

11 a)Strings b)Not predicatable c)Compilation error d)None of the above The correct answer is b. "Strings" is internally stored as "Strings\0" which needs 8 bytes of storage space. Since only 7 bytes are allocated for the str, '\0' is written into some location in stack after 7 bytes and this results in stack corruption. So, the behaviour is not predictable. 26)What is the output of following program? main() { int y = 100; const int x = y; printf("%d\n", x); } a)100 b)Garbage value c)Error d)0 The correct answer is a. It is ok to initialise a const variable with another variable. The keyword const indicates that once initialised, it shouldn't be changed. 27)How many times "Hello World" will be printed in the following program? main() { int i, j, k; for(i = 1; i <= 2; ++i) for(j = 1; j <= i; ++j) for(k = i; k <= j; ++k) printf("Hello World\n"); } a)2 b)8 c)16 d)4 The correct answer is a. First time, value of i is 1, j = 1, k = i = 1. So, Hello world is printed once. Second time, value of i is 2, j = 1, k = i = 2. So, Hello World is not printed. Third time, value of i is 2, j = 2, k = i = 2. So Hello World is printed once more. So, totally it prints Hello world twice.

12 28)The keyword 'static' when used with a variable defined outside of any function in C means:

a)The variable's value cannot be changed by any function in the program b)The variable is stored in non-volatile memory that retains value across power cycles c)The variable is accessible only to functions defined in the same file d)Can be used only by functions that are statically linked The correct answer is c. Static has two purposes. If used in global scope, it ensures that scope of static variable is restricted to file level. If used at function level, it ensures that value of the that static local variable is retained across functions calls. 29)The keyword 'volatile' when used with a variable in C means: a)The variable is stored in volatile memory (RAM) that does not retain value across a power cycle b)The value of the variable can change asynchronous to program execution c)The variable's value is not initialized by the start-up code d)Suggests that the compiler stores the value in registers The correct answer is b. Volatile tells compiler not to do any optimisation on that variable. It is typically useful for pointers to memory mapped area where contents can change outside the scope of program. 30)What does the value stored in a function pointer variable contain? a)Address of the Variable that contains a function address b)Starting address of the function c)Address of the link table d)Stack Frame of the function The correct answer is b. Function pointers always point to the starting address of a function. So that, if they are called, the control goes to the starting of the function. 31)In a C file, the following line is present: #define FAST_COMPUTE When trying to compile the program, a)The C preprocessor gives an error b)The C compiler gives an error c)The program compiles normally d)The assembler gives an error

13 The correct answer is c. As far as the pre-processor is concerned, FAST_COMPUTE is defined but doesn't have a value. So, the statements like ifdef FAST_COMPUTE will succeed. 32)In a C Program, stack is used for a)Storing local variables only b)Storing local variables and passing parameters c)Passing parameters only d)Storing local static variables The correct answer is b. Stack is used for storing local variables as well as for passing parameters. Calling function pushes the arguments into stack before control transfers to the called function. In addition, return address and values of registers also get pushed on to the stack. 33)Memory leak in a program is mostly due to a)RAM becoming bad during program execution b)linker defects c)Improper use of dynamic memory in the code or the libraries used d)Compiler Defects The correct answer is c. Whenver memory is allocated dynamically and not freed, this situation is called as memory leak. Memory leak is a serious problem and difficult to locate. Tools like purify are used to detect the memory leaks faster. It is possible to avoid memory leak by following certain coding guidelines.

C Quiz - Week 2
1) int main() { int i = 0; int sizeint; sizeint = sizeof i++; printf("%d\n", i); return 0; } Considering that integer requires 4 bytes of memory, the value of i printed by the above program is: a)1 b)4 c)0 d)The above program encounters a compilation error.

14

The correct answer is c. sizeof is an operator. Once the sizeof the type int is determined, the expression is not evaluated any further since sizeof(i++) and sizeof(i) both are same as sizeof(int) 2) int main() { int i = 0; int sizeint; sizeint = sizeof(i++); printf("%d\n", sizeint); return 0; } a)1 b)2 c)4 d)The output will be machine dependent The correct answer is d. In the above program, i is of integer type. An integer could occupy either 2 or 4 or more bytes depending on the architecture of the machine. 3) int main() { int j = 6; int i; i = 5, j++; printf("%d\n", i); return 0; } Which of the following statements are true about the code snippet given above a)The code does not compile. b)5 c)6 d)The result in machine dependent. The correct answer is b. Comma is a series operator. In a statement like what is shown above, first assignment is performed and then next part of the statement is evaluated. 4) int main() {

15 int j=6; int i; i = (5, j); printf("%d %d\n", i, j); return 0; } The output from the above program is: a)5 6 b)6 6 c)6 7 d)The output is machine dependent The correct answer is b. (5, j) is first evaluated as (5, 6). When placed in parenthesis (5,6) would return 6 which gets assigned to i. 5) int main() { int j=6; int i; i = (5, j++); printf("%d %d\n", i, j); return 0; } The output from the above program is: a)5 6 b)6 6 c)6 7 d)The output is machine dependent The correct answer is c. (5, j++) is first evaluated as (5, 6). When placed in parenthesis (5,6) would return 6 which gets assigned to i. Then j is incremented. 6) What is the output of following program? main() { int x=10; x = x++; printf("%d\n", x); } a)10 b)11

16 c)12 d)Depends on the compiler. The correct answer is d. x is changed twice in the expression and the order in which x is updated, is not known. As per C language grammar, the result is undefined. So, output is compiler specific. 7) What is the output of following program? main() { int x = 0; int y; y = (x++, x++); printf("%d", y); } a)0 b)1 c)2 d)Compiler Dependent The correct answer is b. Like semicolon character, comma ensures that x is incremented before going to the second part. Paranthesis ensures that result of second part is assigned to y and x is post-incremented after the assigning the result. 8) What is the output of following program? main() { int x = 0; int y = 2; if (1 < ++x | 2 < y++) { ++y; } printf("%d %d\n", x, y); } a)1 2 b)1 3 c)1 4 d)Compiler Error The correct answer is b. Precedence order: ++ followed by < followed by |. The given expression is equivalent to ((1 < ++x) | (2 < y++)). Since post increment

17 happens only after the expression evaluated, this overall condition doesn't succeed and hence ++y is not done. 9) What is the output of following program? main() { int x = 0; int y = 0; if (x++ && ++y) { ++x; } printf("%d %d\n",x, y); } a)0 0 b)1 0 c)2 0 d)2 1 The correct answer is b. x++ translates to 0 (and then x is incremented to 1). Since FALSE && (anything) would become zero, the second part is not evaluated (shortcircuited). And overall condition is false and hence ++x is not executed. 10) What is the output of following program? main() { int x = 0; int y = 0; if (++x || ++y) { x++; } printf("%d %d\n",x, y); } a)1 1 b)1 0 c)2 1 d)2 0 The correct answer is d. ++x translates to 1. Since (TRUE || anything) would be TRUE, the second part is not evaluated. Since overall condition is successful, x++ is executed.

18

11) What is the output of following program? main() { int x = 0; int y = 0; if (!(++x && ++y)) { x++; } printf("%d %d\n",x, y); } a)1 1 b)1 0 c)2 1 d)2 0 The correct answer is a. ++x translates to 1. ++y also needs to be evaluated as we have && operator. ++y translates to 1. !(TRUE && TRUE) translates to FALSE. Since overall condition translates to FALSE, x++ is not executed. 12) What is the output of following program? main() { int x = 0; int y = 0; if (!(++x || ++y)) { x++; } printf("%d %d\n",x, y); } a)1 0 b)1 1 c)2 1 d)2 0 The correct answer is a. ++x translates to 1. The second part need to be evaluated as (TRUE || anything) would be TRUE. Since there is an overall NOT, condition translates to FALSE, x++ is not executed.

19 13) What is the output of following program? main() { int x = 0x01C0FFEE; int y = x >> 15 + 1 & 0xFF; printf("%x\n", y); } a)C0 b)82 c)1C0 d)382 The correct answer is a. Operator precedence is: + followed by >> followed by &. The given expression is equivalent to y = (x >> (15 + 1)) & 0xFF; 14) What is the output of following program? main() { int x = 0xdeadbeef; int y = ~0xdeadbabe ^ x & 0xFFFF; printf("%x\n", y); } a)2152FBAE b)FBAE c)Compiler Error d)0 The correct answer is a. Precedence order: ~ followed by & followed by ^. The given expression is equivalent to (~0xdeadbabe) ^ (x & 0xFFFF). 15) What is the output of following program? main() { int x = 10; int y = 20; if (x <= y == 1) { ++x; } printf("%d\n", x); }

20

a)11 b)10 c)Compiler Dependent d)Syntax Error The correct answer is a. Predence: <= followed by ==. The given expression is equivalent to (x <= y) == 1. 16) What is the output of following program? main() { int x = 1; int y = 0; if (x | y++) { ++y; } printf("%d %d\n", x, y); } a)Compiler Dependent b)1 1 c)1 0 d)1 2 The correct answer is d. The expression (x | y++) has bit-wise OR. i.e the expression would always be evaluated fully. Therefore y would get incremented twice (unlike logical OR ||, where evaluation of expression may be done partially based on partial result). 17) What is the output of following program? int x; int f() { x += 10; return x; } int g() { x /= 10 ;

21 return x; } int h() { x *=2; return x; } int main() { x = 10; printf("%d\n", f() + g() * h()); } a)14 b)28 c)52 d)88 The correct answer is b. Functions will be called in left-to-right order. To begin with, value of x is 10. Function f() adds 10 to x and returns 20. Function g() divides x by 10 and returns 2. Function h() multiplies x by 2 and returns 4. After all the functions are called, the expression 20 + 2 * 4 will be evaluated and printed as 28. 18) What is the output of the following program? int main() { int x=10; int *y=&x; x = x+ *y*x/ *y ; printf("%d\n",x); } a)Syntax Error b)20 c)Runtime error d)Unpredictable Output The correct answer is b. Note the spaces in front of *y. Both x and *y have value of 10. Derefencing * has more precedence than multiplication *. So, the given expression is equivalent to 10 + 10 * 10 / 10. Which evaluates to 20.. 19) What is the output of the following program?

22 int main() { int a = 0; int b; b = (a++)? a++: a++; printf("%d %d\n", a,b); } a)2 1 b)2 2 c)Syntax Error d)Unpredictable The correct answer is a. The expression b=(a++)?a++:a++ is equivalent to if (a++) { b=a++; } else { b=a++; } Since value of a is 0, if the condition is not satisifed. After condition is checked, a is post incremented. Then else part is executed. Value of a (1) is assigned to b and a is post incremented to 2. So, the correct answer is 2 1. 20) What is the output of the following program? int main() { int a = 0; int b = 1; int c;

c = a?1:b?2:3; printf("%d\n", c); } a)1 b)2 c)3 d)Syntax Error

23 The correct answer is b. The expression a?b?1:2:3 is equivalent to a?1:(b?2:3). (As ternary operators are right to left associative). Since a is 0, else part is executed. In the else part b is non-zero, so value of 2 is assigned to c.

C Quiz - Week 3
1) What is the output of following program? #define DOUBLE(x) x + x main() { printf("%d\n", DOUBLE(10)*2); } a)20 b)30 c)40 d)Syntax error The correct answer is b. DOUBLE(10)*2 would expand as 10 + 10 * 2. Since * has more precedence than +, this expression will be evaluated as 10 + 20 (30). 2) What is the output of following program? #define SQUARE(x) (x * x) main() { int x = 10; int y = 5; printf("%d\n", SQUARE(x +y)); } a)225 b)45 c)65 d)Syntax error The correct answer is c. SQUARE(x+y) would expand as (10 + 5 * 10 + 5). Since * has more precedence than +, this expression will be evaluated as 10 + 50 + 5 (65). 3) What is the output of following program? #define ABC(x) DEF(x) #define DEF(x) GHI(x) #define GHI(x) printf x main()

24 { int x = 100; ABC(("value of x is %d\n", x)); } a)value of x is 100 b)Syntax error c)Linker error d)Runtime error The correct answer is a. Because of additional paranthesis in ABC(("value of x is %d\n", x)), the entire ("value of x is %d\n", x) (including the paranthesis) goes as an argument to macro ABC. Eventually, it is expanded to printf ("value of x is %d\n", x). Note the space between printf and ( in the last sentence as well as space between printf and x in the macro GHI. 4) What is the output of following program? #define ABC(x) DEF(x) #define DEF(x) GHI(x) #define GHI(x) printf(x) main() { int x = 100; int y = 200; ABC(("Sum of x + y is %d", x + y)); } a)Sum of x + y is 300 b)Syntax error c)Linker error d)Runtime error or unpredictable behaviour The correct answer is d. Because of additional paranthesis in ABC(("Sum of x + y is %d\n", x + y)), the entire ("Sum of x + y is %d\n", x + y) (including the paranthesis) goes as an argument to macro ABC. Eventually it is expanded to printf(("Sum of x + y is %d\n", x + y)). This is equivalent to passing only one argument to printf. So, when printf tries to access an integer (due to %d) from the stack, it would result in runtime error or unpredictable behaviour. 5) What is the output of following program? #define ABC(x,y) printf(x":printed from ABC\n", y) main() { int x = 100;

25 int y = 200; ABC("Sum of x + y is %d", x + y); } a)Sum of x + y is 300:printed from ABC b)Syntax error c)Linker error d)Behaviour is compiler dependent and hence unpredicatable. The correct answer is a. ABC("Sum of x + y is %d", x + y) is expanded as printf("Sum of x + y is %d"":printed from ABC\n", x + y). When two strings are continuously given, they are automatically concatenated and considered as single string by C compiler. Effectively the statement becomes printf("Sum of x + y is %d:printed from ABC", x+y). 6) What is the output of following program? #define KING_KONG 0xDEADCA1F #define KING_ARTHUR 0xDEADBEAD #define ABC(x) (KING_##x) main() { printf("0x%X\n", ABC(ARTHUR)); } a)0xDEADBEAD b)Syntax error c)Linker error d)Behaviour is compiler dependent and hence unpredicatable. The correct answer is a. ABC(ARTHUR) is expanded as KING_ARTHUR due to "token paste" operator. KING_ARTHUR is further expanded as 0xDEADBEAD and is printed. 7) What is the output of following program? #define MYPRINT(x) printf(#x) main() { MYPRINT(This appears like syntax error\n); } a)This appears like syntax error b)Compilation error c)Linker error d)Behaviour is compiler dependent and hence unpredicatable.

26

The correct answer is a. MYPRINT(This appears like syntax error) is expanded to printf("This appears like syntax error\n") and is printed. 8) Which of the following statements are not true for a preprocessor. 1. Can detect syntax errors 2. Can direct compiler to do certain implementation specific actions 3. Can expand macros only if macro is declared in single line. 4. Supports nested macros a)All of the above b)1 & 3 c)1, 2 & 3 d)3 & 4 The correct answer is b. Preprocessor cannot detect syntax errors as that is job of compiler. Preprocesser handles multiline macro as long as \ is provided at end of each line. Preprocessor can instruct compiler to do implementation specific things using #pragma directives. Once macro is expanded, it checks whether further expansion is possible. So it supports nested macros as well. 9) What is the output of following program? #define MYPRINTF(x) printf("%s: printed at time:%d\n", #x, __TIME__) main() { int i = 5; while(i--) { MYPRINTF(Hello World); sleep(1); } } a)The program prints the same output 5 times b)The program prints Hello World along with time at which the printf is executed. c)Program doesn't link due to undefined symbol. d)Syntax error The correct answer is a. __TIME__ will be replaced with time at which MYPRINTF is expanded by the pre-processor. So, the program will print the same output 5 times. 10) What is the output of following program? Assume, sizeof(int) is 4 and sizeof(char) is 1.

27 #pragma pack(1) typedef struct { char day; char month; int year; }DATE; #pragma pack() typedef struct { int empno; DATE doj; /* date of joining */ int salary; } EmpRec; main() { printf("%d %d\n", sizeof(DATE), sizeof(EmpRec)); } a)8 16 b)6 16 c)6 14 d)8 20 The correct answer is b. Due to #pragma pack(1), DATE struct is byte aligned. i.e there won't be any padding bytes between char month and int year; So, the sizeof(DATE) would be 6 bytes. Due to pragma pack(), the alignment mechanism is restored to default, so there will be 2 bytes padding between DATE doj and int salary; So, sizeof(EmpRec) would be 16 bytes. 11) What is the output of the following program? #include <stdio.h> #define a(x,y) x##y #define b(x) #x #define c(x) b(x) int main() { printf("%s\t",c(a(34,56))); printf("%s\n",b(a(34,56))); return 0; } a)34 56 34 b)3456 3456 c)3456 a(34,56)

28 d)Compiler Error The correct answer is c. ## -- "token paste operator" # - "stringizer operator" Both operators are handled by C preprocessor (not compiler). During macro nesting, further expansion is stopped whenever # is encountered. When c(a(34,56)) is provided, the macro #define c(x) b(x) expands both c & a. So, c(a(34,56)) is expanded as b(3456), which is expanded as "3456" When b(a(34,56)) is provided, the macro #define b(x) #x expands only b, as # is encountered. So, b(a(34,56)) is expanded as "a(34,56)"." 12) Subsequent to the preprocessing phase: a)All macros are substituted and comments are removed b)All adjacent string literals are concatenated c)All of the above d)None of the above The correct answer is c. The preprocessor also strips the comments in addition to macro substitution and string literal concatenation. 13) Assuming the code below is stored in a file "a.c" and the command "gcc a.c" is used to compile the file, what is the output of this program: #ifdef DEBUG #define DEBUG_PRINT(x) printf("debug :%s\n", (x)); #else #define DEBUG_PRINT(x) #endif main() { int x; DEBUG_PRINT("In main"); x=10; printf("%d\n", x); DEBUG_PRINT("Exiting main"); } a)Program encounters compilation error since DEBUG is not defined b)Program does not print anything

29 c)Program prints 10 d)Program prints debug :In main 10 debug :Exiting main The correct answer is c. Unless the program is explicitly compiled with -DDEBUG flag, DEBUG does not get defined. Therefore the "#else" part of the macro is expanded where DEBUG_PRINT(x) is defined as nothing. 14) Assuming the code below is stored in a file "a.c" and the command "gcc a.c" is used to compile the file, what is the output of this program: #ifdef DEBUG #define DEBUG_PRINT(x) printf("debug :%s\n", (x)); #else #define DEBUG_PRINT(x) #endif main() { #define DEBUG DEBUG_PRINT("In main"); int x; x=10; printf("%d\n", x); DEBUG_PRINT("Exiting main"); } a)Program encounters compilation error since DEBUG is not defined b)Program does not print anything c)Program prints 10 d)Program prints debug :In main 10 debug :Exiting main\n" The correct answer is c. Here by the time DEBUG_PRINT gets defined, DEBUG still remains undefined. Therefore the "#else\n" part of the macro is expanded where DEBUG_PRINT(x) is defined as nothing. 15) Assuming the code below is stored in a file "a.c" and the command "gcc a.c" is used to compile the file, what is the output of this program: #ifdef DEBUG #define DEBUG_PRINT(x) printf("debug :%s\n", (x));

30 #else #define DEBUG_PRINT(x) #endif main() { int x; #if 0 x=10; #endif printf("%d\n", x); DEBUG_PRINT("Exiting main"); } a)Program encounters compilation error b)The program prints some junk value c)Program gives run-time error d)Program prints 10 The correct answer is b. Here the assignment statement gets compiled out since text following #if 0 is discarded. This is equivalent to commenting the code between #if 0 and #endif

C Quiz Week 4
1) What is the output of the following program? main() { int xyz = 0xA0A0A0A0; printf("0x%X", xyz >> 1); } a)0x50505050 b)0xD0505050 c)0x40404040 d)0xC0C0C0C0 The correct answer is b. For a signed number the sign of the number is determined by the MSB. 0xA0A0A0A0 in binary is (1010 0000 1010 0000 1010 0000 1010 0000). Here, the MSB is 1 and hence it is a negative number. When right shifted the sign bit will get extended. 2) What is the output of following program? main() {

31 unsigned int xyz = 0; printf("0x%X\n", --xyz); } a)-0 b)0xFFFFFFFF c)Runtime Error or Unpredicatable output d)Syntax Error The correct answer is b. When 1 is subtracted from 0 that is stored in an unsigned int, the resultant value is MAXINT. Since we are printing the value in hex, it prints all Fs. 3) What is the output of following program? main() { int number = 0xdeadbeef; int mask = 0x7ff0; printf("0x%X\n", (number & mask) >> 16); } a)0 b)0x3EEF000 c)0xBEEF d)0x7EEF000 The correct answer is a. Note that the value of the mask is 0x00007fff0. When the number 0xdeafbeef is AND-ed with it the leading 4 nibbles become 0s. So (number & mask) would result in (0x00003ee0) which when right shifted by 16 bits retains only zeros. 4) For what kind of numbers, the following program will print "Yes" main() { int x; scanf("%d", &x); if (x & 3) { printf("No\n"); } else { printf("Yes\n");

32 } } a)Multiples of 2 b)Multiples of 4 c)Multiples of 8 d)Multiples of 3 The correct answer is b. The program prints "No" if any of the last 2 bits of x are set. The last two bits are not set for all multiples of 4. Hence it prints Yes for all the numbers that are multiples of 4 (4, 8, 12, ....). Note that it prints "Yes" even when x is zero. 5) What is the output of following program? main() { int number = 0xdeadbeef; int mask = 0x7ff0; printf("0x%X\n", (number & mask) << 16); } a)0 b)0x3EE00000 c)0xBEEF d)0x7EEF000 The correct answer is b. Note that the value of the mask is 0x00007fff0. When the number 0xdeafbeef is AND-ed with it the leading 4 nibbles become 0s. So (number & mask) would result in (0x00003ee0) which is left shifted by 16 bits resulting in 0x3ee00000 being printed. 6) What is the size of the following structure? typedef struct { int ctrl1; char flag; int ctrl2; char flag2; int ctrl3; } MYREG; a)14 b)20 c)24

33 d)16 The correct answer is b. There is a 3 byte padding added after flag and flag2 to align the integers ctrl2 and ctrl3. Therefore size of this structure will be 20 bytes. 7) What is the size of the following structure? typedef struct { int ctrl1; char flag; char flag2; int ctrl2; int ctrl3; } MYREG; a)14 b)20 c)24 d)16 The correct answer is d. There is a 2-byte padding added before ctrl2 to align ctrl2 to a 4-byte boundary. Hence the size of this structure is 16. 8) What would this function return: int foo(int a) { return !(a & (a - 1)) && a; } a)Returns non zero when a is odd b)Returns non zero when a is even c)Returns non zero when a is power of 2 d)Always return zero The correct answer is c. When 'a' is a power of 2, only single bit in 'a' would be set, so in (a-1) all the trailing bits towards the LSB side would be set, hence (a & (a-1)) would be zero. !(a & (a-1)) would be non zero. Just to handle the case when 'a' is zero, the expression is AND-ed with 'a'. 9) What would this function return: int foo(int a) { int c;

34

for (c = 0; a; c++) { a &= a - 1; } return c; } a)Number of bits set in variable a b)location of most significant set bit c)always return sizeof(v)*8 d)if a is odd it will retunr 1 else sizeof(v)*8 The correct answer is a. The expression inside the for loop clears the least significant bit that is set, so 'c' would contain the count of the number of times 'for' loop is executed, which is number of bits set in 'a'. This method is designed by Brian Kernighan, which takes as many iterations as number of bits set. 10) What would be the output of the following piece of code: void main() { int x, y,z; z = (x=0xaaaa) && (y=0x5555); printf("logical AND result: %x;", z); x =0, y =0; z = (x=0xaaaa) & (y=0x5555); printf(" AND operator result: %x \n", z); } a)logical AND result: b)logical AND result: c)logical AND result: d)logical AND result: 1; AND operator result: 0; AND operator result: 1; AND operator result: 0; AND operator result: ffff ffff 0 0

The correct answer is c. In case of first statement its a logical AND of two non zero number, which results in 1 & in the second case its the bitwise AND of two numbers with no common bit set, hence is zero. 11) What would be the output of the following piece of code: void main() { int x, y,z; z = (x=0xaaaa) || (y=0x5555); printf("logical OR result: %x;", z);

35 x =0, y =0; z = (x=0xaaaa) | (y=0x5555); printf(" bitwise OR result: %x \n", z); } a)a. logical OR result: b)b. logical OR result: c)c. logical OR result: d)d. logical OR result: 1; bitwise OR result: 0; bitwise OR result: 1; bitwise OR result: 0; bitwise OR result: ffff ffff 0 0

The correct answer is a. explaination: In case of first statement its a logical OR of two non zero number, which results in 1 & in the second case its the bitwise OR of two numbers. 12) If you do not understand and address alignment issues in your software, which of the following scenarios are possible? a)Your software may run slower, lock up b)Your software may crash c)Your software may silently fail, yielding incorrect results d)All of the above The correct answer is d. In some architectures, unaligned access results in multiple memory accesses, making your code run very slow. In some architectures, unaligned access can result in SIGBUS (and programs terminates with "Bus error"). If you make assumptions about the offset for a field within a structure and if you don't take into account the padding bytes, your program can have logical errors as well. 13) Consider the following piece of code: #define MASK 0xFFFFFFFF void bit_op(unsigned int p) { unsigned int i; i = MASK ^ ((p ^ MASK) + p); } Which of the following statements are true with respect to the above code? a)At the end of the function, all the bits in 'i' will be set to 0 b)At the end of the function, all the bits in 'i' will be set to 1 c)At the end of the function, the value of 'i' will be equal to that of 'p'

36 d)At the end of the function, the value of 'i' will be equal to that of 'p' with all the bits toggled The correct answer is a. ^ (XOR operation) with all 1's is equivalent to bit toggling. Adding the original value to the toggled value will result in all 1's. One more bit toggling operation will result in all 0's. 14) What does the following code output (on a 32-bit Intel/Linux system)? struct x { unsigned int a:2; unsigned int b:2; unsigned int c:1; unsigned int d:1; int e; }; int main() { struct x foo; memset(&foo, 0, sizeof(foo)); foo.a = 2; foo.b = 7; foo.c = 3; printf("a=%d, b=%d, c=%d, d=%d\n", foo.a, foo.b, foo.c, foo.d); return 0; } a)a=2, b=7, c=3, d=0 b)a=2, b=3, c=1, d=0 c)a=3, b=3, c=1, d=0 d)a=2, b=7, c=1, d=0 The correct answer is b. The bit fields will be filled only as much as the size specified in the definition. So only 2 bits are used for 'b' and one bit for 'c'. Make sure that you are careful about using such code while writing portable applications. 15) What does the following code output (on a 32-bit Intel/Linux system)? struct x { int a:2; int b:2;

37 int c; int d:1; int e:1; }; int main() { printf("%d\n", sizeof(struct x)); return 0; } a)5 b)8 c)12 d)16 The correct answer is c. Both 'a' & 'b' will be part of the first byte. The compiler will add padding so that 'c' starts on a 4-byte boundary. Similarly, d & e will be part of one byte, but the end padding makes sure that the size of the structure is 12 bytes. 16) What does the following code output (on a 32-bit Intel/Linux system)? struct record { char *name; int refcount:4; unsigned int active:1; }; int main() { printf("%d\n", sizeof(struct record)); return 0; } a)5 b)6 c)8 d)12 The correct answer is c. If enough space remains, a bit-field that immediately follows another bit-field in a structure will be packed into adjacent bits of the same unit. Here, since refcount uses only 4 bits of the int, active will be packed into the

38 same int. So name uses 4 bytes (pointer to a char), and refcount and active together use up another 4 bytes. 17) Consider the following piece of code: int fn(int x) { return (x && ((x ^ (x - 1)) == ((2 * x) - 1))); } Which of the following statements is most accurate about the above code? a)It checks if x is an even number or odd number b)It checks if at least one bit is set to 1 in x c)It checks if all the bits are set to 1 in x d)It checks if x is a power of 2 The correct answer is d. All powers of 2 have an interesting property. They have just a single 1 in their binary representation ans the rest are 0s. For example, 1 (=1), 10 (=2), 100 (=4), 1000 (=8), 10000 (=16) and so on. One less that each of these numbers will be a bit-toggled representation -- 0 (=0), 01 (=1), 011 (=3), 0111 (=7), 01111 (=15) and so on. Therefore, a bitwise XOR of x and (x-1) will result in all 1's. ((2 * x) - 1) is basically one less than x's next higher power of 2. So the results (with all 1's) should match for all powers of 2. The first check for positive value of x is because the above logic does not handle the case where x=0. 18) What does the following code output (on a 32-bit Intel/Linux system)? struct st { char a[3]; short int b; long int c; char d[1]; }; int main() { printf("%d\n", sizeof(struct st)); return 0; } a)10 b)16

39 c)18 d)20 The correct answer is b. The compiler will add padding so that a is followed by 1 byte of padding, b by 2 bytes of padding and d followed by 3 bytes of padding. There will not be any padding after c. Thus the total size of the structure is 16 bytes. 19) Which of the following represents the logic for a function getbits(x, p, n) that returns the right adjusted n-bit field of x that begins at position p. Assume that bit position 0 is at the right end and that p and n are sensible values. For example, if x = 174, p = 4, n = 3, then getbits() should return 3 bits in positions 4, 3 and 2 (101"011"10), i. e., getbits(174, 4, 3) = 3. a)return (x << (p + 1 - n)) & ~(~0 >> n); b)return (x >> (p + 1 - n)) & ~(~0 << n); c)return (x << (p - n)) & ~(~0 >> n); d)return (x >> (p - n)) & ~(~0 << n); The correct answer is b. We can get the 'interesting' portion of the value ("011" here) by discarding the unwanted portion of the MSB and the LSB. Let us look at discarding the unwanted LSB portion of x first. If you look at the example of 174, by discarding last portion, we get 101"011". We can achieve this by right shifting x upto the portion we are interested in. That calculation is done by (p + 1 -n). So (x >> (p + 1 -n)) discards the unwanted LSB. Now we want to make sure that we read only the portion we are interested in. Since we know the number of bits we need, we can get the result by ANDing all 1s for the bits we need. Let's look at the second part of the expression now. ~0 is all 1s. Left shifting by n bits will result in the n least significant bits being set to 0. One's complement of that (~(~0 << n)) will result in the n least significant bits being set to 1. Thus the final AND of these two will get you the required result. 20) Consider the following piece of code (on a 32-bit Intel/Linux system): #define BIT(n) (1 << (n)) void bit_op(unsigned int a, unsigned int n) { a |= BIT(n); } Which of the following statements is most accurate about the above code? a)The function sets the n-th bit of a, assuming 0 to be the least significant bit position b)The function sets the n-th bit of a, assuming 0 to be the most significant bit position

40 c)The function clears the n-th bit of a, assuming 0 to be the least significant bit position d)The function clears the n-th bit of a, assuming 0 to be the most significant bit position The correct answer is a. (1 << n) will pad 0s to the n least significant bits. Thus we get a value with 1 set only in the position we are interested in. OR'ing this value with a will set the n-th bit of a. 21) Consider the following piece of code (on a 32-bit Intel/Linux system): #define BIT(n) (1 << (n)) void bit_op(unsigned int a, unsigned int n) { a &= ~BIT(n); } Which of the following statements is most accurate about the above code? a)The function sets the n-th bit of a, assuming 0 to be the least significant bit position b)The function sets the n-th bit of a, assuming 0 to be the most significant bit position c)The function clears the n-th bit of a, assuming 0 to be the least significant bit position d)The function clears the n-th bit of a, assuming 0 to be the most significant bit position The correct answer is c. (1 << n) will put in 0s in the n least significant bits. Thus we get a value with 1 set only in the position we are interested in. AND'ing the one's complement of this value with a will clear the n-th bit of a. 22) Consider the following piece of code (on a 32-bit Intel/Linux system): #define BITS_IN_CHAR int fn1(int a) { int i; i = -(a < 0); return i; } int fn2(int a) { int i; i = a >> (sizeof(int) * BITS_IN_CHAR - 1); 8

41 return i; } Which of the following statements is most accurate about the above code? a)Both the functions compute the sign of a given integer & return -1 for negative and 0 for positive values b)Both the functions compute the sign of a given integer & return -1 for negative and 1 for positive values c)Both the functions compute the sign of a given integer & return -1 for negative and 0 for positive values. fn1() will avoid branching on CPUs with flag registers. d)Both the functions compute the sign of a given integer & return -1 for negative and 0 for positive values. fn2() will avoid branching on CPUs with flag registers. values values values values

The correct answer is d. The working of fn1() is obvious. It checks if a is less than 0. If so, the condition evaluates to 1, and the return is -1. If not, it will return 0. The expression in fn2() evaluates to i = a >> 31. When signed integers are right shifted, the value of left-most bit is copied to other bits. For negative values, this bit will be one. So a >> 31 will result in all 1s which is equivalent to -1. 23) Consider the following piece of code (on a 32-bit Intel/Linux system): struct mystruct { char a; int b; short c; char d; }; int main() { struct mystruct foo[3]; char ch; int i; printf("%p %p %p %p %p\n", &foo[0], &foo[1], &foo[2], &ch, &i); return 0; } Which of the following would be the most likely candidate for its output? a)0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8f 0xfeeece88 b)0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeeceb4 0xfeeeceb8 c)0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeeceb4 0xfeeeceb5

42 d)0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8c 0xfeeece88 The correct answer is a. Remember that the stack grows towards lower memory addresses here. So ch would be at a location above foo, and i above ch. ch would be at a location aligned to its natural (1-)byte boundary. Similarly, i would be a location aligned to the 4-byte boundary. 24) Consider the following piece of code (on a 32-bit Intel/Linux system): /* Assume a > 0 */ unsigned long bit_op(unsigned long a) { int n = 0; if ((a & 0xffff) == 0) { n += 16; a >>= 16; } if ((a & 0xff) == 0) { n += 8; a >>= 8; } if ((a & 0xf) == 0) { n += 4; a >>= 4; } if ((a & 0x3) == 0) { n += 2; a >>= 2; } if ((a & 0x1) == 0) n += 1; return n; } Which of the following statements is most accurate about the above code? a)The function returns the position of the first rightmost bit(LSB) set to 1 b)The function returns the position of the first rightmost(LSB) bit set to 0 c)The function returns the position of the first leftmost(MSB) bit set to 1 d)The function returns the position of the first leftmost(MSB) bit set to 0 The correct answer is a. As mentioned in the comment, the function will not take care of the case a=0. In this case, it returns 0 which is wrong because the 0-th bit is not set to 1.

43 25) Consider the following piece of code (on a 32-bit Intel/Linux system): # pragma pack (1) struct x { char a; int b; short c; }; # pragma pack () int main() { printf("%d\n", sizeof(struct x)); return 0; } What is the output of the above code? a)8 b)7 c)12 d)10 The correct answer is b. The #pragma pack(n) directive indicates to the compiler the alignment needs. When #pragma pack(1) is specified, it tells the compiler to align on a 1-byte boundary. #pragma pack() is used to get back to default alignment. Since struct x is defined within #pragma pack(1) directive, it will align to 1 byte boundary. No padding will be done between the members a, b or c of the structure. Hence a will take up 1 byte, b will take up 4 bytes and c will take up 2 bytes. 26) Consider an unsigned int v. For values of v=255, what would the values of ~v, ~v+1 and ~(v+1) be? a)ffffff00, ffffff01, fffffeff b)fffffffe, fffffffd, ffffffed c)0, 1, 255 d)None of the above The correct answer is a. 255 when represented in hex is 0x0000 00ff. ~v is 1's complement of v, which will be 0xffff ff00. ~v+1 (here ~ takes precedence over arithmetic operator +) would be (~v)+1 which is 0xffff ff01. ~(v+1) would evaluate to ~(0x0000 0100) which is 0xffff feff.

44

C Quiz Week 5
1) What is the output of following program? main() { char **p = 0; printf("%d\n", ++p); } a)4 b)Syntax Error c)Runtime Error d)Unpredictable output The correct answer is a. p is double pointer (pointer to pointer). Sizeof any pointer in 32 bit machines is 4 bytes. So, by incrementing p, it moves 4 bytes. Since, p is initialised to zero, value of p after increment is 4. 2) What is the output of following program? main() { int x, y; int *p1 = &x; int *p2 = &y; printf("%d\n", p1-p2); } a)4 b)1 c)-4 d)Syntax or Runtime error The correct answer is b. All the local variables are stored in stack. So, x, y, p1 and p2, all these variables will be part of the stack. Since, stack follows "last in first out" principle, the first local variable is pushed into the stack. i.e x is pushed first, followed by y, followed by p1 and p2. So, &p2 and &p1 would differ by 4 bytes. Since p1 is pushed earlier than p2, it will have higher memory address than p2. However, subtracting two pointers of the same type, will give the "number of elements" between them and hence output is 1. 3) What is the output of following program? main() {

45 int x, y ; int *p1 = &x; int *p2 = &y; printf("%d\n", (int)p1-(int)p2); } a)4 b)1 c)-4 d)Syntax or Runtime error The correct answer is a. All the local variables are stored in stack. So, x, y, p1 and p2, all these variables will be part of the stack. Since, stack follows "last in first out" principle, the first local variable is pushed into the stack. i.e x is pushed first, followed by y, followed by p1 and p2. So, &p2 and &p1 would differ by 4 bytes. Since p1 is pushed earlier than p2, it will have higher memory address than p2. Since the pointers are cast to integer, by subtracting them, they just behave like normal numbers and hence output would be 4. 4) What is the output of following program? main() { int x, y ; char *p1 = &x; char *p2 = &y; printf("%d\n", p1-p2); } a)4 b)1 c)-4 d)Syntax or Runtime error The correct answer is a. All the local variables are stored in stack. So, x, y, p1 and p2, all these variables will be part of the stack. Since, stack follows "last in first out" principle, the first local variable is pushed into the stack. i.e x is pushed first, followed by y, followed by p1 and p2. So, &p2 and &p1 would differ by 4 bytes. Since p1 is pushed earlier than p2, it will have higher memory address than p2. However, subtracting two pointers of the same type, will give the "number of elements" between them. Since sizeof char is 1 byte, output would be 4. 5) What is the output of the following program? typedef struct {

46 int day; int month; int year; } MYDATE; main() { MYDATE *dp = 0xB8000000; printf("0x%x\n", &dp->year); } a)Unpredictable output b)Runtime error c)0xB8000004 d)0xB8000008 The correct answer is d. The first field starts at 0xB8000000, second field starts at 0xB8000004 and hence third field would start 0xB8000008. 6) What is the output of following program? typedef struct { int day; int month; int year; } MYDATE; int x = 0x10; int y = 0x20; int z = 0x30; int a = 0x40; int b = 0x50; int c = 0x60; int d = 0x70; MYDATE abc = { 1, 1, 2006 }; main() { MYDATE *dp = &x; ++dp ; ++dp ; printf("%x\n", dp->day); } a)0x30 b)0x60 c)0x70

47 d)Syntax or Runtime error The correct answer is c. Size of MYDATE is 12 bytes. So, if incremented twice, dp moves 24 bytes or 6 integers. So, dp->day will print 0x70. 7) What is the output of the following program in little endian architecture based processor ? main() { int xyz = 0xC0FFEE; unsigned char *p = &xyz; ++p; printf("0x%X\n", *p); } a)0xC0 b)0x00 c)0xEE d)0xFF The correct answer is d. In little endian architecture, least significant bytes are stored in lower most address. So, *p would contain lowermost byte of xyz which is 0xEE. Since p is incemented, it moves and points to 0xFF. 8) What is the output of the following program? main() { int x = 10; int *p = &x; printf("%d %d %d\n", x, *(&x), **(&p)); } a)Syntax Error b)Runtime Error c)10 10 10 d)Unpredictable output as addresss of x and p are not known. The correct answer is c. Value of x is 10. *&x is nothing but x. *(&p) is not but p. **(&p) is not but *p. So output would be 10 10 10. 9) What is the output of the following program? main() { int x = 10;

48 int y = 20 ; int *p = &y ; &x = p ; printf("%d %d %d\n", x, y, *p); } a)Syntax Error b)Runtime Error c)20 20 20 d)10 20 20 The correct answer is a. & operator doesn't have lvalue. i.e & of variable cannot be changed. 10) What is the output of the following program? main() { int x = 10 ; int y = 20 ; int *p = &x ; int **pp=&p ; *pp = &y ; printf("%d %d\n", *p, **pp); } a)Syntax Error or Runtime Error b)10 20 c)10 10 d)20 20 The correct answer is d. First, p is initialised to &x and pp is initialised to &p. i.e *pp is &p. After the assignment *pp=&y, value of p changes to &y. So, both *p and **pp is 20. 11) What is the output of the following program? typedef struct { int day; int month; int year; } MYDATE; MYDATE abc = {11, 9, 2006};

49 main() { MYDATE *dp = &abc; dp = (MYDATE *)((char *)dp + 8); printf("%d\n", dp->day); } a)Syntax Error or Runtime Error b)11 c)2006 d)Unpredictable output The correct answer is c. To begin with dp->day is 11. When dp is cast to char * and 8 is added to it, dp points to the address of 2006. So, dp->day would be 2006. However, note that in some rare architectures, they enforce that dp must be always be divisible by 12 (alingment requirement) and accessing dp after the assignment as shown above, may throw SIGBUS. 12) What is the output of the following program? char *def[5] = {"pqrs", "rstu", "tuvw", "vwxyz", "xyzab" }; char abc[5][5] = {"abc", "def", "ghi", "jkl", "mno"}; main() { char *p =(char *)def; p = p + 40; printf("%s\n", p); } a)Syntax Error or Runtime Error b)mno c)jkl d)ghi The correct answer is b. def is array of character pointer. Its size is 20. (sizeof(def[0] is 4, as each element is a pointer). abc is two dimensional array and its size is 25. The size of each element in abc is 5. (i.e sizeof(abc[0]) is 5. p is initialised to def and moved by 40 bytes. This offset of 40 bytes makes it cross 20 bytes of def and 20 bytes in abc. i.e it just crosses a[3] and points to a[4]. Hence the above program would print "mno" which is the last element of abc. 13) What is the output of the following program? f1(char *p) { char abc[6]="Hello";

50 p = abc; } main() { char *p="World"; f1(p); printf("%s\n", p); } a)World b)Hello c)Runtime error d)Hello World The correct answer is a. Note that arguments are passed by value and changes done to arguments in called function will not be reflected in Calling function.. So, p in scope of f1 is pointing to "Hello", but when in returns, in scope of main, it points to "World" and hence output would be "World" 14) What is the output of the following program? f1(char *p) { *(p+4) = '\0'; } main() { char abc[6]="Hello"; char *p = abc; f1(p); printf("%s\n", p); } a)Hello b)Hel c)Hell d)Runtime error The correct answer is c. The arguments are passed by value, but in this example, we are not changing argument, but we are changing the content pointed by the argument. So this change will be reflected in variable abc which is in scope of main function. Since the change is made at offset 4, alphabet 'o' will be replaced by '\0'.

51 15) What is the output of the following program? char * f1() { char abc[6]="Hello"; char *p = abc; return abc; } main() { char *p; p = f1(); printf("%s\n", p); } a)H b)Hello c)Runtime error Or Unpredictable output d)Syntax error The correct answer is c. Note that local variables go into the stack and is valid only in the scope of that function. Once the function returns, contents of the called function "stack frame" is not guaranteed. Since content pointed by p is not guaranteed to be "Hello" after the f1 returns, output is unpredictable or can have runtime error. In general, whenever function returns an address of local variable, it is definitely an error. 16) What is the output of the following program? char *f1() { char *abc ="Hello"; return abc; } main() { char *p; p = f1(); printf("%s\n", p);

52 } a)H b)Hello c)Runtime error Or Unpredictable output d)Syntax error The correct answer is b. Note that string constants go to the constant data segment. Therefore the string hello will be kept in the constant data segment and the address of it would get assigned to abc. The same is being returned by the function. 17) main() { char *p; char buff[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; p = (buff + 2)[5]; printf("%c" , p); } The output of this program is: a)f b)g c)h d)None of the others The correct answer is c. (buf+2)[5] evaluates to *((buf+2)+5) which is effectively buf[7] and therefore h will be printed. Like any other variable, pointer is just a place to store data. Ideally, only addresses are stored there. But one can misuse this and store anything else as well. In this example, we are storing a character into a pointer. Since C is not a strongly typed language a C-compiler will just give a warning in this case but will go ahead and generate the executable. 18) main() { int x[][3] = {1, 2, 3, 4, 5, 6}; int (*ptr)[3] = x; printf("%d ", sizeof(ptr)); printf("%d\n", sizeof(x)); } Considering size of integer is 4 bytes, the output of the above program is: a)12 24

53 b)12 12 c)4 12 d)4 24 The correct answer is d. ptr is a pointer to an array of 3 integers. Hence its size is 4 bytes (size of a pointer). x is a 2-d array containing 6 integers. Hence its size is 6*4 = 24. 19) main() { int x[][4] = {1, 2, 3, 4, 5, 6, 7, 8}; int (*ptr)[4] = x; printf("%d %d ", (*ptr)[1], (*ptr)[2]); ++ptr; printf("%d %d\n", (*ptr)[1], (*ptr)[2]); } Considering size of integer as 4 bytes, output of the above program is: a)5 6 5 6 b)2 3 6 7 c)2 3 4 5 d)2 3 5 6 The correct answer is b. ptr is a pointer to an array of 4 integers. It gets assigned the address of array x. (*ptr)[1] gets expanded to (*((*ptr)+1)). So ((*ptr)+1) would point to address of 2. Since ptr is a pointer to an array of 4 integers, ptr++ would make it move by 4 integers. This is nothing but address of 6. 20) What is the output of the follwoing program: main() { int i; char str[80] = "I am feeling good today"; for(i=0; i <strlen(str); i++) printf("%c", i[str]); printf("\n"); } a)I am feeling good today b)Compilation error

54 c)Run time error generating core d)Unexpected results The correct answer is a. Since str[i] would be represented as *(str+i) & additon is symteric operation, this is same as *(i+str) or i[str]. Hence, technically the statements str[i] & i[str] are same, hence the answer is a. 21) Considering that malloc is successful, What would be the output of the following program (consider sizeof(int) is 4): main() { int StatArr[2]; int *DynArr; DynArr = (int*)malloc(2*sizeof(int)); printf("sizeof(StatArr) : %d, sizeof(DynArr): %d\n", sizeof(StatArr), sizeof(DynArr)); } a)sizeof(StatArr) : 8, sizeof(DynArr): 8 b)sizeof(StatArr) : 8, sizeof(DynArr): 4 c)sizeof(StatArr) : 4, sizeof(DynArr): 8 d)sizeof(StatArr) : 8, sizeof(DynArr): 8 The correct answer is b. Incase of an array compiler knows the size of the array statically & hence sizeof returns the number of bytes occupied by it. Since sizeof(int) is 4 and 2 elelements are present, the size of the array is 8. A dynamic array is nothing but a pointer initialised properly to address that has space for the array. Since compiler knows that DynArr is a pointer, it would return the size of the pointer which is 4 bytes. 22) What is the output of following program? int i = 10; int f1(int(*p)()) { --i; if (i > 0) { int j; j = p(p); return(j); }

55

return 1; }

main() { printf("%d\n", f1(f1)); } a)1 b)Syntax Error c)10 d)Runtime Error The correct answer is a. The function takes a pointer to function as an argument. f1(f1) will eventually call f1 and p(p) will call f1 untill value of i becomes 0. When value of i becomes 0, f1 returns 1. The same is returned throughout the previous invocation of f1 and hence output is 1. 23) int f1(int); int f2(int); int (*fp[2])(int) = { f1, f2 }; int f1(int x) { return(x+10); } int f2(int x) { return(x+20); } main() { int sum = 0; int (*fp1)(int); fp1 = fp[0]; ++fp1; sum = fp1(sum);

56 printf("%d\n",sum); } a)Runtime error or unpredictable output b)20 c)10 d)Syntax Error The correct answer is a. If we increment a function pointer, it moves only by one byte. Because, a function pointer can point to any function (as long as return type and argument types are matched) and hence sizeof a function will be different. Since fp1 is moved only by one byte, the control would go to a wrong entry point and the program willl have runtime error. 24) int f1(int); int f2(int); int (*fp[2])(int) = { f1, f2 }; int f1(int x) { return(x+10); } int f2(int x) { return(x+20); } main() { int sum = 0; int (**fp1)(int); fp1 = fp; ++fp1; sum = (**fp1)(sum); printf("%d\n",sum); } a)Runtime error or unpredictable output b)20 c)10 d)Syntax Error

57 The correct answer is b. If we increment a pointer to a function pointer, it moves only by 4 bytes. Hence, *fp1 would point to f2. By calling (**fp1)(sum) or (*fp1)(sum), both will result in calling f2 and hence output would be 20.

C Quiz Week 6
1) What is the output of the following program: main() { int i=15; char *str; strcpy(str, "Hello, World!"); printf("i=%d\n", i--); } a)15 b)14 c)The program does not compile d)Program behaviour is unpredictable The correct answer is d. str being a pointer has only 4-bytes allocated for it to store an address. Copying a string into it will corrupt the stack 2) What is the output of the following program: #include <stdio.h> int i=0; main() { int i=5; printf("%d\n", i++); } a)0 b)1 c)5 d)6 The correct answer is c. Though i is a global variable, the local value of i holds within the block in which it is declared. So printf would print 5, and then a postincrement would take place. 3) What is the output of the following program: #include <stdio.h>

58 int i=0; main() { printf("%d ", i); { int i=2; printf("%d ", i); { i++; printf("%d ", i); } printf("%d ", i); } printf("%d\n", i); } a)0 2 3 3 0 b)0 2 3 2 0 c)0 2 3 2 2 d)None of the above The correct answer is a. In the block where i is declared (after the first printf statement), i will hold the value of 2 on stack. This scope of i is there before the last printf statement. For the last printf statement, the global scope holds for i 4) What is the output of the following program: int i=5; int f1(int i) { i=i/2; return i; } main() { int i=10; printf("%d, %d\n", f1(i), i); } a)5, 5 b)5, 10 c)10, 10 d)None of the above The correct answer is b. When f1() is called, the local copy of i which f1 receives as argument(10) holds. The on-stack value of i is changed to 5 in f1 and 5 is returned

59 from f1. This is first printed in the printf statement when f1(i) is called, and then the on-stack variable i which is assigned 10 is printed. 5) What is the output of the following program: int i=10; int f1() { static int i = 15; printf("f1:%d ", i); return i--; } main() { int i, j; i = 5; printf("%d %d %d", f1(), f1(), i); } a)f1:15 f1:14 14 15 5 b)f1:15 14 f1:15 14 5 c)f1:15 f1:14 14 14 5 d)None of the above The correct answer is a. Here the catch is that the parameters are evaluated right to left. So, when f1 is first called it is the call made from the 3rd parameter of printf, During this call, 15 is printed, and the static variable i gets decremented to 14. Again, f1 is called and this time, 14 gets printed. 14 is also returned. In the sequence in which values are returned, the printf statement prints them. Hence the output. 6) File a.c contains: static int i=12; forward(void) { return (i+=1); } backward(void) { return (i-=1); } f1(int i) { static int j=2; return(i=j+=i);

60 } File b.c contains: extern int i; int restore() { return i; } Another file c.c contains: #include <stdio.h> int i=5; main() { int i, j; i=restore(); printf("%d ", forward()); printf("%d ", backward()); printf("%d ", f1(i)); } When all the above three files are linked together and executable is created what is the output of the program? a)13 13 7 b)13 12 7 c)12 12 7 d)13 7 7 The correct answer is b. When restore() is first called, it returns the global value of i and assigns it to the local value of i in main(). The scope of i in a.c is that of the static variable with visibility in the file a.c. In file b.c the global variable i defined in a.c holds. Within the function main() the scope of i is that of the on-stack local variable. With this in mind, when forward() is called, the static value of i(initialized to 12) in a.c gets incremented and printed. Then, when backward() is called the same gets decremented. When f1() is called, 2 gets added to the value of i which was assigned 5 during call to restore. 7) File a.c contains int f1(int x, int y) { printf("%d %d", x, y); return x+y; } File b.c contains extern int f1();

61 main() { printf(" %d\n", f1(10, 20, 3)); } What is the output of the above program when a.c and b.c are compiled and linked together a)Linker Error b)Compilation Error c)10 20 23 d)10 20 30 The correct answer is d. The order in which variables are pushed on the stack is 3, then 20 and then 10. The first argument is always (ebp+2) and the second one is (ebp+3). Therefore values of 10 and 20 get passed to f1. 8) void Recurse(int x) { int y = 10; printf("%d %p\n", y, &y); if (x == 0) { ++y; Recurse(1); } } main() { Recurse(0); } The above program prints two lines. Which of the following statements is true for the above program: a)Value of y and &y will remain same across the two output lines. b)Value of y will remain same across two output lines, but not &y c)Value of &y will remain same across two output lines, but not y d)Both value of y and &y will be different across both output lines. The correct answer is b. Here, y is a local variable. Copies of it are created each time a function is called recursively. Its value is being printed each time it is assigned the value 10. Therefore, the value of y printed will always be 10, but its address will vary for each call to the function. 9) int func(int x)

62 { char a[10]; strcpy(a, "Hello, This is indeed a very big world"); return (x+1); } main() { printf("%d\n", func(1)); } Which of the following statement is true with respect to the above program. a)There is a stack corruption, but it does not corrupt x. So, output will be 2. b)Value of x is indeterministic, but program control returns to main and some junk value is printed on the screen. c)There is a stack corruption, it would corrupt return address as well. Hence there will be runtime error. d)None of the above The correct answer is c. The return address is stored at the location (ebp+1). Remember that stack grows towards lower memory addresses and local variables start from (ebp-1). Since a is just a 10 byte array, and the length of the string being copied is much beyond that the return address will get corrupted. 10) int * func(int *xp) { int y = 10 + *xp; return (&y); } main() { int x = 10; int *xp = func(&x); printf("%d\n", x); printf("%d\n", *xp); } What is the output of above program. a)20 b)10 c)Runtime Error d)Unpredictable The correct answer is d. Please note that a normal gcc compiler will always give a warning whenever the address of a local variable is returned. When func() is called and then printf() is called right after, the stack would have got over-written during

63 the execution of printf(). Hence when contents of that location where y was present during call to func() are read, either some junk value will be read or an unpredictable behaviour may be seen. 11) void func(int a[10]) { a[0] = 1; } main() { int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; func(a); printf("%d\n", a[0]); } What is the output of the above program? a)Syntax error b)Runtime error c)0 d)1 The correct answer is d. When call to func(a), a is nothing but &a[0]. So when func modifies a[0], the same is reflected in the array that is referred to in main. 12) What is the output of the following program: #include <stdarg.h> int func(int x, ...) { char y; int z; va_list ap; va_start(ap, x); y = (char)va_arg(ap, int); z = va_arg(ap, int); printf("%c 0x%x\n", y, z); va_end(ap); } main() { func(0x10, 0x32, 0x31); } a)0x32 0x31 b)Not predictable

64 c)2 0x31 d)Syntax Error The correct answer is c. When va_arg is made to interpret the location pointed to by 0x32, it will interpret it as a character and print 2. The next argument is interpreted as an integer and hence its hex value is printed. The cast to char is necessary since va_arg is capable of interpreting only fully promoted types. 13) #include <stdarg.h> int foo(char *fmt, ...) { va_list ap; int d; int count=0; char c, *p, *s; va_start(ap, fmt); while (*fmt) switch(*fmt++) { case '%': if((*fmt) && (*(fmt) != '%')) count++; else if (*fmt) fmt++; break; } va_end(ap); return count; } a)Counts the number of arguments passed from the format string b)Counts the number of %s in the given format string c)Encounters a linker error d)Encounters compilation error The correct answer is a. Note that the while loop increments count each time a '%' character is encountereed. The only exceptions are when a % is followed by a % or a null termination. Therefore the loop effectively counts the number of arguments passed by parsing the format string.

C Quiz Week7
1) What is wrong with the following program:

65 main() { char *s = "Hello World\n"; printf("%s", s); } a)s has memory for only 4-bytes so this will not compile. b)Its behaviour is unpredictable since s has memory for only 4 bytes c)Program will encounter segmentation violation d)It will work without any problem The correct answer is d. "Hello World\n" is allocated in read only data segment of memory. The address of that gets assigned to s. 2) What is wrong with the following program: main() { char *s = (char *) malloc(sizeof("Hello World\n")); strcpy(s, "Hello World\n"); printf("%s", s); } a)It will work fine since memory sufficient to hold "Hello World\n" is requested from heap b)Its behaviour is unpredictable since s has memory for only 4 bytes c)Program will encounter segmentation violation d)The malloc statement is fine, but subsequently the program could have problem the correct answer is d. Though the program allocated sufficient memory, the return value of malloc is not being tested. The correct answer is d. Though the program allocated sufficient memory, the return value of malloc is not being tested. 3) What is wrong with the following program: main() { char *p = (char *)malloc(sizeof ("Hello World\n")); if (p) { strcpy(p, "Hello World"); printf("%s ", p); } p = (char *)malloc(sizeof("Good Morning\n")); if (p)

66 { strcpy("p, "Good Morning"); printf("%s", p); } if (p) free(p); } a)There is nothing wrong in the program since all memory allocated is being freed b)The memory allocated for "Hello World\n" is lost forever c)p should be an array of characters instead of a pointer to char d)None of the above The correct answer is b. 2nd call to malloc will overwrite the address returned by the first call. That memory is therefore lost forever 4) Since the process address is unique to each process, and all the resources allocated for a particular process is freed when it exits, even heap gets freed. Therefore: a)It will be a problem in systems where heap is shared across threads b)It will be a problem in systems where there is a common system heap c)It will be a problem when memory is continuously allocated in a while(1) loop without getting freed. d)All of the above. The correct answer is d. There are OSes where the heap is a common pool for all processes. Also in case of multi threading when multiple threads come to play. Also when memory keeps on getting allocated in server processes etc in a while(1) loop. 5) What is the likely size of stack in an ELF file? a)The stack is of 1K size b)The stack is just 8 bytes to mark the start address and end address c)There is no stack in an ELF file d)None of the above The correct answer is c. Stack grows dynamically during program execution. Hence there will be no stack in an ELF file. 6) What is the likely size of heap in an ELF file? a)The heap is of 1K size

67 b)The heap is just 8 bytes to mark the start address and end address c)There is no heap in an ELF file d)None of the above The correct answer is c. heap grows dynamically during program execution. Hence there will be no stack in an ELF file. 7) What is the problem with the following piece of code? main() { char *p = (char *)malloc(strlen("Hello World\n")); if (p) { strcpy(p, "Hello World\n"); free(p); } } a)strlen returns 12, but the entire string needs 13 bytes, so strcpy will corrupt memory. b)strlen returns 12, the string needs 12 bytes, so there is no problem in the program. c)strlen returns 13, the string needs 13 bytes, so there is no problem in the program. d)None of the above The correct answer is a. Since strlen does not include the space needed for the trailing NULL character in the string, copying 13 bytes into allocted 12 bytes would corrupt memory 8) Which of the following statements is true: a)Memory corruption will immediately result in a crash - hence debugging it is very easy b)Memory corruption can never result in a crash c)Memory corruption will not always result in a crash, problem occurs only when corrupted memory gets accessed d)It is OK to have memory corruption since the problems caused by it are very rare The correct answer is c. Since it is not always necessary to have misbehaviour with memory corruption, it is very necessary to be very discplined during coding. 9) Having access to the memory allocated through the pointer returned is important because: a)The address returned by malloc can be accessed only through it b)To check the return value of malloc c)Freeing that memory is completely dependent on this address

68 d)All of the above The correct answer is d. Memory allocated through pointer returned is the only means for the program to have access to the chunk allocated, for subsequently freeing it. 10) A loader is a)Independent of the OS and hence loaders can work across OS platforms b)It is dependent on the OS and understands the OS specific process loading requirements c)Is part of the compiler and takes care of the last phase of compilation d)None of the above The correct answer is b. Loader is responsible for loading the executable file generated into the memory to prepare it for running. Hence it needs to understand the OS specifics to enable running of the program. 11) What is the likely problem with this code: main() { char *p = (char *)malloc(1024); if (p) { strcpy(p,"Hello\n"); p += 10; strcpy(p,"World\n"); p += 10; strcpy(p,"That is all\n"); free (p); } } a)Incrementing p will result in runtime error. b)There is no problem with the code. c)The pointer being given to free does not contain the address returned by malloc. d)None of the above. The correct answer is c. As already seen, the address to free plays a key role in identifying the memory that has to be freed. If that is wrong, the behaviour of the program could be unpredictable. 12) Below is the code to find the factorial of a number:

69 unsigned int Factorial(unsigned int n) { if (n==1) return 1; else return Factorial(n-1) * n; } Which of the following is true about this code: a)The above code could result in integer overflow when n is big b)The above code can result in stack overflow when n is big c)The above code fails when n is 0 d)All of the above The correct answer is d. The code to find factorial, can have problems in all the mentioned areas. 13) What happens during relocation? a)Symbols in shared memory are resolved. b)Absolute references of a location are changed to virtual addresses. c)Allocation for stack and heap for the program. d)Moving executable image from hard disk to main memory. The correct answer is b. Relocation is a phase when all absolute refrences are changed to virtual addresses 14) What happens during "dynamic linking"? a)Symbols in shared libraries are resolved. b)Absolute references of a location are changed to virtual addresses. c)Allocation for stack and heap for the program. d)Moving executable image from hard disk to main memory. The correct answer is a. Dynamic linking is the phase when symbols from shared libraries are resolved 15) .ro segment contains: a)Constant data and strings. b)Re-organized data segment. c)heap for the program. d)Symbol Table.

70 The correct answer is a. .ro segment is the readonly data segment and hence contains the constant data and string literals contained in the program. 16) .rela segment contains: a)Information about read only symbols. b)Information about symbol table. c)Symbols that are to be "dynamically linked". d)Symbols that need to be relocated. The correct answer is d. .rela segment contains the symbols that are to be relocated. 17) .dynsym segment contains: a)Information about read only symbols. b)Information about symbol table. c)Symbols that are to be "dynamically linked". d)Symbols that need to be relocated. The correct answer is c. .rela segment contains the symbols that are to be resolved dynamically.

C Quiz Week 8
1) What happens when the following program is compiled as a.out and run as ./a.out main(int argc, char *argv[]) { int flag; char filename[10]; strcpy(filename, argv[1]); printf("%s", filename); } a)If the file is stored in a file by name "a.c", that name will get copied into parameter filename b)Since the file executable filename is "a.out", that will get copied to filename in the strcpy command. c)Any junk value on the stack will be copied on to filename and subsequent behavior of the program is unpredictable d)None of the above

71 The correct answer is c. Any junk value supposedly present in the location of argv[1] will get copied on to filename and the subsequent behaviour of the program would be unpredictable. 2) What happens when the following program is compiled as a.out and run as ./a.out /home/user/harry/next.c main(int argc, char *argv[]) { int flag; char filename[10]; strcpy(filename, argv[1]); printf("%s", filename); } a)If the file is stored in a file by name "a.c", that name will get copied into parameter filename b)The entire string "/home/user/harry/next.c" will be copied into filename corrupting flag and other contents of the stack c)Just the path "next.c" will be copied into filename and rest of the path is omitted. d)Since the file executable filename is "a.out", that will get copied to filename in the strcpy command. The correct answer is b. Complete path will get copied into the location starting at &filename[0] eating up the space for the flag. 3) Consider the code snippet: main() { struct { int arr[4]; int key; } name_key; int i; name_key.key = 0; for (i=0; i<=4; i++) name_key.arr[i] = i+5; } What is the value of "name_key.key" after the above chunk of code is executed? a)0 b)9 c)The compiler gives a warning since array bounds are crossed in the loop and does not generate code.

72 d)The compiler gives an error since array bounds are crossed in the loop and does not generate code. The correct answer is b. &name_key.arr[4] will be the same as &name_key.key Hence the loop overwrites the value of name_key.key with 9. 4) Which of the following is meant by DoS? a)Dual Office Service b)Denial of Service c)Denial Office Symdrome d)Denial of Security The correct answer is b. DoS expands to Denial of Service 5) Which of the following are likely to be affected by a DoS attack? a)e-mail services b)network routers c)internet servers d)All of the above The correct answer is d. All of the above can be subjects Denial of Service attacks. 6) Denial of Service can happen if a)There are attempts to flood a server with numerous unwanted requests. b)There are attempts to disrupt a server by sending more requests than it can handle c)There are too many spurious requests generated towards a networking device d)All of the above The correct answer is d. Any of the above could result in a DoS attack. 7) By overwriting into the heap area, which of the following are you likely to corrupt? a)Other allocated MCB structures b)Other un-allocated MCB structures c)Other dynamically allocated data d)All of the above The correct answer is d. Depending on the pattern in which allocation took place, it is likely that you can corrupt all the structures

73 8) By overwriting into the stack area, which of the following are you likely to corrupt: a)Other local variables in the current function b)Return address c)local variables of calling functions d)All of the above The correct answer is d. Depending on the extent to which stack over-writing happened, it is likely that all of the above can get corrupted. 9) By overwriting memory in strings that are global variables, which of the following are you likely to corrupt? a)Return address b)Other global variables c)local variables of calling functions d)All of the above The correct answer is b. Since all the global variables are allocated from the data section, you are likely to corrupt the data section. 10) Which of the following statements is true a)The C-compiler checks for array bounds and prevents overwriting of memory that is not part of the array if the array is on the stack b)The C-compiler checks for sizes of various variables, and prevents a particular variable's memory being illegally overwritten when another variable is being written to. c)The C-compiler checks for array bounds and prevents overwriting of memory that is not part of the array if the array is on the heap d)None of the above The correct answer is d. As per the C-standard, there are no such checks mandated and hence compilers do not take care of violations of memory access. Hence it is all the more important for programmers to take care of this.

74

C++ Week 1/2


1) What is the output of following program? class MyClass { }; int main() { MyClass obj; return 0; } a)This is not valid C++ code. A class cannot be empty b)This code is perfectly legal C++ code c)This code will give error since there is no constructor defined d)Don't know The correct answer is b. This code will build fine with probable warnings on some compilers / settings since obj is unreferenced 2)What is the output of following program? class MyClass { string m_strSchoolName; MyClass(string strSchool) : m_strSchoolName(strSchool) { } void SelfDump(){ cout << "School Name is " + m_strSchoolName << endl; } }; int main() { MyClass obj("Little Feat"); obj.SelfDump(); return 0; } a)The output is School Name is Little Feat

75 b)The code gives compilation error for the statement MyClass obj("Little Feat") c)The code gives compilation error for the statement obj.SelfDump d)Both b & c The correct answer is d. In this case, the class has a private constructor and hence the object of MyClass cannot be created. Additionally even SelfDump is a private member function and hence cannot be accessed from outside the class. As per Stroustrup, the compiler tries to generate the default public constructor for a class if needed and if the user has not declared other constructors 3)What is the output of following program? class School { private: string m_strSchoolName; public: School(string strSchool) : m_strSchoolName(strSchool) { } virtual void SelfDump(){ cout << m_strSchoolName << endl; } }; class University : public School { public: University(string strSchool = "") : School(strSchool) { } virtual void SelfDump(){ cout << "University Name is "; School::SelfDump(); } }; int main() { University obj("Little Feat"); obj.SelfDump(); return 0;

76 } a)The output is University Name is Little Feat b)The output is Little Feat c)The output is not defined d)The code does not compile The correct answer is a. Note the syntax for calling base class constructor with arguments in the initialization list of the derived class constructor. 4)What is the output of following program? class Bike { public: string m_regnNumber; string m_color; public: Bike(string regnNumber = "", string color = "") : m_regnNumber(regnNumber), m_color(color){ } virtual void SelfDump(){ cout << endl << m_regnNumber << " : " << m_color << endl; } }; class Yamaha : public Bike { int m_nCylinders; float m_bhp; public: Yamaha(string regnNumber = "", string color = "", int nEngineCylinders = 2, float bhp = 200) : Bike(regnNumber, color), m_nCylinders(nEngineCylinders), m_bhp(bhp){ } virtual void SelfDump(){ Bike::SelfDump(); cout << "Cylinders = " << m_nCylinders << " And BHP = " << m_bhp << endl; } };

77

void DisplayBikeData(Bike &bk); int main(){ Yamaha ymh("KA-01-MC-0988", "RED", 2, 60); Bike bk("KA-03-MD-0988", "BLUE"); DisplayBikeData(ymh); DisplayBikeData(bk); return 0; } void DisplayBikeData(Bike &bk){ bk.SelfDump(); } a)Regn number, color will be displayed for ymh and bk. Number of cylinders and bhp will be displayed only for ymh b)Regn number, color, number of engines and bhp will be displayed for both ymh and bk c)This code is not correct. It will give compilation error d)This code is not correct. It will give run time error The correct answer is a. Derived object address can be held in base class reference or pointer. The member function called depends on the dynamic run time information of the pointer or reference. Hence in this case, when a Yamaha object is passed to DisplayBikeData, Yamaha::SelfDump is called. However when Bike object is passed to DisplayBikeData only the base class object is created and hence Bike::SelfDump is called. Note how the initialization list is used to pass arguments to the base class constructor. Initialization list is also an instance when comma separated code can be written in C++ source code 5)What is the output of following program? class Bike { public: string m_regnNumber; string m_color; public: Bike(string regnNumber = "", string color = "") : m_regnNumber(regnNumber), m_color(color){ } virtual void SelfDump(){ cout << "Dumpbing Bike Object" << endl;

78 } }; class Yamaha : public Bike { int m_nCylinders; float m_bhp; public: Yamaha(string regnNumber = "", string color = "", int nEngineCylinders = 2, float bhp = 200) : m_bhp(bhp){ } virtual void SelfDump(){ cout << "Dumpbing Yamaha Object" << endl; } }; void DisplayBikeInformation(Yamaha *pBike); int main(){ Yamaha *pYmh1 = new Yamaha("KA-01-MC-0988", "RED", 2, 60); Bike *pBk1 = new Bike("KA-03-MD-0988", "BLUE"); DisplayBikeInformation(pYmh1); DisplayBikeInformation(pBk1); delete pYmh1; delete pBk1; return 0; } void DisplayBikeInformation(Yamaha *pBike) { pBike->SelfDump(); } a)Regn number, color will be displayed for ymh and bk. Number of cylinders and bhp will be displayed only for ymh b)Regn number, color, number of engines and bhp will be displayed for both ymh and bk c)This code is not correct. It will give compilation error d)This code is not correct. It will give run time error Bike(regnNumber, color), m_nCylinders(nEngineCylinders),

79

The correct answer is c. This code will give compilation error since pointers with dynamic type as Base class cannot be passed to functions which take Derived class reference 6)Which of these statements invoke the overloaded assignment operator? class House { public: string m_Name; int m_nLength; int m_nWidth;

public: House(string name = "", int nLength = 20, int nWidth = 40) : m_Name(name), m_nLength(nLength), m_nWidth(nWidth){ } virtual void SelfDump(){ cout << "Dumping House Object" << endl; } }; class Flat : public House { int m_nNumLifts; int m_nNumSwimmingPools; public: Flat(string name = "", int nLength = 20, int nWidth = 40, int nNumLifts = 1, int nNumSwimmingPools = 1) : House(name, nLength, nWidth), m_nNumLifts(nNumLifts), m_nNumSwimmingPools(nNumSwimmingPools){ } virtual void SelfDump(){ cout << "Dumpbing Flat Object" << endl; } Flat & operator= (const Flat &rhs) { m_nNumLifts = rhs.m_nNumLifts; m_nNumSwimmingPools = rhs.m_nNumSwimmingPools; return *this; }

80

Flat(const Flat &rhs) { m_nNumLifts = rhs.m_nNumLifts; m_nNumSwimmingPools = rhs.m_nNumSwimmingPools; } }; int main(){ Flat fl1("Raheja", 20, 40, 2, 2); Flat fl2 = fl1; Flat fl3; fl3 = fl2; return 0; } a)The program has a compilation error b)Flat fl2 = fl1 c)Flat fl2 = fl1 and fl3 = f12 d)Only fl3 = fl2 The correct answer is d. C++ differentiates between initialization and instantiation. fl2 = fl1 invokes the copy constructor as part of instantiation 7)Which of the following is true for the below program class House { public: string m_Name; int m_nLength; int m_nWidth;

public: House(string name = "", int nLength = 20, int nWidth = 40) : m_Name(name), m_nLength(nLength), m_nWidth(nWidth){ } virtual void SelfDump(){ cout << "Dumping House Object" << endl; } };

81

class Flat : public House { int m_nNumLifts; int m_nNumSwimmingPools; public: Flat(string name = "", int nLength = 20, int nWidth = 40, int nNumLifts = 1, int nNumSwimmingPools = 1) : House(name, nLength, nWidth), m_nNumLifts(nNumLifts), m_nNumSwimmingPools(nNumSwimmingPools){ } virtual void SelfDump(){ cout << "Dumpbing Flat Object" << endl; } Flat & operator= (const Flat &rhs) { m_nNumLifts = rhs.m_nNumLifts; m_nNumSwimmingPools = rhs.m_nNumSwimmingPools; return *this; } Flat(const Flat &rhs) { m_nNumLifts = rhs.m_nNumLifts; m_nNumSwimmingPools = rhs.m_nNumSwimmingPools; } }; int main(){ Flat fl1("Raheja", 20, 40, 2, 2); Flat fl2 = fl1; Flat fl3; fl3 = fl2; return 0; } a)There are no errors in this program. It is fine b)The assignment operator does not guard against self assignment c)The assignment operator does not call the base class assignment operator explicitly

82 d)Both b and c The correct answer is d. Overloaded assignment operators should always guard against self assignment. Also it is recommended to call the base class assignment operator explicitly if the derived class overloads the assignment operator 8)What is the output of the below program class Parent { public: FILE *m_pFile; public: Parent(){ m_pFile = NULL; } void Init() { m_pFile = fopen("readme.txt", "rt"); } void Cleanup() { cout << "Cleaning up parent" << endl; if(m_pFile) fclose(m_pFile); } ~Parent() { Cleanup(); } }; class Child : public Parent { public: FILE *m_pFile; public: Child(){ m_pFile = NULL; } void Init()

83 { m_pFile = fopen("guess.txt", "rt"); } void Cleanup() { cout << "Cleaning up child" << endl; if(m_pFile) fclose(m_pFile); } ~Child() { Cleanup(); } };

int main(){ Parent *pnt = new Parent; Child *pcld = new Child; Parent *pParent = pcld; delete pParent; delete pnt; return 0; } a)Parent's destructor will be called twice b)Child's destructor will be called and then parents c)This program will not compile. d)Parent's destructor will be called and then childs The correct answer is a. If we delete a pointer to base, then the base-class destructor is run and the members of the base are cleaned up. If the object really is a derived type, then the behavior is undefined. To ensure that the proper destructor is run, the destructor must be virtual in the base class 9)How many errors will be generated while compiling the following program? int main(){ char *ptr1 = "Wipro"; const char *ptr2 = "Wipro";

84 char const *ptr3 = "Wipro"; char *const ptr4 = "Wipro"; const char *const ptr5 = "Wipro";

*ptr1 = 'K'; ptr1++; ptr1 = ptr2; *ptr2 = 'K'; ptr2++; ptr2 = ptr3;

*ptr3 = 'K'; ptr3++; ptr3 = ptr4;

*ptr4 = 'K'; ptr4++; ptr4 = ptr5;

*ptr5 = 'K'; ptr5++; ptr5 = ptr1; return 0; } a)2 b)3 c)8 d)5 The correct answer is c. This program will generate 8 errors First error is at the line ptr1 = ptr2. This is because we cannot assign const char * to char *. Second error is at the line *ptr2 = 'K'. This is because as per declaration ptr2 is a pointer to a constant string. The pointer can change value but not the string pointed to by ptr4. That is the reason the line ptr2 = ptr3 does not generate an error. The cause for the third error at line *ptr3 = 'K' is same as that of the second error. Fourth error is generated at line ptr4++ because as per declaration ptr4 is a constant pointer but the string pointed to by ptr4 can vary. Fifth error is generated at the line ptr4 =

85 ptr5, because again ptr4 is a const pointer and cannot change. Last three errors are generated on all manipulations related to ptr5 since as per declaration ptr5 is a constant pointer to a constant string i.e. neither ptr5 can change, nor the contents pointed to by ptr5 10)What is output of following program? class Sample{ public: int m_nCount;

public: Sample(int nCount){ m_nCount = nCount; cout << "In Sample constructor" << endl; } ~Sample(){ cout << "In Sample destructor" << endl; } }; class Lab{ Sample m_samp; string m_strName; public: Lab(string strName = "") : m_strName(strName){ cout << "In Lab constructor" << endl; } ~Lab(){ cout << "In Lab Destructor" << endl; } }; int main(){ Lab *ptr = new Lab[10];

86

delete ptr; return 1; } a)In Lab constructor In Sample constructor In Lab destructor In Sample Destructor b) In Sample constructor In Lab constructor In Sample destructor In Lab Destructor c) In Lab constructor In Sample constructor In Sample destructor In Lab Destructor d) The program is not OK. It will give compilation error The correct answer is d. Assume that we have a class MyClass that does not have a default constructor, but which has defined a constructor which takes an int as a parameter. This means that the compiler is not going to provide a default constructor for the class. When such a condition is true, the following statements hold good for MyClass 1. Every constructor for every class that has a MyClass member must explicitly initialize the MyClass member by passing an initial int value to the MyClass constructor. 2. The compiler will not synthesize the default constructor for classes that have members of type MyClass. If such classes want to provide a default, they must define one explicitly, and that constructor must explicitly initialize their MyClass member. 3. The MyClass type may not be used as the element type for a dynamically allocated array. 4. Statically allocated arrays of type MyClass must provide an explicit initializer for each element. 5. If we have a container such as vector that holds MyClass objects, we cannot use the constructor that takes a size without also supplying an element initializer. Hence in our case the program does not compile because of the point 3. above 11)What change is required to remove the compilation error in the code? class Sample{ public:

87 int m_nCount; const int m_ciMax; public: Sample(int nCount = 2){ m_nCount = nCount; m_ciMax = 255; cout << "In Sample constructor" << endl; } ~Sample(){ cout << "In Sample destructor" << endl; } }; a)This code is fine. It has no problems b)A class cannot have const member variables c)Change the declaration of ciMax as "const int m_ciMax = 2" d)None of the above The correct answer is d. Const members can be initialized only using the construction initialization list .e.g Sample(int nCount = 2): m_ciMax(255){ 12)What is wrong with this code class Lab{ string m_strName; int m_nDuration; int m_nParticipants; public: Lab(string strName = "") : m_strName(strName){ cout << "In Lab constructor with name" << endl; }

Lab(string strName, int nDuration, int nParticipants = 20) : m_nDuration(nDuration), m_nParticipants(nParticipants){ cout <<"In Lab constructor with name and duration" << endl; } ~Lab(){ cout << "In Lab Destructor" << endl; } };

88 int main(){ Lab chemistry = "Block A - C200"; return 0; } a)There will be a compilation error in the statement Lab chemistry = "Block A - C200"; b)The program will compile but will throw run time error c)Don't know d)This program is correct. chemistry object will be created on running the program The correct answer is d. The compiler treats the statement Lab chemistry = "Block A - C200"; as Lab chemistry("Block A - C200"). As long as there is an unambiguous constructor in Lab which takes a single string parameter, this code will compile and run perfectly fine 13)What is the output of this program? class MyClass { int m_nVal; public: MyClass(int nVal = 0) : m_nVal(nVal){ } MyClass& operator++(){ cout << "In operator++()" << endl; m_nVal++; return *this; } MyClass(const MyClass& rhs) { cout << "In Copy Constructor" << endl; m_nVal = rhs.m_nVal; } MyClass operator++(int){ cout << "In operator++(int)" << endl; MyClass ret(*this); ++*this; return ret; } };

89

int main(){ MyClass cls(0); cls++; ++cls; return 0; } a)In operator++(int) In Copy Constructor In operator++() In Copy Constructor In operator++() b) In operator++() In operator++(int) In Copy Constructor In operator++() In Copy Constructor c)In operator++(int) In Copy Constructor In operator++() In operator++() d)This program does not compile The correct answer is a. operator++(int) is a postfix++ and operator++() is the prefix++. Note that in the postfix++, the function has to save the current state of the object and return the saved object by value 14)What change is required in MyClass to make the below code work? class MyClass { int m_nIVal; int m_nFVal; public: MyClass() : m_nIVal(0), m_nFVal(0){ cout << "In constructor(int = 0, float = 0.0)" << endl; } MyClass operator+ (const MyClass& rhs) { MyClass s; s.m_nIVal = rhs.m_nIVal;

90 s.m_nFVal = rhs.m_nFVal; return s; } MyClass(const MyClass &rhs) { cout << "In Copy Constructor" << endl; m_nIVal = rhs.m_nIVal; m_nFVal = rhs.m_nFVal; } }; int main(){ MyClass cls(0,0.0), cls2; cls2 = cls + 10; return 0; } a)It is illegal to add an integer to a class. This problem cannot be fixed by only modifying MyClass b)Provide an overloaded assignment operator in MyClass c)Provide a constructor that takes a single integer parameter d)Don't know The correct answer is c. The call cls + 10 is translated to cls.operator+(10). Now value 10 is to be collected in MyClass which is internally treated as MyClass rhs = 10. This is declaration and initialization together. Hence if MyClass has a constructor which takes a single integer, this constructor will be called and the rhs object of MyClass will be created 15)What is the output of the following program? class MyClass { public: int m_nIVal; int m_nFVal; public: MyClass(int nIVal = 0) : m_nIVal(nIVal){ cout << "In constructor(int = 0)" << endl; } MyClass(const MyClass &rhs)

91 { cout << "In Copy Constructor" << endl; m_nIVal = rhs.m_nIVal; } MyClass& operator=(const MyClass &rhs) { cout << "In the overloaded operator=()" << endl; m_nIVal = rhs.m_nIVal; return *this; } operator int(){ cout << "In the overloaded int() operator" << endl; return m_nIVal; } ~MyClass(){ cout << "In Destructor" << endl; } }; int main(){ MyClass cls(1), cls2(2); cls2 = 4 * cls; cout << cls << endl; return 0; } a)This program works fine and cls2 will be created with the value of m_nIVal = 4 b)The program will give error in line "cls2 = 4 * cls;" c)The program will give error in line "cout << cls << endl;" d)Both b & c The correct answer is a. This program works fine. The statement cls2 = 4 * cls first converts cls to an integer using the int() operator and then performs multiplication. It then creates a temporary object with the result of the multiplication.

92 After this this temporary object is used to assign cls2 thereby invoking the overloaded= operator. In the cout statement the int() operator is used to extract the integer from cls2 and then the resulting integer is printed using the cout object 16)What if anything is wrong with this program? class Test { char *m_ptr; public: Test(){ cout << "In Constructor" << endl; m_ptr = NULL; } void Init(){ m_ptr = new char [100]; } void Cleanup(){ delete m_ptr; } ~Test(){ cout << "In Destructor" << endl; Cleanup(); } private: Test& operator=(const Test& rhs); Test(const Test&); }; int main(){ Test* tArray = new Test[10]; char *cArray = new char [10];

delete cArray; delete tArray; return 0; } a)The delete syntax is not proper

93 b)There is no problem with this code c)You cannot delete NULL pointer m_ptr d)Don't know The correct answer is a. Any allocation done with the new [] should always be deleted with delete [] else there will be memory leaks. In this case using delete [] will ensure that the destructor for all the 10 dynamically created objects will be called 17)What will be the value of m_nNumInstances printed by this program? class Test { static int m_nNumInstances; public: Test(){ cout << "In Constructor" << endl; m_nNumInstances++; }

~Test(){ cout << "In Destructor" << endl; m_nNumInstances--; } void SelfDump(){ cout << "Number of instances = " << m_nNumInstances << endl; } private: Test& operator=(const Test& rhs); Test(const Test&); }; int main(){ Test test1; Test *pTest = new Test [10]; test1.SelfDump(); pTest->SelfDump(); return 0; }

94 a)test1.SelfDump will print 1 and pTest->SelfDump will print 10 b)Both will print 11 c)Non Static member function SelfDump cannot access the static variable m_nNumInstances d)This program will not build properly The correct answer is d. This program will not build properly. This is because it is not defined by the program at all. static data members must be defined (exactly once) outside the class body. Unlike ordinary data members, static members are not initialized through the class constructor(s) and instead should be initialized when they are defined. Here is how we can define m_nNumInstances int Test::m_nNumInstances = 0; 18)What change is required in this program so that it can print the value of both the members in the class without changing the main function? class Test { public: int m_nMember; string m_strName; public: Test(string strName = "", int nMember = 0) : m_strName(strName), m_nMember(nMember){ cout << "In Constructor" << endl; }

~Test(){ cout << "In Destructor" << endl; } }; int main(){ Test test("ABCD", 2); cout << test << endl; return 0; } a)Overload the << operator in the class Test b)Overload the global << operator

95 c)It cannot be done d)Insufficient information The correct answer is b. Provide a overloaded global << operator. An example is as shown ostream& operator << (ostream& os, const Test& rhs){ os << rhs.m_nMember << ", " + rhs.m_strName; return os; } However this has a limiation. The overloaded function cannot access the private member variables of the object. Make the overloaded operator a friend of Test if private member variables are also to be displayed 19)What is your opinion on the below statement? We can derive a class from a base class even if the base class's source code is not available? a)True b)False c)Not sure d)Ridiculuous The correct answer is a. Yes, we can derive a class from base class as long as it's declaration is available, which is usually in the header files 20)What is the typedef declaration of nMemberPtr? class Test { private: int m_nMember; float m_fMember;

public: Test(float fMember= 0.0, int nMember = 0) : m_fMember(fMember), m_nMember(nMember){ cout << "In Constructor" << endl; }

void SetNMember(int nMember){ m_nMember = nMember; }

void SetFMember(float fMember){

96 m_fMember = fMember; } ~Test(){ cout << "In Destructor" << endl; } }; int main(){ Test test(1.0, 2); nMemberPtr ptr = &Test::SetNMember; (test.*ptr)(2); return 0; } a)typedef void (Test::*nMemberPtr)(int nMember); b)It is not possible to call class member functions using pointers. This code will not compile c)Don't know d)typedef void (*Test::nMemberPtr)(int nMember); The correct answer is a. Note the .* operator. This is one of the operators in C++ that cannot be overloaded. Another example is ->*

C++ Week 4 Quiz


1)Which of the following statements are incorrect void PrintText(string szText){ cout << szText << endl; } class Editor{ public: Editor() : m_szName("Editor"){} virtual void OpenFile(string szFile = ""){ PrintText("In Editor::OpenFile"); } void PrintFile(string szFile = ""){ PrintText("In Editor::PrintFile"); } virtual ~Editor(){

97 PrintText("In Editor::~Editor"); } private: string m_szName; }; class SpreadSheetApp : public Editor{ public: SpreadSheetApp(string szApp = "MSEXCEL") : m_szName(szApp){} virtual void OpenFile(string szFile = ""){ PrintText("In SpreadSheetApp::OpenFile"); } void PrintFile(string szFile = ""){ PrintText("In SpreadSheetApp::PrintFile"); } virtual ~SpreadSheetApp(){ PrintText("In SpreadSheetApp::~SpreadSheetApp"); } protected: string m_szName; };

class MSEXCEL : public SpreadSheetApp{ public: MSEXCEL() : SpreadSheetApp("EXCEL"){}; virtual void OpenFile(string szFile = "book1.xls"){ PrintText("In MSEXCEL::OpenFile"); } void PrintFile(string szFile = "book1.xls"){ PrintText("In MSEXCEL::PrintFile"); } virtual ~MSEXCEL(){ PrintText("In MSEXCEL::~MSEXCEL"); } protected: string m_szFile; }; What is the output of the code shown below Editor ed; SpreadSheetApp sApp; MSEXCEL exApp; Editor *ptrEd = &ed, *ptrSApp = &sApp, *ptrExApp = &exApp; ptrEd->OpenFile(); ptrSApp->OpenFile();

98 ptrExApp->PrintFile(); a)In Editor::OpenFile In SpreadSheet::OpenFile In Editor::PrintFile b) In SpreadSheet::OpenFile In SpreadSheet::OpenFile In SpreadSheet::PrintFile c) Compilation Error d) In Editor::OpenFile In Editor::OpenFile In Editor::PrintFile The correct answer is a. Editor defines OpenFile as a virtual member function. Even if the intermediate parents (in this case SpreadSheetApp) do not declare it as virtual the member function is still virtual. Editor::PrintFile is called since it is not declared as virtual in the base class It is important to note that the actual function called at run time really depends on the dynamic type of the underlying object reference for virtual functions. In this example the dynamic type of ptrEd is Editor*, ptrSApp is SpreadSheetApp* and ptrExApp is MSEXCEL* 2)Look at the following derivations class Base { }; class PublicChild : public Base { }; class ProtectedChild: protected Base { }; class PrivateChild : private Base { }; Which of these (is)/(are) not possible in C++? a)Private and protected inheritance are not possible b)Private is not possible. What's the use?

99 c)All the above derivations are perfectly legal d)Don't know The correct answer is c. All of these are perfectly fine in C++. A publicly derived class inherits the interface of its base class; it has the same interface as its base class. Classes derived using either private or protected do not inherit the base-class interface. Instead, these derivations are often referred to as implementation inheritance. The derived class uses the inherited class in its implementation but does not expose the fact of the inheritance as part of its interface. 3)What is wrong with this code? class MyBase{ protected: static int nCount; }; class PublicChild : public MyBase{ public: PublicChild(){ cout << "Public Child->" << MyBase::nCount << endl; } }; class ProtectedChild: protected MyBase{ public: ProtectedChild(){ cout << "Protected Child->" << ProtectedChild::nCount << endl; } }; class PrivateChild : private MyBase{ public: PrivateChild(){ cout << "Private Child->" << PrivateChild::nCount << endl; } using MyBase::nCount; }; class AnotherChild : public PrivateChild { public: AnotherChild(){ cout << "Another Child->" << PrivateChild::nCount << endl; } };

100

int MyBase::nCount = 0; int main(int argc, char *argv[]){ ProtectedChild pcld; PrivateChild pvtcld; PublicChild pubcld; AnotherChild ancld; return 0; } a)Compilation error at declaration of pvtcld b)Compilation error at declaration of pubcld c)Both a and b d)Nothing is wrong. The code works fine The correct answer is d. Nothing is wrong with this code. Static members of the base follow the regular rule of access specifiers. However note the use of using Base::nCount syntax in PrivateChild. Using this syntax the derived class restores the access level of the base class. The derived class can restore the access level of an inherited member. The access level cannot be made more or less restrictive than the level originally specified within the base class. 4)Look at the code below. What is wrong with this code class A { public: A(string szPublic = "", string szProtected = ""){ m_publica = szPublic; m_protecteda = szProtected; } string m_publica; protected: string m_protecteda; }; class B : public A { public: B(string szPublic = "", string szProtected = "") { m_publicb = "Public b"; m_protectedb = "Protected b";; m_publica = "Public A";

101 m_protecteda = "Protected A"; } string m_publicb; protected: string m_protectedb; }; int main(int argc, char *argv[]){ B b("pubB", "protB"); return 0; } a)Nothing is wrong. It is fine b)It is not a proper way to initialize base class members c)Derived class constructor cannot access base class members since the base object is not yet created d)Don't know The correct answer is b. Base class members should be initialized using the Initialization list syntax. A possibility in this case is B(string szPublic, string szProtected) : A("Public A", "Protected A") 5)In this program the A portion of being is copied in to the local variables in Fn. What is this called? class A { public: A(string szPublic = "", string szProtected = ""){ m_publica = szPublic; m_protecteda = szProtected; } A(const A&a){ m_publica = a.m_publica; m_protecteda = a.m_protecteda; cout << "In A's Copy constructor" << endl; } A& operator = (const A&a){ cout << "In A's =" << endl; m_publica = a.m_publica; m_protecteda = a.m_protecteda; return *this; } string m_publica;

102 protected: string m_protecteda; }; class B : public A { public: B(string szPublic = "", string szProtected = "") : A("Public A", "Protected A") { m_publicb = "Public b"; m_protectedb = "Protected b";; } B(const B&b){ cout << "In B's Copy constructor" << endl; m_publicb = b.m_publicb; m_protectedb = b.m_protectedb; } B& operator = (const B&b){ cout << "In B's =" << endl; m_publicb = b.m_publicb; m_protectedb = b.m_protectedb; return *this; } string m_publicb; protected: string m_protectedb; }; void Fn(B &pB) { A a = pB; A a2(pB); A a3; a3 = pB; } int main(int argc, char *argv[]){ B b("pubB", "protB"); Fn(b); return 0; }

103 a)Conversion b)Typecasting c)Slicing d)Don't know The correct answer is c. This is called slicing 6)What is the output of this program? class A { public: A(string szPublic = ""){ m_publica = szPublic; } virtual void SetPublicString(string str = "PUBLICA"){ m_publica = str; cout << "In A->" << m_publica << endl; } string m_publica; }; class B : public A { public: B(string szPublic = "") : A("Public A") { m_publicb } virtual void SetPublicString(string str = "PUBLICB"){ m_publicb = str; cout << "In B->" << m_publicb << endl; } string m_publicb; }; int main(int argc, char *argv[]){ B b("pubB"); A a("pubA"); B *pb = &b; = "Public b";

104

A *pa = &b; pb->SetPublicString(); pa->SetPublicString(); static_cast<A*>(pb)->SetPublicString(); return 0; } a)In B->Public B In A->Public A In A->Public A b)In B->Public B In B->Public A In B->Public A c)In B->Public B In B->Public B In A->Public A d)Virtual functions cannot have default parameters The correct answer is b. 1. When a virtual is called through a reference or pointer to base, then the default argument is the value specified in the declaration of the virtual in the base class. This is the reason why pa->SetPublicString prints In B>Public A 2. If a virtual is called through a pointer or reference to derived, the default argument is the one declared in the version in the derived class. This is the reason why pb->SetPublicString prints In B->Public B 3. If a call omits an argument that has a default value, then the value that is used is the one defined by the type through which the function is called, irrespective of the object's dynamic type This is the reason why static_cast<A*>(pb)>SetPublicString() prints In A->Public A 7)Which of the following statement(s) is/are correct? Friends of the base class are also friends of the derived class Derived objects can be used to initialize or assign base class objects There is no automatic conversion from the base class to a derived class. If we have a pointer to Base named basePtr, we can cast it at run time to a pointer to Derived using the dynamic_cast operator a)a b)b c)d d)a&d

105

The correct answer is d. Here is a possible usage: if (Derived *derivedPtr = dynamic_cast<Derived*>(basePtr)) { // use the Derived object to which derivedPtr points } else { // BasePtr points at a Base object // use the Base object to which basePtr points } 8)Which of the following statement(s) is/are correct? 1. Friends of the base class are also friends of the derived class 2. Derived objects can be used to initialize or assign base class objects 3. There is no automatic conversion from the base class to a derived class. 4. If we have a pointer to Base named basePtr, we can cast it at run time to a pointer to Derived using the dynamic_cast operator a)a b)b c)d d)a&d The correct answer is d. Here is a possible usage: if (Derived *derivedPtr = dynamic_cast<Derived*>(basePtr)) { // use the Derived object to which derivedPtr points } else { // BasePtr points at a Base object // use the Base object to which basePtr points } 9)Look at the code below class Shape { public: Shape(int nWidth m_nHeight(nHeight){ = 0, int nHeight = 0) : m_nWidth(nWidth),

} virtual void SetDimensions(int nWidth, int nHeight) = 0{ cout << "In Shape::SetDimensions" << endl; } protected: int m_nWidth, m_nHeight;

106 }; class Square : public Shape{ public: Square(int nWidth = 0) : Shape(nWidth, nWidth){ } virtual void SetDimensions(int nWidth, int nHeight){ Shape::SetDimensions(nWidth, nWidth); } }; int main(int argc, char *argv[]){ Square s; return 0; } a. Which of the following statements are false? b. Shape class has a pure virtual function called SetDimensions c. User code cannot create an object of class Shape d. Square class can be instantiated only when it provides an implementation of SetDimensions e. Shape is an abstract base class f. There is a bug in Shape::SetDimensions. Pure virtual functions cannot have a body a)c&f b)b&e c)c&d d)f The correct answer is d. Pure virtual functions can have an optional implementation. 10)Look at the code below. Which statements given below are true void Fn1(Square s) { } void Fn1(Square &s) { } void Fn1(const Square s) { }

107

void Fn1(const Square &s) { } 1. void Fn1(Square s) and void Fn1(Square &s) can't coexist 2. void Fn1(Square &s) and void Fn1(const Square &s) can't coexist 3. void Fn1(Square s) and void Fn1(const Square &s) can't coexist 4. There is no problem with this code. All functions can coexist a)a b)b c)c d)d The correct answer is d. When the parameter is copied, whether the parameter is const is irrelevantthe function executes on a copy. Nothing the function does can change the argument. As a result, we can pass a const object to either a const or nonconst parameter. The two parameters are indistinguishable. It is worth noting that the equivalence between a parameter and a const parameter applies only to nonreference parameters. A function that takes a const reference is different from on that takes a nonconst reference. Similarly, a function that takes a pointer to a const type differs from a function that takes a pointer to the nonconst object of the same type. 11)Given the below polymorphic versions of function 'f'? void f(); void f(int); void f(int, int); void f(double, double = 1.20); Which of the above overloaded functions will be called by the function call f(21, 1.28) a)f(int, int) b)f(double, double) c)This call will give a compilation error d)Don't know The correct answer is c. This function call will give an error since the call is ambiguous. Each of the overloaded functions are equally "good" candidates. In one case int parameter has to be converted to a double and in the other case a double parameter has to be converted to an int 12)What is the output of this code on a 32-bit machine? class Base{ public:

108 int i; int GetI(){ return i; } }; class Virtual1 { public: int d; virtual int GetD(){ return d; } }; class Virtual2 { public: int fd; virtual int GetFD(){ return fd; } }; int main(int argc, char *argv[]){ Base b; Virtual1 d; Virtual2 fd; cout << sizeof(b) << " " << sizeof(d) << " " << sizeof(fd) << endl; return 0; } a)4 4 4 b)4 8 8 c)4 8 12 d)Don't know The correct answer is b. Sizeof(int) is 4 on a 32-bit machine. Adding virtual function to a class introduces a VPTR into the class. The VPTR points to a VTABLE. Hence more than one virtual function does not really increase the size of the class

C++ Week 9 Quiz


1)What is wrong with this code? namespace MyNameSpace{

109 int nStart; } namespace MyNameSpace{ int nEnd; } using namespace MyNameSpace; int main() { nStart = 2; nEnd = 3; } a)Syntax error: A namespace has to have a name b)Multiple declarations of the namespace MyNameSpace c)Cannot access nStart and nEnd as the default access specifier in namespace is private d)There is no problem with the code The correct answer is d. Namespaces are by default open in nature and need not be contiguous. They can even span across translation units. 2)This code is an example of which of the following choices? #include <iostream> using std::cout; using std::endl; int main() { cout << "Hi There" << endl; } a)Using declaration b)Using directive c)This is illegal code in C++ d)Don't know The correct answer is a. It is a selective using of the required declaration in a given namespace. Alternative is to use using directive which is done by using namespace std; Using declaration is an alternative for all-or-nothing approach 3)Consider the file arrangement below //nmspc.h namespace MynameSpace{ void F1(){};

110 } //nmspc.cpp namespace MynameSpace{ void F2(){}; } void Test() { } //main.cpp #include "nmspc.h" using namespace MynameSpace; int main() { F1(); F2(); } Which of the following choices is TRUE about the above code? a)The code has no problems. Both F1 and F2 will compile and link b)The call to F2 will fail to compile since F2 is not known c)The call to both F1 and F2 will fail d)Don't know The correct answer is b. The call to F2 will fail since the compiler has not seen the definition and declaration of F2 as yet while compiling main.cpp. This technique is deliberately used to hide interface from implementation. All interface functions in a namespace are kept in a header file and the internal implementation functions are declared and defined separately 4)What is your reaction on the code below? 1. using namespace std; 2. int nSomeVal = 2; 3. namespace 4. { 5. int nSomeVal = 3; 6. class MyClass 7. { 8. public:

111 9. MyClass(){ 10. cout << "nSomeVal = " << nSomeVal << endl; 11. } 12. } g_MyClass; 13.} 14. int main() 15. { 16. cout << nSomeVal << endl; 17. } a)Compilation error at line 2 b)Compilation error at line 5 c)Compilation error at line 16 d)Compilation error at line 5 and 16 The correct answer is c. There is compilation error at line 16 because main cannot know which nSomeVal is being referenced. Unnamed spaces inject the names in the same scope level as the namespace which in this case is the file level namespace. Also note that the names injected have an internal linkage like static variables and hence cannot be referred in other translation units using "extern"

Você também pode gostar