Algorithmes et C appliqués aux Systèmes Numériques
Les appels systèmes, les erreurs et la chaine de compilation
John Samuel
CPE Lyon
Année : 2018-2019
Courriel : john(dot)samuel(at)cpe(dot)fr
Objectifs
Préprocesseur
Les appels systèmes
Les erreurs
La chaine de compilation
cercle.c
#define PI 3.14159
float area (
float radius ) {
return (PI * radius
* radius );
}
Prototype (defs.h)
#define PI 3.14159
cercle.c
#include "defs.h"
#ifndef PI // Si PI n'est pas défini
#define PI 3.14159
#endif
float area (
float radius ) {
return (PI * radius
* radius );
}
Remarque 1: PI n'est pas une variable
Remarque 2: Utilisez l'option gcc -E pour comprendre l'objectif d'un préprocesseur
Erreur: PI n'est pas une variable
#include "defs.h"
#ifndef PI
#define PI 3.14159
#endif
float area (
float radius ) {
PI = 3.14;
return (PI * radius
* radius );
}
Erreur (compilation)
Error: lvalue required as left operand of assignment
PI = 3.15;
^
operators.h
#ifndef __OPERATORS_H__
#define __OPERATORS_H__
int
add(
int ,
int );
#endif //__OPERATORS_H__
L'utilisation
#include
"operators.h" // en-têtes(headers)
#include
"operators.h" // 2eme fois, mais pas d'erreurs
#ifndef PI
#define PI 3.14159
#endif
#ifndef square
#define square(value) value * value
#endif
float area (
float radius ) {
return (PI * square(radius) );
}
Remarque: Il'n y a pas d'espace entre square et (
struct couleur1{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
};
struct couleur2{
unsigned char rouge;
unsigned int count;
unsigned char vert;
unsigned char bleu;
};
printf (
"size- couleur1: %lu, couleur2: %lu\n" ,
sizeof (
struct
couleur1 ),
sizeof (
struct
couleur2 ));
Question: Quel est l'affichage de ce programme?
Alignement d'un octet
couleur1
couleur2
Alignement de 4 octets
couleur1
couleur2
En utilisant gcc
#pragma pack(push)
#pragma pack(1) //alignement d'un octet
struct couleur3{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
};
#pragma pack(pop)
printf (
"%lu\n" ,
sizeof (struct couleur3 ));
Remarque: L'affichage de ce programme: 7
struct couleur4{ //alignement de 4 octets
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned char _pad;
unsigned int count;
};
struct couleur5{ //alignement de 4 octets
unsigned char rouge;
unsigned char _pad1[3];
unsigned int count;
unsigned char vert;
unsigned char bleu;
unsigned char _pad2[2];
};
Remarque: Utilisez l'option gcc -Wpadded pour savoir si une structure nécessite du padding our être alignée
struct couleur{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
};
int main () {
struct couleur c1 ;
struct couleur *scptr = &c1 ;
c1.bleu = 0xff ;
scptr->bleu = 0x01 ;
printf (
"c1.bleu: %hhx\n" , c1.bleu ); //0x01
}
struct couleur{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
};
void change (
struct couleur *c) {
c->bleu = 0x01 ;
}
int main () {
struct couleur c1 ;
c1.bleu = 0xff ;
change(&c1 );
printf (
"c1.bleu: %hhx\n" , c1.bleu ); //0x01
}
struct couleur{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
};
void nochange (
struct couleur c) {
c.bleu = 0x03 ;
}
int main () {
struct couleur c1 ;
c1.bleu = 0xff ;
nochange(c1 );
printf (
"c1.bleu: %hhx\n" , c1.bleu ); //0xff
}
Une liste de couleurs
struct couleur{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
struct couleur *next;
};
Une liste de couleurs
int main () {
struct couleur first , c1 , c2 ;
struct couleur *cptr ;
first.next = &c1 ;
c1.next = &c2 ;
c2.next = NULL ;
cptr = &first ;
while (cptr != NULL ) { //navigation
printf (
"cptr->bleu: %hhx\n" , cptr->bleu );
cptr = cptr->next ; //couleur suivante
}
}
Une liste de couleurs
struct couleur{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
struct couleur *next;
struct couleur *prev;
};
int main () {
struct couleur first , c1 , c2 , last ;
struct couleur *cptr = &last ;
first.next = &c1 ;
first.prev = NULL ;
last.next = NULL ;
last.prev = &c2 ;
c1.next = &c2 ;
c1.prev = &first ;
c2.next = &last ;
c2.prev = &c1 ;
while (cptr != &first ) { //navigation
printf (
"cptr->bleu: %hhx\n" , cptr->bleu );
cptr = cptr->prev ; //couleur précédente
}
}
int
add(
int
a ,
int
b
) {
return
a
+ b ;
}
int
subtract(
int
a ,
int
b
) {
return
a
- b ;
}
int main () {
int (*func )(int , int ); //pointeur de function
char op = '-' ;
int num1 = 20 , num2 = 30 ;
if (op == '+' ) {
func = add ;
}
else {
func = subtract ;
}
printf ("value: %d\n" ,func (20, 30));
}
/* Fichier: stats.c * la taille d'une fichier
* auteur: John Samuel */ #include
<stdio.h> // en-têtes(headers)
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<unistd.h>
int main (int argc , char ** argv)
{
struct stat sf ;
stat ("./stats.c" , &sf);
printf ("Taille: %ld octets" , sf.st_size );
return 0; }
#include
<stdio.h> // en-têtes(headers)
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<unistd.h>
#include
<stdlib.h>
int main (int argc , char ** argv)
{
struct stat sf ;
int status ;
status = stat (argv[1] , &sf);
if (status == -1) {
perror ("Stats" );
return (EXIT_FAILURE);
}
printf ("Taille: %ld octets" , sf.st_size );
return 0; }
La compilation
$ gcc -o stats stats.c
L'exécution
$./stats stats.c
Taille: ... octets
$ echo $?
0
La compilation
$ gcc -o stats stats.c
L'exécution
$ ./stats nostats
Stats: No such file or directory
$ echo $?
1
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main (int argc , char **argv ) {
if (argc < 2) {
printf ("Usage: readdir path\n" );
return (EXIT_FAILURE);
}
DIR *dirp = opendir (argv [1]);
if (dirp == NULL ) {
perror ("opendir" );
return (EXIT_FAILURE);
}
struct dirent * ent;
while (1) {
ent = readdir (dirp );
if (ent == NULL ) {
break ;
}
printf ("%s\n" , ent->d_name );
}
closedir (dirp );
return (0);
}
#define PORT 8089
int main() {
int socketfd;
int bind_status;
struct sockaddr_in server_addr, client_addr;
/*
* Creation of a socket
* AF_INET: IPv4 Internet protocols
* SOCK_STREAM: two-way, connection-based byte streams
*/
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if ( socketfd < 0 ) {
perror("Unable to open a socket" );
return -1;
}
//server address details
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
//Connect to the server
int connect_status = connect(socketfd, (struct sockaddr *)
&server_addr, sizeof(server_addr));
if ( connect_status < 0 ) {
perror("Unable to connect to server" );
return -1;
}
int main() {
int socketfd;
int bind_status;
struct sockaddr_in server_addr, client_addr;
/*
* Creation of a socket
* AF_INET: IPv4 Internet protocols
* SOCK_STREAM: two-way, connection-based byte streams
*/
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if ( socketfd < 0 ) {
perror("Unable to open a socket" );
return -1;
}
int option = 1;
setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR,
&option, sizeof(option));
//server address details
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
bind_status = bind(socketfd, (struct sockaddr *)
&server_addr, sizeof(server_addr));
if (bind_status < 0 ) {
perror("Unable to bind to socket");
return -1;
}
// Start listening to the socket
listen(socketfd, 10);
char data[1024];
int client_addr_len = sizeof(client_addr);
int client_socket_fd = accept(socketfd,
(struct sockaddr *) &client_addr, &client_addr_len);
if (client_socket_fd < 0 ) {
perror("Unable to accept client requests");
return -1;
}
Préprocesseur
$ gcc -E bonjour.c
Langage intermédiaire
$ gcc -fdump-tree-all bonjour.c
$ gcc -fdump-rtl-all bonjour.c
Optimisation de code
$ gcc -O2 bonjour.c
$ gcc -O3 bonjour.c
Remarque: Autres optimisations: -O1 -O2 -O3 -Os -Ofast -Og
Génération de code natif
$ gcc -S bonjour.c
$ cat bonjour.s
Optimisation de code
int main () {
int num = 2 + 3;
return (0);
}
Compilation (Pas d'optimisations)
$ gcc -O0 -S add.c
add.s
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $5, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
Optimisation de code
int main () {
int num = 2 + 3;
return (0);
}
Compilation (optimisation: 2)
$ gcc -O2 -S add.c
add.s
main:
.LFB0:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
Génération de code
$ gcc -march=i686 -m32 bonjour.c
$ gcc -S -march=i686 -m32 bonjour.c
Code objet
$ gcc -c client.c
$ gcc -c color.c
$ gcc -o color color.o client.o
Code objet (Modifications et recompilation)
$ gcc -c client.c
$ gcc -c color.c
$ gcc -o client client.o color.o
$ vim client.c
$ gcc -c client.c
$ gcc -c client.o color.o
$ vim client.c
$ gcc -c client.c
$ gcc -o client client.o color.o
Makefile
CC ?= gcc
COBJS ?= client.o color.o
SOBJS ?= server.o color.o
.SUFFIXES : .c .o
SERVER = server
CLIENT = client
Makefile
all : $(SERVER) $(CLIENT)
$(SERVER ): $(SOBJS)
$(CC) -o $(SERVER) $(SOBJS)
$(CLIENT ): $(COBJS)
$(CC) -o $(CLIENT) $(COBJS)
.c.o:
$(CC) -c $*.c
Exécution d'un Makefile
$ vim server.c
$ vim client.c
$ vim color.c
$ make
$ vim color.c
$ make
Références
Crédits d'images