Introduction

Nothing to say more than hello 👋, In Case your wondering who is this man in the banner it's the Khwarizmi the inventor of algorithms concept. Make sure to follow because I will start more advanced series in future.

Character arrays and pointers

you can declare char constants using

char a[] = "omar";
char *p  = "omar";

omar will look in the memory like this

01234
omar\0

\0 mean null character which is the end of string.

*(p+3) <=> p[3] <=> a[3]

The main difference between a and p that p can't change the value inside of it. This is the main difference between them. You can access it but not change it , because it is a string constant.

/* strcpy : copy t to s */
void strcpy(char *s , char *t){
    while(*s++ = *t++);
}

this line is amazing just with one line you can copy the array , this work like this it will copy all content from t to s , when it reach the null char it be like this s = '\0' then the entire expression will be null or 0 and while will break.

example 1

//what does the following fragment of c-program print
char c[] = "coding";
char *p = c;
printf("%s" , p+p[2]-p[0]);
//output will be : oding

because p[3]-p[1] = 'd'-'c' = difference in ASCII between d and c = 100-99= 1 , so it will be p+1 elements

0123456
coding\0

example 2

# include <stdio.h>
int main() {
    char a[6] = "world";
    int i,j;
    for(i=0,j=5;i<j;a[i++]=a[j--]);
    printf("%s\n" , a);
}
// output : Null String

it is null because the array is like this

012345
world\0

so when array a[0] = a[5] the string will become

012345
\0orld\0

I can stop here because I already know that the program is printing a , and printing the char stop when it face \0 . So it will stop directly so output is Null String.

Array of pointers and Multidimensional arrays

char *name[] = {"omar" , "khatib" , "omarkhatib"};

this mean that this is an array of pointers to the characters.

image-20200826091624776

Assume starting address of name is 100 , "omar" is 200 , "khatib" is 300 , "omarkhatib" is 400

name+1 will be like I am standing outside of 102 which is cell that pointing to "khatib" , and *(name+1) it's like I am inside the cell which nothing more than the value.

printf("%s" , *(name+1)); //output : khatib

now let's see this other peace of code

printf("%s" , *name+1); // output : mar

We get that result because * have higher president than + so it will point inside the first cell . Then +1 it will move to letter m

printf("%s" , (*(name+2)+7)); //output : tib

I can also access the 8th element (start from 0 so index is 7) from name[2]

printf("%c" , name[2][7]); //output : t

the key difference from this way of implementation and array implementation that arrays like this

char[3][11] = {"omar" , "khatib" , "omarkhatib"}
012345678910
0omar\0
1khatib\0
2omarkhatib\0

last the key difference is that arrays will occupy memory in 2D arrays based on the longest string in them in our case is "omarkhatib"

the pointer implementation is more popular because it doesn't waste any memory , even the pointers will occupy more memory. Also it's easier to access it using pointer rather than arrays.

And each row can be a different size.

Multidimensional arrays , pointers and function

fun(int a[5]);
fun(int a[]);
fun(int *a);

int b[5];
fun(b);

those three are valid because in fact its going to consider as a pointer , so even if you don't pass the size of array it's valid because it's an pointer.

now in case we are passing a 2D array

fun(int a[5][6]);
fun(int a[][6]);
fun(int *(a)[6])

int b[5][6];
fun(b);

those three are valid because it gonna be read like this pointer a which will point to array of 6 elements.

int (*a)[6];
int *a[6];

those two are not the same the first will read as an array point to 6 element . The other is array of pointers which point to integers.

image-20200826095756276

Pointers to functions

This is not commonly used technique , and there is no good libraries that use this method . But yet it is still available in C . Also it make the code difficult to read.

int sum(int , int);
int *fp(int , int);

( have higher president than * , so second line is read like this this is a function which will return pointer to integer.

int(*fp)(int , int);

from the operators table we know that c is left to right association so this will be read , *fp is a pointer which point to an function which take to integers as parameter and will return integer. So it can point to any function like sum.

int s;
*fp = sum;
s = sum(2,5); // output : 7
s = (*fp)(2,5); // output : 7

another complicated thing

void* (*gp)(void * , void *);
int* sum(int* , int*);
gp = (void*(void* , void*))sum;

When you cast type a pointer to another pointer there is no loss of information because as we said earlier they have same size in memory.

Some complex declarations

a) char **argv
b) int (*daytag)[13]
c) int *daytag[13]
d) void *comp()
e) char (*comp)()
f) char (*(*f()))[])()
g) char (*(*f[3])())[5]

a) argv is pointer which point to another pointer.

b) daytag an pointer to an array of 13 element.

c) daytag an array of 13 element that point to an integer

d) comp is a function that return void pointer

e) comp is a pointer to a function that return a char

f) f is an function which return a pointer to an array of pointers to a function which will return char

g) f is an array of 3 pointers and pointers to function returning pointers of 5 characters.

This post is also available on DEV.