IAE Academy

GATE CS

C fundamentals

Types, operators, expressions and control flow

Programming in C fundamentals covers how a value is stored (its type and size), how it is transformed before and during an operation (promotions, conversions, wraparound and overflow), how operators combine values (precedence, associativity, short-circuiting and sequencing), and how control constructs decide what runs next (switch fall-through, loops with break and continue). Questions here are typically short programs to trace, or expressions to classify as well-defined or undefined, so the skill is to apply the C standard's rules mechanically under the stated machine model rather than guess from what one compiler happens to print. Unless a question says otherwise, these notes assume int = 4 bytes, char = 1 byte and signed, two's complement integers and ASCII characters.

7 previous-year questions · 7 solved · 5 practice questions

Data types, sizes and integer promotions

C fixes only minimum sizes and a relative ordering for its integer types, so every size-dependent answer rests on a machine model. Unless a question states its own, these notes use: char = 1 byte, short = 2 bytes, int = 4 bytes, float = 4 bytes, double = 8 bytes, two's complement for signed integers, and ASCII for characters. long is 4 bytes on some systems and 8 on others, so take its size from the question. Whether plain char is signed or unsigned is implementation-defined. These notes take it as signed (as on common x86 compilers). Whenever a question states its own assumption, use that one.

Type

Size (convention above)

Range

signed char (and plain char, taken as signed)

1 byte

−128 to 127

unsigned char

1 byte

0 to 255

short

2 bytes

−32768 to 32767

unsigned short

2 bytes

0 to 65535

int

4 bytes

−2147483648 to 2147483647

unsigned int

4 bytes

0 to 4294967295

long

4 or 8 bytes (take from the question)

as int if 4 bytes; to if 8 bytes

float

4 bytes

IEEE-754 single precision

double

8 bytes

IEEE-754 double precision

N-BIT INTEGER RANGES

Holds for any fixed-width integer type once its width in bits and its signedness are known. Use it to check whether a constant fits the type it is stored in.

STORING AN OUT-OF-RANGE VALUE V IN A SIGNED N-BIT TYPE

The standard leaves this conversion implementation-defined. On the two's complement machines these notes assume, the result is the value above. For example, 200 stored in a signed 8-bit char gives . An unsigned -bit type always stores , and that case is defined by the standard.

  1. Integer promotion: a value of type char, signed char, unsigned char, short, unsigned short, _Bool, a bit-field of those widths, or an enum of lower rank than int is converted to int (or to unsigned int if int cannot hold all its values; under this convention int always can). Promotion happens to the operands of the usual arithmetic conversions (binary + - * / %, relational and equality operators, bitwise & ^ |, and the second and third operands of ?:), to the lone operand of unary +, - and ~, to each operand of << and >> separately, and to arguments passed to the ... part of a variadic function such as printf.

  2. Plain assignment does NOT promote. In x = c; the value of c is converted directly to the type of x. Likewise sizeof(c) is 1, while sizeof(+c) is sizeof(int), because unary + promotes.

  3. After promotion, the usual arithmetic conversions (next section) bring two operands of different types to a common type before the operation.

  4. In C a character constant such as 'A' has type int, so sizeof('A') is sizeof(int), which is 4 here. In C++ it would be 1.

WORKED EXAMPLE

Given char c = 130; on a machine where char is a signed 8-bit two's complement type, what does printf("%d", c); print?

Solution
  1. 130 lies outside the signed 8-bit range −128 to 127.

  2. Reduce it into the range: , so c holds −126. The bit pattern is 10000010.

  3. c is promoted to int when passed to printf, and the value stays −126. %d prints it.

Answer: −126

EXAM TIP

Never assume that an assigned constant survives if it is outside the destination type's range. Reduce it into the type's range first, then work with the stored value.

Signed/unsigned arithmetic and overflow

