C fundamentals
Fundamentals of C.
C fundamentals
I resumed learning C. It is actually pretty fun! I learned a few neat things from beej's guide for C. It was nice. Must read: Brian Jorgensen Hall's blog
C is not a big language, and it is not well served by a big book.
-- Brian W. Kernighan, Dennis M. Ritchie
Booleans in C
Traditionally, 0 is false, and any other value is
true. #include <stdbool.h> to include a
bool type, same semantics.
Operators
Standard operators. Also, ternary operator.
Ternary operator is NOT flow control. It is an expression that evaluates to something.
Also, there is pre and post decrement. Stir clear of these unless you know what you are doing.
int x = (1, 2, 3);
/* x is 3 in this case */Short circuiting
&& only of both are true. || if
atleast one is true. ! takes the current value and
inverts it. They operate on stuff meant to be boolean kinda.
The first two have something called short circuiting. If the
first one is false, the second one isn't even evaluated in case of
&&. Similarly if the first one is true, second
one isn't even evaluated in case of ||.
Special functions
printf: Well, prints stuff. Look up manpage for more
info.
sizeof: returns the size of anything. It's return
type is an unsigned int called size_t.
It's a compile time operator, not a function
Note
It is compile time to use sizeof
Switch case
Always specify when you need a fallthrough.
#include <stdio.h>
int x = 0;
int main() {
switch (x) {
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("any other value\n");
}
}If break isn't there all the other cases are evaluated unless a break is encountered.
Functions in C
If the parentheses in a C function are empty, it means it can
take in any number of arguments. Not sure what the usecase is
though. To specify no arguments, use void.
Arguments are copied. To modify the original thing pass a pointer.
A prototype is the signature that tells the compiler what the function takes in and spits out. Ends with a semicolon.
Pointers in C
Hold memory locations. Really, that's all there is to it.
#include <stdio.h>
int main(void)
{
int i = 10;
printf("The value of i is %d\n", i);
printf("And its address is %p\n", (void *)&i);
// %p expects the argument to be a pointer to void
// so we cast it to make the compiler happy.
}The address of anything can be obtained with =&= in front of it. To get the value from the address, use =*= in front of it.
Important
Note on pointer declaration: int *p, q; over here
only p is a pointer, q is a regular int.
Pointer arithmetic
Integers can be added to pointers and the pointers move forward
or backward by those many units. C makes sure that the pointer is
incremented by sizeof(type) if the pointer is
type *.
void pointer
- Can point to anything.
- Cannot be dereferenced.
- No pointer arithmetic.
- sizeof(void *) will most likely crash.
- Can be legally typecasted to and from any other pointer.
Arrays in C
No surprises here either. You cannot have arrays with variable length, (you technically can), and you need to store the value of the length separately.
If you declared an array in the same scope you can check its size
using sizeof(arr)/sizeof(arr[0]).
Stuff like this also works:
int a[10] = {0, 11, 22, [5]=55, 66, 77};
Intermediate values and others are set to be 0. We can leave the size to be blank if we specify all values in the constructor initializer.
Arrays also act as pointers.
int main() {
int a[10] = {0};
int *p = a;
p = &a[0];
}Always pass the size of the array as a separate variable.
For multidimensional arrays, you have to pass all the dimensions except for the first one.
Array and pointer equivalence
E1[E2] == (*((E1) + (E2)))
Strings in C
Arrays of characters terminated by the null character.
int main() {
char *s = "Hello world\n";
char t[] = "Loss pro max\n";
}In the above example, s is /immutable/ because it points to a hardcoded place in memory. On the other hand, the array copies the individual bytes from the hardcoded location and is therefore mutable.
strlen function returns the length of a
null-terminated string and its return type is
size_t.
strcpy makes a copy of the string byte by byte.
Notice that doing t = s does not exactly copy the
string as it only changes t to point to the same hardocded string
and is not two different memory locations.
Structs
Ordered data-type containing various kinds of data fields.
struct car {
char *name;
float price;
int speed;
};
// Now with an initializer! Same field order as in the struct declaration:
struct car saturn = {"Saturn SL/2", 16000.99, 175};
printf("Name: %s\n", saturn.name);
printf("Price: %f\n", saturn.price);
printf("Top Speed: %d km\n", saturn.speed);struct car saturn = {.speed=175, .name="Saturn SL/2"};
something like this can also be done.
Whatever isn't initialized explicitly is initialised to 0 in memory.
Dot to access fields, arrow to access if it is a pointer to a struct.
Caution
Do NOT compare structs directly.
The structs are laid out in memory in the same way as they are declared in the struct declaration, barring the fact that there might be struct padding in between them.