Primitives
Primitive types in C are shown in this table:
Category | Types |
---|---|
Integer | char, unsigned char, signed char, short, unsigned short, int, unsigned int, long, unsigned long |
Floating-Point | float, double, long double |
Void | void |
Initialization
int main() {
int i = 0;
char a[6] = {'H','e','l','l','o','\0'};
char b[] = "Hello";
char* c = "Hello";
return 0;
}
Integer promotion
Integer promotion is a process in C that automatically converts "smaller" integer types to "larger" integer types in certain situations to avoid data loss during expressions or function calls. This promotion follows a set of rules defined by the C standard.
For example:
#include <stdio.h>
int main() {
char charVar = 127; // A signed char with maximum positive value
int intVar = 1000;
// The expression involving charVar will undergo integer promotion
int result = charVar + intVar;
printf("Result: %d\n", result);
return 0;
}
Type Qualifiers
In C, type qualifiers are used to specify additional properties of variables.
int main() {
// Should only be accessed from this pointer
restrict int* a;
// Its value should not be modified after initialization
const int b;
// Can only be modified by one thread at a time
atomic int c;
// The variable's value can be changed at any time by external
// factors not explicitly specified in the program
volatile int d;
return 0;
}
Storage Class specifiers
In addtion to the above qualifiers, C still has a bunch of storage class specifiers which define the storage duration of an object.
int main() {
// The extern storage class is used to declare a variable that is defined in
// another source file or will be defined later in the program.
extern int a;
// The static storage class is used to make a variable retain its value between function calls.
// It is also used for file scope (global) variables,
// limiting their visibility to the file in which they are declared.
static int b;
// The register storage class suggests to the compiler that the
// variable should be stored in a register for quicker access.
register int c;
// The auto storage class is the default for local variables.
// It is rarely used explicitly.
auto int d;
// _Thread_local indicates that a variable has thread storage duration
_Thread_local int e;
return 0;
}
Typedef
typedef
is used to add an additional name to an existing type.
#include <stdio.h>
typedef unsigned char byte;
int main() {
byte b = 'a';
return 0;
}
Bitwise Operations
Bitwise operations in C are used to manipulate individual bits of variables. The bitwise operators include AND (&
), OR (|
), XOR (^
), left shift (<<
), and right shift (>>
).
#include <stdio.h>
int main() {
// Bitwise AND (&) example
unsigned int x = 0b001; // Binary representation of 1
unsigned int y = 0b101; // Binary representation of 5
unsigned int result_and = x & y;
printf("Bitwise AND: %u\n", result_and); // Output: 1
// Bitwise OR (|) example
unsigned int result_or = x | y;
printf("Bitwise OR: %u\n", result_or); // Output: 5
// Bitwise XOR (^) example
unsigned int result_xor = x ^ y;
printf("Bitwise XOR: %u\n", result_xor); // Output: 4
// Bitwise left shift (<<) example
unsigned int result_left_shift = x << 2;
printf("Bitwise Left Shift: %u\n", result_left_shift); // Output: 4
// Bitwise right shift (>>) example
unsigned int result_right_shift = y >> 1;
printf("Bitwise Right Shift: %u\n", result_right_shift); // Output: 2
return 0;
}
Compound Assignment
Compound assignments in C are shorthand notations that combine an arithmetic or bitwise operation with the assignment operation. The compound assignment operators include +=
, -=
, *=
, /=
, %=
, &=
, |=
, ^=
, <<=
, and >>=
.
#include <stdio.h>
int main() {
int x = 58;
x += 2;
x /= 2;
printf("x = %d\n", x);
return 0;
}
Code Challenge
Write a C function named
countSetBits
that takes an unsigned integer as input and returns the count of set bits (1
s) in its binary representation.