When the two operands of a binary arithmetic, relational or equality operator have different types, the usual arithmetic conversions give them one common type before the operation runs. Floating types come first: long double, then double, then float. If neither operand is floating, both are promoted and the integer steps below apply. The case that most often surprises is an int meeting an unsigned int: the int is converted to unsigned int, so a negative value becomes a large positive one.

  1. Step 1: if either operand is long double, the other converts to long double. Otherwise, if either is double, the other converts to double. Otherwise, if either is float, the other converts to float.

  2. Step 2: otherwise both operands are integers. Apply integer promotion to each one. If the two promoted types are now the same, stop.

  3. Step 3: if both are signed, or both are unsigned, the operand of lower rank converts to the higher-rank type (for example, int + long gives long).

  4. Step 4: if the unsigned operand's rank is greater than or equal to the signed operand's rank (for example, int with unsigned int, or int with unsigned long), the signed operand converts to the unsigned type. The operation or comparison then happens in unsigned arithmetic, modulo .

  5. Step 5: otherwise the signed operand has the higher rank. If its type can represent every value of the unsigned type (for example, an 8-byte long with unsigned int), the unsigned operand converts to that signed type. If it cannot (for example, a 4-byte long with unsigned int), both convert to the unsigned version of the signed type, here unsigned long.

  6. unsigned char and unsigned short promote to (signed) int, so arithmetic on them happens in int. With unsigned char a = 250;, a + 10 is the int 260. The wrap to 4 happens only when that value is stored back into an unsigned char.

TWO'S COMPLEMENT NEGATION AND UNSIGNED WRAPAROUND

Here is the bitwise complement. Arithmetic done in unsigned int (or a wider unsigned type) never overflows in the undefined-behaviour sense: it is defined to wrap modulo . Signed overflow, such as INT_MAX + 1, is undefined behaviour. Converting an out-of-range value to a signed type is implementation-defined (see the storing rule in the previous section).

Expression

What actually happens

Pitfall

-1 < 0u (an int compared with an unsigned int)

−1 converts to unsigned int, becoming 4294967295, and the comparison is 4294967295 < 0

Evaluates to 0 (false)

unsigned int u = 0; then u - 1

The result wraps to 4294967295 (UINT_MAX), not −1

Causes the endless loop for (unsigned i = n; i >= 0; i--)

INT_MAX + 1 in int

Undefined behaviour; the result is NOT guaranteed to wrap

Never assume a wrapped value for signed overflow

WORKED EXAMPLE

What happens when the following loop runs, given that n is a positive unsigned int?

unsigned int i;
for (i = n - 1; i >= 0; i--) {
    printf("%u ", i);
}
Solution
  1. i is unsigned int, so i >= 0 is always true, because an unsigned value is never negative.

  2. After the body runs with i equal to 0, i-- wraps i to UINT_MAX (4294967295) instead of making it −1.

  3. The condition stays true, so the loop prints n−1 down to 0, then 4294967295 and so on, and never stops.

Answer: Infinite loop: an unsigned int can never make i >= 0 false.

EXAM TIP

When an int and an unsigned int meet in one arithmetic or relational expression, convert the int to unsigned in your head before you evaluate anything.

Operators: precedence, associativity and short-circuit evaluation

Precedence decides which operator binds tighter when two different operators are adjacent. Associativity decides the grouping when operators of the SAME precedence appear in sequence. Neither decides the order in which operands are evaluated; that is a separate question, covered below.

Precedence (high to low)

Operators

Associativity

1 (highest)

() function call, [], ->, ., postfix ++ --

Left to right

2

Unary + - ! ~, prefix ++ --, * (dereference), & (address-of), sizeof, cast (type)

Right to left

3

* / %

Left to right

4

+ - (binary)

Left to right

5

<< >>

Left to right

6

< <= > >=

Left to right

7

== !=

Left to right

8

& (bitwise AND)

Left to right

9

^

Left to right

10

| (bitwise OR)

Left to right

11

&&

Left to right

12

||

Left to right

13

?: (conditional)

