Programmation en C Les appels systèmes, les erreurs et la chaine de compilation
John Samuel
CPE Lyon
Année: 2020-2021
Courriel: john(dot)samuel(at)cpe(dot)fr
/* Une variable constante
*/
#include <stdio.h>
int main()
{
const int year = 2017; // une variable constante
year = 2019; // une variable constante
printf("C'est l'annee %d", year); //affiche 2017
return 0;
}
$ gcc bonjour.c
const.c: In function ‘main’:
const.c:5:8: error: assignment of read-only variable ‘year’
year = 2019;
/* affiche un message à l'écran en utilisant une variable globale
*/
#include <stdio.h>
int year = 2017 // une variable globale;
int main()
{
printf("C'est l'annee %d", year); //affiche 2017
return 0;
}
/* affiche un message à l'écran en utilisant une variable globale
*/
#include <stdio.h>
int main()
{
printf("C'est l'annee %d", year);
return 0;
}
int year = 2017 // une variable globale;
$ gcc bonjour.c
bonjour.c: In function ‘main’:
bonjour.c:5:30: error: ‘year’ undeclared (first use in this function)
5 | printf("C'est l'annee %d", year);
| ^~~~
bonjour.c:5:30: note: each undeclared identifier is reported only once for each function it appears in
/* affiche un message à l'écran en utilisant une variable locale
*/
#include <stdio.h>
int year = 2017 // une variable globale;
int main()
{
int year = 2018 // une variable locale;
printf("C'est l'annee %d", year); //affiche 2018
return 0;
}
/* affiche un message à l'écran en utilisant une variable locale
*/
#include <stdio.h>
int year = 2017 // une variable globale;
int main()
{
int year = 2018 // une variable locale;
{
int year = 2019 // une variable locale;
printf("C'est l'annee %d", year); //affiche 2019
}
return 0;
}
void
echange(
int
a,
int
b
) {
int
temp
= a;
a
= b;
b
= temp;
}
int main()
{
int a = 10;
int b = 20;
echange(a, b);
printf("a: %d, b: %d", a, b); //affiche 10, 20
return 0;
}
void
echange(
int
*a,
int
*b
) {
int
temp
= *a;
*a
= *b;
*b
= temp;
}
int main()
{
int a = 10;
int b = 20;
echange(&a, &b);
printf("a: %d, b: %d", a, b); //affiche 20, 10
return 0;
}
void
affichage(
char
message[10]
) {
printf("%s\n", message);
}
int main()
{
char message[10] =
"Bonjour";
affichage(message);
return 0;
}
void
affichage(
char
message[]
) {
printf("%s\n", message);
}
int main()
{
char message[10] =
"Bonjour";
affichage(message);
return 0;
}
void
affichage(
char
*message
) {
printf("%s\n", message);
}
int main()
{
char message[10] =
"Bonjour";
affichage(message);
return 0;
}
void
affichage(
int
tableau[2][2]
) {
for ( int i = 0;
i < 2; i++) {
for ( int j = 0;
j < 2; j++) {
printf("%d\n",
tableau[i][j]);
}
}
}
int main()
{
int prix[2][2] = {
{11, 12},
{13, 14}};
affichage(prix);
return 0;
}
void
affichage(
int
tableau[][]
) {
for ( int i = 0;
i < 2; i++) {
for ( int j = 0;
j < 2; j++) {
printf("%d\n",
tableau[i][j]);
}
}
}
int main()
{
int prix[2][2] = {
{11, 12},
{13, 14}};
affichage(prix);
return 0;
}
$ gcc tableau.c
tableau.c:3:21: error: array type has incomplete element type ‘int[]’
3 | void affichage( int tableau[][] ) {
| ^~~~~~~
tableau.c:3:21: note: declaration of ‘tableau’ as multidimensional array must have bounds for all dimensions except the first
tableau.c: In function ‘main’:
tableau.c:15:13: error: type of formal parameter 1 is incomplete
15 | affichage(prix);
void
affichage(
int
tableau[][2]
) {
for ( int i = 0;
i < 2; i++) {
for ( int j = 0;
j < 2; j++) {
printf("%d\n",
tableau[i][j]);
}
}
}
int main()
{
int prix[2][2] = {
{11, 12},
{13, 14}};
affichage(prix);
return 0;
}
void
affichage(
int
(*tableau)[2]
) {
for ( int i = 0;
i < 2; i++) {
for ( int j = 0;
j < 2; j++) {
printf("%d\n",
tableau[i][j]);
}
}
}
int main()
{
int prix[2][2] = {
{11, 12},
{13, 14}};
affichage(prix);
return 0;
}
void
affichage(
int
**tableau,
int
lignes,
int
colonnes
) {
for ( int i = 0;
i < lignes; i++) {
for ( int j = 0;
j < colonnes; j++) {
printf("%d\n",
tableau[i][j]);
}
}
}
int main()
{
int **prix, lignes, colonnes;
....
affichage(prix);
return 0;
}
int main()
{
int **tableau, lignes = 2, colonnes = 10;
tableau = calloc(sizeof(int *), lignes);
for ( int i = 0;
i < lignes; i++) {
tableau[i] = calloc(sizeof(int), colonnes);
}
for ( int i = 0;
i < lignes; i++) {
for ( int j = 0;
j < colonnes; j++) {
tableau[i][j] = i+j;
}
}
affichage(tableau,
lignes,
colonnes);
for ( int i = 0;
i < lignes; i++) {
free(tableau[i]);
}
free(tableau);
return 0;
}
#define PI 3.14159
float area(
float radius) {
return(PI * radius
* radius);
}
#define PI 3.14159
#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);
}
Error: lvalue required as left operand of assignment
PI = 3.15;
^
int
add(
int,
int);
#include
"operators.h" // en-têtes(headers)
#include
"operators.h" // pas d'erreurs
int
num = 20;
#include
"operators.h" // en-têtes(headers)
#include
"operators.h" // erreur
$ gcc operator.c
note: previous definition of ‘num’ was here
int num=20;
#ifndef __OPERATORS_H__
#define __OPERATORS_H__
int
num = 20;
int
add(
int,
int);
#endif //__OPERATORS_H__
#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?
#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
(*scptr).bleu = 0x22;
printf(
"c1.bleu: %hhx\n", c1.bleu); //0x22
}
struct couleur *scptr = &c1;
(*scptr).bleu | scptr->bleu |
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
}
struct couleur{
unsigned char rouge;
unsigned char vert;
unsigned char bleu;
unsigned int count;
struct couleur *next;
};
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
}
}
struct element{
unsigned int numero;
struct element *suivant;
};
// insertion d'un élement dans une liste
void insertion(struct element*, int);
// parcours de la liste
void parcours(struct element *);
int main() {
struct element premier;
premier.suivant = NULL;
while(1) {
int num;
char strnum[50];
fgets(strnum, sizeof(strnum), stdin);
if(strcmp(strnum, "FIN\n") == 0) {
break;
}
sscanf(strnum, "%d\n", &num);
insertion(&premier, num);
}
parcours(&premier);
}
void insertion(struct element *premier, int num) {
struct element *nouveau;
nouveau = malloc(sizeof(*nouveau));
nouveau->num = num;
nouveau->suivant = premier->suivant;
premier->suivant = nouveau;
}
void parcours(struct element *premier) {
struct element *elem = premier;
while(elem != NULL) {
printf("%d\n", elem->num);
elem = elem->suivant;
}
}
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
}
}
struct element {
int num;
struct element *suivant;
struct element *precedent;
};
struct liste {
struct element premier;
struct element dernier;
};
void insertion_debut(struct liste *, struct element *);
void insertion_fin(struct liste *, struct element *);
void parcourir_debut(struct liste *);
void parcourir_fin(struct liste *);
void insertion_debut(struct liste *liste,
struct element *nouveau) {
nouveau->suivant = liste->premier.suivant;
nouveau->precedent = &liste->premier;
liste->premier.suivant->precedent = nouveau;
liste->premier.suivant = nouveau;
}
void insertion_fin(struct liste *liste,
struct element *nouveau) {
nouveau->suivant = &liste->dernier;
nouveau->precedent = liste->dernier.precedent;
liste->dernier.precedent->suivant = nouveau;
liste->dernier.precedent = nouveau;
}
void parcourir_debut(struct liste *liste) {
struct element *elem = liste->premier.suivant;
while(elem != &liste->dernier) {
printf("%d\n", elem->num);
elem = elem->suivant;
}
}
void parcourir_fin(struct liste *liste) {
struct element *elem = liste->dernier.precedent;
while(elem != &liste->premier) {
printf("%d\n", elem->num);
elem = elem->precedent;
}
}
int main() {
struct liste liste;
liste.premier.suivant = &liste.dernier;
liste.dernier.precedent = &liste.premier;
liste.premier.precedent = NULL;
liste.dernier.suivant = NULL;
while (1) {
char strnum[50];
struct element *elem = malloc(sizeof(*elem));
fgets(strnum, sizeof(strnum), stdin);
if(strcmp(strnum, "FIN\n") == 0) {
break;
}
sscanf(strnum, "%d\n", &elem->num);
insertion_fin(&liste, elem);
}
parcourir_debut(&liste);
parcourir_fin(&liste);
}
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;
}
$ gcc -o stats stats.c
$./stats stats.c
Taille: ... octets
$ echo $?
0
$ gcc -o stats stats.c
$ ./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;
}
#ifndef PI
#define PI 3.14159
#endif
float area(
float radius) {
return(PI * radius
* radius);
}
$ gcc -E cercle.c
# 1 "cercle.c"
# 1 ""
# 1 ""
# 31 ""
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "" 2
# 1 "cercle.c"
float area(float radius) {
return(3.14 * radius * radius);
}
$ gcc -v bonjour.c # les étapes importantes
$ gcc -save-temps -v bonjour.c # les fichiers *.i, *.s
$ gcc -fdump-tree-all bonjour.c
$ gcc -fdump-rtl-all bonjour.c
$ gcc -fdump-tree-all -c cercle.c
$ cat cercle.c.005t.gimple
area (float radius)
{
float D.1914;
_1 = (double) radius;
_2 = _1 * 3.140000000000000124344978758017532527446746826171875e+0;
_3 = (double) radius;
_4 = _2 * _3;
D.1914 = (float) _4;
return D.1914;
}
$ gcc -O2 bonjour.c
$ gcc -O3 bonjour.c
Remarque: Autres optimisations: -O1 -O2 -O3 -Os -Ofast -Og
$ gcc -S bonjour.c
$ cat bonjour.s
int main() {
int num = 2 + 3;
return(0);
}
$ 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
int main() {
int num = 2 + 3;
return(0);
}
$ gcc -O2 -S add.c
add.s
main:
.LFB0:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
$ gcc bonjour.c
$ file a.out
a.out: ELF 64-bit LSB shared object, x86-64
$ gcc -march=i686 -m32 bonjour.c
$ gcc -S -march=i686 -m32 bonjour.c
$ file ./a.out
./a.out: ELF 32-bit LSB shared object, Intel 80386
$ gcc -c client.c
$ gcc -c color.c
$ gcc -o color color.o client.o
$ 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
client: client.c color.c
<TAB>gcc -o client client.c color.c
$ make
gcc -o client client.c color.c
client: client.o color.o
gcc -o client client.o color.o
client.o: client.c client.h
gcc -c client.c
color.o: color.c color.h
gcc -c color.c
CC ?= gcc
CFLAGS ?= -Wall -Wextra -g
COBJS ?= client.o color.o
SOBJS ?= server.o color.o
.SUFFIXES: .c .o
SERVER = server
CLIENT = client
all: $(SERVER) $(CLIENT)
$(SERVER): $(SOBJS)
$(CC) -o $(SERVER) $(SOBJS)
$(CLIENT): $(COBJS)
$(CC) -o $(CLIENT) $(COBJS)
.c.o:
$(CC) -c $*.c
$ vim server.c
$ vim client.c
$ vim color.c
$ make
$ vim color.c
$ make