C language

    Require: build-essential packet.

    Hello Summary

    #include <stdlib.h>
    #include <stdio.h>
    
    int fib(int n) {
      if(n < 0) {
        fprintf(stderr, "n=%d, must be positive\n", n);
        exit(EXIT_FAILURE);
      }
    
      if (n == 0) return 0;
    
      if (n == 1 || n == 2) return 1;
    
      return fib(n-1) + fib(n-2);
    }
    
    typedef struct Point {
      int x;
      int y;
    } Point;
    
    
    typedef enum {
      SUCCESS = 1,
      FAIL = 0
    } STATUS;
    
    int main(int argc,  char* argv[]) {
    	printf("fib(4)=%d\n", fib(atoi(argv[1])));
    
      // stack memory
      Point p; p.x = 5; p.y = 5, 6;
      printf("p.x=%d\n", p.x);
    
      // heap memory
      Point *pp;
      if((pp = malloc(sizeof *pp)) == NULL) { fprintf(stderr, "impossible to have memory on heap"); exit(EXIT_FAILURE); }
      pp->x = 7; pp->y = 10;
      printf("pp->x=%d\n", pp->x);
    
      STATUS status = SUCCESS;
    
      switch(status) {
        case SUCCESS:
          printf("success\n");
          break;
        case FAIL:
          printf("fail\n");
          break;
        default:
          printf("default\n");
          break;
      }
    
      exit(EXIT_SUCCESS);
    }
    
    

    Data Structures

    Binary Heap

    See binary heap

    Fork

    See Fork

    Dup

    The function dup((utilise le plus petit numéro inutilisé pour le nouveau descripteur)) use the smallest number of file descriptor which is available.

    So if you close 1, it will redirect 1 to the file descriptor.

    Here is an example which redirect output standard to file descriptor.

    FILE fd = open(...);
    ...
    close(1); /* close standard output descriptor */
    dup(fd); /* duplicate the smallest number of file descriptor available, here 1, because we just have close standard output */
    ... /* that's it ! */
    close(fd); /* don't forget to close fd of couse */
    

    Type

    In croissant((byte size)) order we find:

    • char ((1 byte : 2^8 from -128 to 127))
    • short ((2 byte : 2^16 from -32768 to 32767))
    • int ((4 byte : 2^32 from -2^16 to (-2^16)-1 because there is 0))
    • long ((4 byte : 2^32 from -2^16 to (-2^16)-1 because there is 0))
    • long long ((8 byte : 2^64 from -2^16 to (-2^16)-1 because there is 0))
    • float
    • Double

    If you add unsigned before type, you will have an unsigned number and you could be touch limit byte.

    Operator

    #include `<stdio.h>`
    #include `<stdlib.h>`
    
    int main()
    {
      unsigned short a = 0xFFF0;
      unsigned short b = 0x0FFF;
    
      unsigned short c = a & b; // and
      unsigned short d = a | b; // or
      unsigned short e = a ^ b; // xor
    
      printf("%X\n", c); // FF0
      printf("%X\n", d); // FFFF
      printf("%X\n", e); // 0FF0
    
      return 0;
    }
    

    Pointer

    When you use malloc, and just after you free memory, your variable continue to pointing to an address memory. So you have to set it to NULL.

    #include `<stdlib.h>`
    #include `<stdio.h>`
    
    int main(){
    	int *pointer;
    
    	pointer = calloc(1, sizeof(int));
    
    
    	*pointer = 5;
    
    	printf("[Before free]\n");
    	printf("adr: %p\n", pointer);
    	printf("val: %d\n\n", *pointer);
    	free(pointer);
    
    	printf("[After free]\n");
    	printf("adr: %p\n", pointer);
    	printf("value: %d\n\n", *pointer);
    
    	/* so we need that : */
    
    	pointer = NULL;
    
    	printf("[After NULL]\n");
    	printf("adr: %p\n", pointer);
    	printf("value: %d\n\n", *pointer);
    
    	return EXIT_SUCCESS;
    }
    

    Associated output:

    laubosslink@pc-lbl:/media/files/projects/singular/lab/c/c-pointer$ ./simple_test
    [Before free]
    adr: 0x1a2e010
    val: 5
    
    [After free]
    adr: 0x1a2e010
    value: 0
    
    [After NULL]
    adr: (nil)
    Segmentation fault (core dumped)
    

    Libraries

    Std lib

    Basic usage for memory, convert type, random number.

    Functions: free, malloc, realloc, rand, exit

    Constants: EXIT_SUCCESS

    Math

    Functions: cos, sin, sqrt, pow

    Require: math.h and -lm option with gcc complation.

    Enum

    enum couleur {
    	BLANC=0,
    	GRIS=1,
    	NOIR=2
    };
    

    Delicate Issue

    Handle an error

    Solution 1

    void initTab(int *tab, int taille){
    	if(taille <= 0 || tab == NULL){
    		fprintf(stderr, "prob taille ou alloc");
    		return;
    	}
    	// ...
    }
    

    Note: Not good because if you don't have screen anybody see that.

    Solution 2

    int initTab(int *tab, int taille){
    	if(taille <= 0 || tab == NULL){
    		fprintf(stderr, "prob taille ou alloc");
    		return -1;
    	}
    	// ...
    }
    

    Note: Better than solution 1 cause another function could retrieve the result (-1) and adjust his work from the problem.

    Solution 3

    void initTab(int *tab, int taille){
    	assert(taille >= 0 && tab);
    	// ...
    }
    

    Note: stop program, and give line of assert.

    Multiplication int to long

    I'll show an example of a multiplication, and explain the result.

    #include `<stdio.h>`
    
    int main(){
    	int i1 = 2000000000;
    	int i2 = 1000000000;
    
    	long long l1 = i1 + i2;
    
    	printf("%lld\n", l1); // return -1294967296 instead of 3000000000
    
    	/**
    	 * to resolve this, change var type of i1 or i2 from : int to long
    	 * even if long is equivalent to int, gcc seems to be better to understand the multiplication with long
    	 * you could also resolve this to cast (long) during multiplication see below :
    	 * */
    
    	l1 = (long) i1 + i2;
    	printf("%lld\n", l1);
    
    	return 0;
    }
    

    Note: This problem happening too with addition. Note: This will just happening with ''int'' to ''long long''. I've try with ''short'' to ''int'' i've not this problem.

    Float loss with multiplication

    #include `<stdio.h>`
    #include `<stdlib.h>`
    
    int main(){
            float in;
            int somme;
    
            printf("Veuillez entrer un montant: "); // 155.76
    
            scanf("%f", &in);
    
            somme = in * 100; // contain 15575 (we lost 1)
    
    
            printf("Veuillez entrer un montant: "); // 1555.76
    
            scanf("%f", &in);
    
            somme = in * 100; // contain 155576 (no problem)
    }
    

    Resolve: Use double type instead of float, and %lf instead of %f in scanf(...).

    <latex>``</latex>

    Codage d'un flottant et addition

    #include `<stdio.h>`
    
    int main(void){
            int n=0;
            double e=1.0;
    
            do {
                    e/=10.0;
                    n++;
            } while(1.0+e!=1.0);
    
            printf("e = 10^-%d\n",n); // On obtient n=16
    
            return EXIT_SUCCESS;
    }
    

    Explication: Lorsqu'on fait ''1.0 + e'' c'est équivalent à $2^{0}\times(1+2^{-100})$. Car l'addition des deux nombres est stocké dans un nombre flottant, et le codage d'un nombre((basé sur la norme IEE754 : http://fr.wikipedia.org/wiki/IEEE_754)) flottant utilise une mantisse.

    Exemple: Codons le nombre décimal −118,625 en utilisant le mécanisme IEEE 754.

    1. Premièrement, nous avons besoin du signe, de l'exposant et de la partie fractionnaire. C'est un nombre négatif, le signe est donc "1".
    2. Puis nous écrivons le nombre (sans le signe) en binaire. Nous obtenons 1110110,101 (avec divisions par deux successives pour la partie décimale)
    3. Ensuite, nous décalons la virgule vers la gauche, de façon à ne laisser qu'un 1 sur sa gauche : 1110110,101 (bin) = 1,110110101 (bin) × 2^6. C'est un nombre flottant normalisé : la mantisse est la partie à droite de la virgule, remplie de 0 vers la droite pour obtenir 23 bits. Cela donne 110 1101 0100 0000 0000 0000 (on omet le 1 avant la virgule, qui est implicite).
    4. L'exposant est égal à 6, et nous devons le convertir en binaire et le décaler. Pour le format 32-bit IEEE 754, le décalage est 2^(8-1)-1 = 127. Donc 6 + 127 = 133 (dec) = 1000 0101 (bin).
    > On a donc −118,625 (dec)1100 0010 1110 1101 0100 0000 0000 0000 (bin) = C2ED4000 (hexa)

    Lors de l'addition, on factorise par la plus grande puissance de 2.

    Donc il faudrait 100 bit pour stocker le 2^-100, car le stockage de la mantisse se base sur la plus grande puissance de 2, donc on factorise par 2^0. Car 1.0 c'est 1*2^0

    schema : |___|| (bp........bp) (p)

    e=1______0 | -100

    avec p = -100

    ceci est la représentation de 2^-100

    <latex>x = \sum_{i=-p}^{p} \left ( b_i 2^i \right ) = 2^p \times \sum_{i=-1}^{p} (b_i 2^{i-p})</latex>

    Reallocate static array

    We can't do that.

    Example :

    #include `<stdlib.h>`
    #include `<stdio.h>`
    
    void reductionMemoire(int *tab, int nouvelleTaille){
    	tab = realloc(tab, sizeof(int) * nouvelleTaille); // can't use realloc on static array ! (())
    }
    
    int main(){
    	int tab[] = {3,4,0,0,5,0,6,7,8,0,0,9,0,0,0,0,1,2}; // static array
    	reductionMemoire(tab, 5);
    }