Right to left

14

= += -= *= /= %= <<= >>= &= ^= |=

Right to left

15 (lowest)

, (comma operator)

Left to right

  1. && and || short-circuit. In A && B, if A is 0 (false), B is not evaluated at all. In A || B, if A is nonzero (true), B is not evaluated at all.

  2. There is a sequence point after the left operand of && and ||: every side effect of A is complete before B (if it runs) is evaluated.

  3. &&, || and ! yield the int 1 or 0, not the value of an operand. For example, 5 && 7 is 1.

  4. Apart from &&, ||, ?: and the comma operator, the standard does NOT fix the order in which an operator's operands are evaluated. That covers the two sides of + and *, and the arguments of a function call.

  5. Do not assume left-to-right evaluation of function arguments, or of the operands of +, * and similar operators.

WORKED EXAMPLE

What does this program print?

#include <stdio.h>
int f(int *p) {
    *p = 10;
    return 0;
}
int main() {
    int x = 5;
    int r = (x > 3) || f(&x);
    printf("%d", x);
    return 0;
}
Solution
  1. x > 3 is true (1), because x is 5.

  2. The left operand of || is true, so short-circuit evaluation guarantees that f(&x) is never called. r becomes 1.

  3. x is never modified, so it keeps the value 5.

Answer: 5

EXAM TIP

When && or || has a function call or a side effect on its right, first check whether short-circuiting skips that side entirely.

Increment/decrement semantics, undefined behaviour and bitwise/shift operators

