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.
- 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".
- Puis nous écrivons le nombre (sans le signe) en binaire. Nous obtenons 1110110,101 (avec divisions par deux successives pour la partie décimale)
- 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).
- 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);
}