x++ (postfix) yields the value of x BEFORE the increment and increments x as a side effect. ++x (prefix) yields the incremented value. Each is well-defined on its own. The behaviour is undefined when, within one expression and with no sequence point in between, a side effect on an object is unsequenced relative to either another side effect on the same object or a read of that object's value (other than the read used to compute the value being stored). The compiler may then produce any result, and different compilers or optimisation levels legitimately disagree. Several reads of the same object are harmless.

  1. Sequence points occur at the end of each full expression (an expression statement's ;, and the controlling expression of if, switch, while, do-while and a return), after the left operand of &&, || and the comma operator, after the condition of ?:, at the end of each full declarator, and after a function's designator and arguments are evaluated but before the call itself.

  2. i = i++ + 1;, a[i] = i++; and printf("%d %d", i, i++) all have undefined behaviour in C. Undefined is not the same as unspecified. There is no correct numeric trace, and the correct answer is that the behaviour is undefined.

  3. *p++ parses as *(p++): postfix ++ binds tighter than unary *. The expression's value is the object at the OLD address, and incrementing p is a side effect completed by the next sequence point. (*p)++ instead increments the object that p points to.

  4. Shift counts: for any integer type, x << k and x >> k are undefined if k is negative or k is at least the width of the promoted left operand (32 for int here).

  5. Left shift: for unsigned x, x << k equals . For signed x, x << k is defined only if x is non-negative and fits in the type. Left-shifting a negative value, or shifting a 1 into or past the sign bit (such as 1 << 31 with a 4-byte int), is undefined behaviour.

  6. Right shift: for unsigned x, or signed x that is non-negative, x >> k equals . For a negative signed x, the result is implementation-defined. With the usual arithmetic (sign-filling) shift, it rounds toward minus infinity, so -7 >> 1 is −4, whereas -7 / 2 is −3.

Operator

Meaning

Note

&

Bitwise AND

Works bit by bit on the promoted operands

|

Bitwise OR

—

^

Bitwise XOR

x ^ x == 0. The XOR swap a ^= b; b ^= a; a ^= b; works for two distinct objects, but zeroes the value if a and b are the same object

~

Bitwise complement (unary)

~x == -x - 1 in two's complement

<<

Left shift

For unsigned int x and :

>>

Right shift

For non-negative or unsigned x: . For negative signed x: implementation-defined

WORKED EXAMPLE

Trace this well-defined program and give its output.

#include <stdio.h>
int main() {
    int i = 5;
    int j = i++;
    int k = ++i;
    printf("%d %d %d", i, j, k);
    return 0;
}
Solution
  1. int j = i++; modifies i once and reads it only to compute the value being stored, so it is well-defined. j gets the old value 5, and i becomes 6.

  2. int k = ++i; increments i from 6 to 7, and k gets the new value 7.

  3. Final values: i = 7, j = 5, k = 7.

Answer: 7 5 7

EXAM TIP

If one full expression modifies a variable twice, or modifies it and also reads it for some purpose other than computing the new value (as in i = i++ + 1 or a[i] = i++), with no &&, ||, ?: condition or comma operator between the two, the answer is undefined behaviour. The comma between function arguments is not the comma operator. i = i + 1 is fine: its one read is needed to compute the value it stores.

Conditional (?:) and comma (,) operators

The conditional operator cond ? a : b evaluates cond first, and there is a sequence point after it. If cond is nonzero, only a is evaluated and becomes the result. Otherwise, only b is. The comma operator e1, e2 evaluates e1 fully (side effects included), discards its value, then evaluates e2; the value and type of e2 are the result. It has the lowest precedence of all C operators. The commas that separate function arguments are NOT the comma operator: they impose no order between the arguments, although every argument is evaluated before the call begins. The commas between declarators in a declaration are not the comma operator either, but each full declarator ends with a sequence point, so int a = 5, b = a + 1; is well-defined and gives b the value 6.

  1. ?: is right-associative: a ? b : c ? d : e parses as a ? b : (c ? d : e).

  2. When the second and third operands are arithmetic, the result type comes from the usual arithmetic conversions of the two. An int branch and a double branch make the whole expression double, even when the int branch is taken. An int branch and an unsigned int branch make it unsigned int, so a taken branch of −1 yields 4294967295.

  3. A common use of the comma operator is to run two expressions in one clause of a for loop: for (i = 0, j = 10; i < j; i++, j--).

  4. In f(a, b) the comma separates arguments: nothing guarantees that a is evaluated before b.

WORKED EXAMPLE

What does this program print?

#include <stdio.h>
int main() {
    int a = 5;
    double b = 2.5;
    printf("%f\n", (a > 3) ? a : b);
    return 0;
}
Solution
  1. a > 3 is true, so the ?: expression evaluates its second operand, a, whose value is 5.

  2. The result TYPE is decided by both branches: int and double convert to double. So the ?: expression is the double 5.0.

  3. %f expects a double, and it gets one, so the call is valid and prints 5.0 with six decimal places. Had the result been int, %f would be undefined behaviour.

Answer: 5.000000

EXAM TIP

Check the types of BOTH branches of a ?:, not just the branch that is taken. The branch that is not taken can still change the result to double or to unsigned.

Control flow: switch fall-through and loops with break/continue

switch (expr) evaluates expr, which must have an integer type and is promoted. Control jumps to the case label whose constant matches the value. If no label matches, control goes to default: if there is one; if there is none, the whole body is skipped. From the label it jumps to, execution runs on through the statements that follow, past any later case labels, until a break or the end of the switch. Case labels are only jump targets, not boundaries. This fall-through is defined C behaviour.

  1. Every case label must be an integer constant expression, and no two labels in the same switch may have the same value.

  2. default: may appear anywhere in the body, not only last. Control goes there only when no case matches.

  3. Without a break, control falls through into the next label's statements, whatever that label's value is.

  4. A break exits the innermost enclosing switch or loop, and only that one.

  5. continue skips the rest of the current iteration. In a for loop it jumps to the update expression, then the condition is tested. In while and do-while it jumps to the condition test.

  6. do { … } while (cond); tests after the body, so the body runs at least once. while and for test first, so their body can run zero times.

  7. An else pairs with the nearest preceding if in the same block that has no else yet, whatever the indentation suggests (the dangling-else rule).

  8. if (x = 0) assigns 0 to x and tests the value assigned, so its body never runs. if (x == 0) is the comparison.

  9. A ; straight after for (…) or while (…) is an empty loop body. for (i = 0; i < 5; i++); runs the empty statement five times and leaves i equal to 5; the next statement then runs once.

Statement

In a loop (for/while/do-while)

In a switch

break

Exits the loop immediately

Exits the switch immediately

continue

Skips to the next iteration (via the update or the condition)

Not allowed in a switch that is not inside a loop. Inside a loop it applies to that loop

WORKED EXAMPLE

Trace the output of:

#include <stdio.h>
int main() {
    for (int i = 1; i <= 5; i++) {
        if (i == 3) continue;
        if (i == 5) break;
        printf("%d", i);
    }
    return 0;
}
Solution
  1. i = 1: not 3 and not 5, so it prints 1.

  2. i = 2: not 3 and not 5, so it prints 2.

  3. i = 3: continue skips printf and jumps to the update, making i 4; the condition is then tested.

  4. i = 4: not 3 and not 5, so it prints 4.

  5. i = 5: break runs before printf, and the loop ends.

Answer: 124

EXAM TIP

A break inside a switch that sits inside a loop leaves only the switch, not the loop. Leaving both needs a flag, a goto, or restructured code.

Division, logical values, sizeof and other trace traps

Several short-program questions turn on how integer division and remainder behave with negative numbers, on the fact that comparisons produce 0 or 1, and on sizeof not evaluating its operand. These rules are fixed by the standard (division truncating toward zero has been required since C99), so they give definite answers.

INTEGER DIVISION IDENTITY IN C

Holds for C integer operands when is representable. Truncation toward zero means that the sign of a % b follows the sign of a. Division or % by zero is undefined behaviour.

  1. / between two integers is integer division even when the result is stored in a double. double d = 7 / 2; stores 3.0. To get 3.5, make one operand floating: 7.0 / 2.

  2. % needs integer operands. 5.0 % 2 does not compile.

  3. Relational, equality and logical operators (<, ==, !, &&, ||) yield the int 0 or 1. In a condition, any nonzero value counts as true.

  4. a < b < c means (a < b) < c: the first comparison gives 0 or 1, and that is compared with c. So 3 > 2 > 1 is 1 > 1, which is 0.

  5. sizeof does not evaluate its operand, unless the operand is a variable-length array. After int i = 5; sizeof(i++);, i is still 5. The result has the unsigned type size_t and is printed with %zu.

Expression

Value (convention above)

Why

7 / 2

3

Integer division truncates

-7 / 2

−3

Truncation toward zero, not −4

-7 % 2

−1

7 % -2

1

7.0 / 2

3.5

One operand is double

3 > 2 > 1

0

(3 > 2) is 1, and 1 > 1 is 0

!5 and !!5

0 and 1

! yields 0 or 1

sizeof('A')

4

A character constant has type int in C

WORKED EXAMPLE

What does this program print?

#include <stdio.h>
int main() {
    int i = 5;
    int s = sizeof(i++);
    int n = printf("%d", -7 / 2);
    printf(" %d %d %d", -7 % 2, i, n);
    return 0;
}
Solution
  1. sizeof(i++) does not evaluate i++, so i stays 5. s gets 4, which is not printed.

  2. -7 / 2 truncates toward zero to −3. The first printf prints -3, which is 2 characters, and returns 2, so n is 2.

  3. -7 % 2 is −1, from .

  4. The second printf prints a space, then −1, 5 and 2 separated by spaces.

Answer: -3 -1 5 2

EXAM TIP

For negative integer division, apply truncation toward zero to / first. Then get % from the identity , not from the non-negative remainder used in mathematics.

printf and scanf behaviour as output questions use it

printf and scanf are variadic functions, and the language does not require the compiler to check their arguments against the format string (many compilers warn anyway). Each conversion specifier must match the type of the argument actually passed, after default argument promotions; otherwise the behaviour is undefined, because no conversion takes place. Output-trace questions often depend on these promotions, on printf's return value, and on the unspecified evaluation order of the arguments.

  1. Default argument promotions in variadic calls: char and short become int (the integer promotions), and float becomes double. That is why %f prints a float variable: it is actually passed as a double.

  2. scanf needs %f for a float * and %lf for a double *. printf prints both with %f, and since C99 it also accepts %lf as meaning the same thing. Mixing up the scanf forms is undefined behaviour.

  3. A mismatched specifier is undefined behaviour, not a conversion. printf("%d", 3.0) does not print 3, and printf("%f", 3) does not print 3.000000.

  4. printf returns the number of characters it printed, as an int. printf("%d", printf("hello")) prints hello5: the inner call must finish (printing hello and returning 5) before the outer call can run.

  5. The order in which the arguments after the format string are evaluated is unspecified. If two arguments modify the same variable, as in printf("%d %d", i++, i++), the behaviour is undefined, and no trace is correct.

  6. scanf returns the number of input items matched and assigned. It returns EOF if input fails before the first conversion. A smaller count than requested means a matching failure or early end of input.

  7. Passing a variable instead of its address to scanf (forgetting &) is undefined behaviour, often a crash, not a compile error in standard C.

WORKED EXAMPLE

What can you correctly say about the output of this program?

#include <stdio.h>
int main() {
    int i = 1;
    printf("%d %d\n", i++, i++);
    return 0;
}
Solution
  1. The evaluations of printf's arguments are unsequenced relative to each other, and both arguments modify the same object i.

  2. Two unsequenced side effects on one object make the behaviour undefined. It is not merely a case of an unspecified order with each value still well-defined.

  3. So no particular pair of numbers is the answer, and different compilers may print different things.

Answer: Undefined behaviour: the C standard does not define what is printed, and the output may differ between compilers.

EXAM TIP

When two arguments of one function call (including printf) both modify the same variable, or one modifies it and another reads it, mark it undefined behaviour. Do not try a left-to-right or right-to-left trace.

PREVIOUS-YEAR QUESTIONS

7 questions from the CS papers

Try each question first, then open the answer. We placed each question under a topic ourselves; the exam paper does not label topics.

See these papers in full: GATE CSE 2025 Set 1 · GATE CSE 2025 Set 2 · GATE CSE 2024 Set 1 · GATE CSE 2022 · GATE CSE 2018

GATE 2025 CS1 Q.63

GATE 2025 · CS1Q.63 · 2 marks · NAT

Consider the following C program:

#include <stdio.h>
int gate (int n) {
    int d, t, newnum, turn;
    newnum = turn = 0; t=1;
    while (n>=t) t *= 10;
    t /=10;
    while (t>0) {
        d = n/t;
        n = n%t;
        t /= 10;
        if (turn) newnum = 10*newnum + d;
        turn = (turn + 1) % 2;
    }
    return newnum;
}
int main () {
    printf ("%d", gate(14362));
    return 0;

}

The value printed by the given C program is _______ . (Answer in integer)

Answer and solution
See the question in the paper
GATE 2025 CS1 Q.63: answer and solution

GATE 2024 CS1 Q.18

GATE 2024 · CS1Q.18 · 1 mark · MCQ

Consider the following C program:

#include <stdio.h>
int main(){
    int a = 6;
    int b = 0;
    while(a < 10) {
        a = a / 12 + 1;
        a += b;}
    printf("%d", a);
    return 0;}

Which one of the following statements is CORRECT?

  1. (A)

    The program prints 9 as output

  2. (B)

    The program prints 10 as output

  3. (C)

    The program gets stuck in an infinite loop

  4. (D)

    The program prints 6 as output

Answer and solution
See the question in the paper
GATE 2024 CS1 Q.18: answer and solution

GATE 2024 CS1 Q.33

GATE 2024 · CS1Q.33 · 1 mark · NAT

Consider the operator precedence and associativity rules for the integer arithmetic operators given in the table below.

| Operator | Precedence | Associativity |
|---|---|---|
| + | Highest | Left |
| − | High | Right |
| * | Medium | Right |
| / | Low | Right |

The value of the expression as per the above rules is ____

GATE 2024 CS1 question 33: A 4-row table (plus header) listing four arithmetic operators with their precedence level and associativity: '+' →…Tap to open full size
Figure from the GATE 2024 CS1 paper. It is part of the question.
Figure description

A 4-row table (plus header) listing four arithmetic operators with their precedence level and associativity: '+' → Highest, Left; '−' → High, Right; '*' → Medium, Right; '/' → Low, Right.

Answer and solution
GATE 2024 CS1 Q.33: answer and solution

GATE 2024 CS1 Q.48

GATE 2024 · CS1Q.48 · 2 marks · MSQ

Consider the following C function definition.

int f(int x, int y) {
  for (int i=0; i<y; i++) {
    x=x+x+y;
  }
  return x;
}

Which of the following statements is/are TRUE about the above function?

  1. (A)

    If the inputs are x=20, y=10, then the return value is greater than

  2. (B)

    If the inputs are x=20, y=20, then the return value is greater than

  3. (C)

    If the inputs are x=20, y=10, then the return value is less than

  4. (D)

    If the inputs are x=10, y=20, then the return value is greater than

Answer and solution
See the question in the paper
GATE 2024 CS1 Q.48: answer and solution

GATE 2022 CS Q.44

GATE 2022 · CSQ.44 · 2 marks · MCQ

What is printed by the following ANSI C program?

#include<stdio.h>

int main(int argc, char *argv[]){
    char a = 'P';
    char b = 'x';
    char c = (a & b) + '*';
    char d = (a | b) - '-';
    char e = (a ^ b) + '+';
    printf("%c %c %c\n", c, d, e);
    return 0;
}

ASCII encoding for relevant characters is given below: A=65, B=66, C=67, ..., Z=90; a=97, b=98, c=99, ..., z=122; *=42, +=43, -=45.

GATE 2022 CS question 44: Three small ASCII reference tables printed below the code: (1) uppercase letters A, B, C,..., Z with codes 65, 66, 67…Tap to open full size
Figure from the GATE 2022 CS paper. It is part of the question.
Figure description

Three small ASCII reference tables printed below the code: (1) uppercase letters A, B, C,..., Z with codes 65, 66, 67,..., 90; (2) lowercase letters a, b, c,..., z with codes 97, 98, 99,..., 122; (3) symbols *, +, - with codes 42, 43, 45.

  1. (A)

    z K S

  2. (B)

    122 75 83

  3. (C)
    • - +
  4. (D)

    P x +

Answer and solution
GATE 2022 CS Q.44: answer and solution

GATE 2018 CS Q.32

GATE 2018 · CSQ.32 · 2 marks · MCQ

Consider the following C code. Assume that unsigned long int type length is 64 bits.

unsigned long int fun(unsigned long int n){
    unsigned long int i, j = 0, sum = 0;
    for (i = n; i > 1; i = i/2) j++;
    for ( ; j > 1; j = j/2) sum++;
    return(sum);
}

The value returned when we call fun with the input is

  1. (A)

    4

  2. (B)

    5

  3. (C)

    6

  4. (D)

    40

Answer and solution
See the question in the paper
GATE 2018 CS Q.32: answer and solution

PRACTICE

5 questions to test yourself

PRACTICE 11 mark · MCQ

Assume char is 1 byte, plain char is signed, and integers use two's complement. Consider the program:

#include <stdio.h>
int main() {
    char c = 200;
    int x = c + 100;
    printf("%d\n", x);
    return 0;
}

What is printed?

  1. (A)

    44

  2. (B)

    300

  3. (C)

    −56

  4. (D)

    156

Answer and solution

Answer: (A)

  1. 200 is outside the signed 8-bit range −128 to 127. Under the stated two's complement assumption (the standard leaves this conversion implementation-defined), the stored value is .

  2. In c + 100, integer promotion converts c to int first, with the value −56 (not 200). The addition is done in int.

  3. .

  4. printf("%d") prints the int value 44.

PRACTICE 22 marks · MSQ

Consider the expression statement i = i++ + ++i; where i is an int. Which of the following statements are TRUE?

  1. (A)

    The statement's behaviour is undefined because i is modified more than once without an intervening sequence point.

  2. (B)

    The result is guaranteed to equal i_old + i_old + 2 on every conforming compiler.

  3. (C)

    The comma operator introduces a sequence point between its two operands.

  4. (D)

    If a side effect on i is unsequenced relative to another side effect on i, or to a read of i's value, the behaviour is undefined, even if every possible evaluation order would give the same number.

Answer and solution

Answer: (A), (C), (D)

  1. i is modified by i++, by ++i and by the assignment, and these side effects are unsequenced relative to each other, with no sequence point between them. The behaviour is undefined, so (A) is true.

  2. Because the behaviour is undefined, no value is guaranteed on every compiler, so (B) is false.

  3. The comma operator puts a sequence point between its operands: the left operand is fully evaluated, side effects included, before the right one. So (C) is true.

  4. The rule on unsequenced side effects is about the program, not about the numbers it produces. The behaviour is undefined even if every order a compiler might choose happens to give the same result, so (D) is true.

PRACTICE 31 mark · NAT

Assume unsigned char is 1 byte (range 0 to 255) and int is 4 bytes. What is printed by:

#include <stdio.h>
int main() {
    unsigned char a = 250;
    a = a + 10;
    printf("%d", a);
    return 0;
}
Answer and solution

Answer:

  1. In a + 10, a is promoted to int (value 250), so the addition is done in int. Nothing wraps yet.

  2. Storing 260 in the 1-byte unsigned char a reduces it modulo 256, which is defined for unsigned types: .

  3. a now holds 4. In printf("%d", a), a is promoted to the int 4, which matches %d, so 4 is printed.

PRACTICE 42 marks · MCQ

What does the following program print?

#include <stdio.h>
int main() {
    int x = 2;
    switch (x) {
        case 1:
            printf("A");
        case 2:
            printf("B");
        case 3:
            printf("C");
            break;
        case 4:
            printf("D");
    }
    return 0;
}
  1. (A)

    B

  2. (B)

    BC

  3. (C)

    BCD

  4. (D)

    ABC

Answer and solution

Answer: (B)

  1. switch (x) with x == 2 jumps straight to the label case 2:. The statements under case 1: are not executed.

  2. There is no break after case 2:, so execution falls through into case 3:. It prints B, then C.

  3. The break at the end of case 3: leaves the switch before case 4: is reached.

  4. Total output: BC.

PRACTICE 52 marks · NAT

Assume the compiler implements right shift of a negative signed integer as an arithmetic (sign-filling) shift. int is 4 bytes, in two's complement. What is printed by:

#include <stdio.h>
int main() {
    int x = -8;
    int y = x >> 2;
    printf("%d", y);
    return 0;
}
Answer and solution

Answer:

  1. In two's complement, −8 ends in the bits …11111000.

  2. An arithmetic right shift by 2 moves the bits right and fills the vacated high bits with copies of the sign bit (1), giving …11111110.

  3. That pattern is the two's complement representation of −2. Equivalently, .

  4. So y = -2, and printf prints −2. The standard leaves right-shifting a negative value implementation-defined, which is why the question states the arithmetic-shift assumption. A logical shift would give a large positive number instead.

OFFICIAL GATE 2027 SYLLABUS WORDING

Copied from the GATE 2027 syllabus; see all 2027 syllabi.

GATE CS

Programming in C

Preparing in Kolkata? IAE Academy's course for GATE CSE.