Pages : 1
#1 Le 23/11/2008, à 17:56
- Bzh
Petites questions de C
Bonjour,
J'ai un petit doute sur l'utilisation des pointeurs en C.
1ère question :
#include <stdio.h>
void main( void )
{
char chaine[] = "chaine de caractères\0";
char* pointeur;
pointeur = &chaine[3];
printf( "%s", pointeur );
}
Est-ce bien correcte ?
2ème question :
#include <stdio.h>
void main( void )
{
char* chaine;
char* pointeur;
chaine = malloc( 20 * sizeof( char ) );
strcpy( chaine, "chaine de caractères\0" );
pointeur = chaine + 3;
printf( "%s", pointeur );
free( chaine );
}
De même, est-ce correcte ?
Merci
Hors ligne
#2 Le 23/11/2008, à 18:20
- nicolas.sitbon
Re : Petites questions de C
Bonjour,
J'ai un petit doute sur l'utilisation des pointeurs en C.
1ère question :
#include <stdio.h> void main( void ) { char chaine[] = "chaine de caractères\0"; char* pointeur; pointeur = &chaine[3]; printf( "%s", pointeur ); }
Est-ce bien correcte ?
2ème question :
#include <stdio.h> void main( void ) { char* chaine; char* pointeur; chaine = malloc( 20 * sizeof( char ) ); strcpy( chaine, "chaine de caractères\0" ); pointeur = chaine + 3; printf( "%s", pointeur ); free( chaine ); }
De même, est-ce correcte ?
Merci
l'utilisation des pointeurs est correcte mais,
- la déclaration de main est incorrect
- le \0 est implicite dans une chaine litérale
- pointeur = &chaine[3]; peut être simplifié en pointeur = chaine + 3;
- sizeof (char) vaut par définition toujours 1 donc inutile
- strcpy est à proscrire
- tu dois tester le retour de malloc
- le prototype de malloc est défini dans stdlib.h (oubli == comportement indéterminé)
- strcpy est défni dans string.h (même remarque que précédemment)
Dernière modification par nicolas.sitbon (Le 23/11/2008, à 18:21)
Hors ligne
#3 Le 23/11/2008, à 18:23
- Prokopy
Re : Petites questions de C
Regarde ici :
http://www.siteduzero.com/tutoriel-3-14 … -en-c.html
Ubuntu 8.10 , 1 Go de Ram , 160 Go de Disque Dur , Pentium Intel Dual - core 2.00 Ghz chacun.
Hors ligne
#4 Le 23/11/2008, à 18:36
- Bzh
Re : Petites questions de C
pointeur = &chaine[3]; peut être simplifié en pointeur = chaine + 3;
Là je ne suis pas...
Dans le deuxième cas, oui, je suis d'accord. Mais dans le premier cas, chaine est déclarée comme char et non comme char*...
Hors ligne
#5 Le 23/11/2008, à 18:41
- nicolas.sitbon
Re : Petites questions de C
pointeur = &chaine[3]; peut être simplifié en pointeur = chaine + 3;
Là je ne suis pas...
Mais dans le premier cas, chaine est déclarée comme char et non comme char*...
Non dans le premier cas chaine est déclaré ainsi:
char chaine[] = "chaine de caractères\0";
chaine a donc le type (char []), un tableau de T étant implicitement converti dans la plupart (mais pas tous) des contextes en un pointeur sur T, pointant sur le premier élément du tableau.
Hors ligne
#6 Le 23/11/2008, à 19:23
- Plokta
Re : Petites questions de C
chaine = malloc( 20 * sizeof( char ) );
strcpy( chaine, "chaine de caractères\0" );
Pas bon, ton allocation fait 20 octets et ta chaine 20+1 caractères
De plus le caractère \0 ne sert à rien, le langage C le rajoute automatiquement à la fin de toute chaine de caractères
Dernière modification par Plokta (Le 23/11/2008, à 19:25)
Hervé ADAM
http://www.tvpaint.fr
Hors ligne
#7 Le 23/11/2008, à 21:30
- nicolas66
Re : Petites questions de C
sizeof (char) vaut par définition toujours 1 donc inutile
En pratique, oui. Néanmoins, la norme C99 stipule qu'un `char' doit faire au minimum 8 bits. Rien ne m'empêche de créer des `char' de 2 octets ...
"The computer was born to solve problems that did not exist before." (B. Gates)
Hors ligne
#8 Le 23/11/2008, à 21:37
- nicolas.sitbon
Re : Petites questions de C
Relis la norme, d'après celle ci, un char fait toujours un byte, par contre le nombre de bits qu'il y a dans ce byte dépend de l'implémentation avec comme tu l'as dis un minimum de 8 bits mais ça peut être 9 ou même 36 comme j'ai pu le voir sur certaine architecture. sizeof renvoi la taille en byte, un char fait toujours un byte, donc sizeof (char) renverra toujours un. Pour rappel, octet n'est pas la traduction du mot byte. byte se traduit par multiplet.
3.6
1 byte
addressable unit of data storage large enough to hold any member of the basic character
set of the execution environment
NOTE 1 It is possible to express the address of each individual byte of an object uniquely.
2
NOTE 2 A byte is composed of a contiguous sequence of bits, the number of which is implementation-
3
defined. The least significant bit is called the low-order bit; the most significant bit is called the high-order
bit.
5.2.4.2.1 Sizes of integer types <limits.h>
1 The values given below shall be replaced by constant expressions suitable for use in #if
preprocessing directives. Moreover, except for CHAR_BIT and MB_LEN_MAX, the
following shall be replaced by expressions that have the same type as would an
expression that is an object of the corresponding type converted according to the integer
promotions. Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.
— number of bits for smallest object that is not a bit-field (byte)
CHAR_BIT 8
3.7.1
1 character
single-byte character
〈C〉 bit representation that fits in a byte
6.5.3.4 The sizeof operator
Constraints
1 The sizeof operator shall not be applied to an expression that has function type or an
incomplete type, to the parenthesized name of such a type, or to an expression that
designates a bit-field member.
Semantics
2 The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. The result is an integer. If the type of the operand is a variable length array
type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.
3 When applied to an operand that has type char, unsigned char, or signed char,
(or a qualified version thereof) the result is 1.
Dernière modification par nicolas.sitbon (Le 23/11/2008, à 21:49)
Hors ligne
#9 Le 24/11/2008, à 11:23
- jofab
Re : Petites questions de C
- sizeof (char) vaut par définition toujours 1 donc inutile
Equivalent du point de vue de la norme ne veut pas forcement dire inutile
- strcpy est à proscrire
Tu peux utiliser strncpy à la place qui permet d'eviter un debordement de tableau. Il faut quand meme etre vigilant car le \0 terminal n'est pas ajouté lorsque la source est plus grande que la destination... Du coup c'est un peu mieux mais pas bcp...
Hors ligne
#10 Le 24/11/2008, à 13:55
- nicolas.sitbon
Re : Petites questions de C
nicolas.sitbon a écrit :- sizeof (char) vaut par définition toujours 1 donc inutile
Equivalent du point de vue de la norme ne veut pas forcement dire inutile
dans ce cas précis ça l'est et ça empêche même la généricité (pour ceux qui la pratique).
nicolas.sitbon a écrit :- strcpy est à proscrire
Tu peux utiliser strncpy à la place qui permet d'eviter un debordement de tableau. Il faut quand meme etre vigilant car le \0 terminal n'est pas ajouté lorsque la source est plus grande que la destination... Du coup c'est un peu mieux mais pas bcp...
préféré strlcpy() si dispo sur votre système, ou bien plutôt strncat() à strncpy().
Hors ligne
#11 Le 24/11/2008, à 14:16
- Bzh
Re : Petites questions de C
J'essaye de chercher des infos pour strcpy();
Il s'agit de se proteger des buffer overflow.
Mais en quoi strncat() est préférable à strncpy() ?
Hors ligne
#12 Le 24/11/2008, à 14:26
- nicolas.sitbon
Re : Petites questions de C
un exemple vaut mieux qu'un long discours:
#include <stdio.h>
#include <string.h>
int main (void)
{
char const * const chaine_source = "une chaine trop longue";
char chaine_strncpy[15];
char chaine_strncat[15];
strncpy (chaine_strncpy, chaine_source, sizeof chaine_strncpy - 1); /* appel identique à strncat */
chaine_strncpy[sizeof chaine_strncpy - 1] = '\0'; /* nécessite de calculer l'offset */
chaine_strncat[0] = '\0'; /* pas d'offset à calculer */
strncat (chaine_strncat, chaine_source, sizeof chaine_strncpy - 1); /* appel identique à strncpy */
puts (chaine_strncpy);
puts (chaine_strncat);
return 0;
}
Hors ligne
#13 Le 25/11/2008, à 16:27
- philou8237
Re : Petites questions de C
mmm... je suis pas sur que ce soit si intéressant que ça. Tu fais un accès mémoire quand meme, et je pense (pas sur hein !) que deux "sizeof chaine_strncpy - 1" successifs est optimisé par le compilateur, je pense pas qu'il fasse le calcul deux fois.
Après faut voir comment gcc choisit d'optimiser le code (et les options d'optimisation de l'appel à gcc).
Hors ligne
#14 Le 25/11/2008, à 16:39
- nicolas.sitbon
Re : Petites questions de C
Si tu veux pinailler sur les optimisations, il suffit de dire que l'offset dans un tableau à un impact.
Hors ligne
#15 Le 25/11/2008, à 16:53
- philou8237
Re : Petites questions de C
boh c'est pas pour pinailler, juste pour donner mon avis... maintenant si on va par là nos deux solutions sont des pinaillements
Hors ligne
#16 Le 25/11/2008, à 16:55
- nicolas.sitbon
Re : Petites questions de C
Ok alors sans parler de performance, pour des raisons de lisibilité, je préfère la méthode strncat().
Hors ligne
#17 Le 25/11/2008, à 19:24
- robrob
Re : Petites questions de C
je pense (pas sur hein !) que deux "sizeof chaine_strncpy - 1" successifs est optimisé par le compilateur, je pense pas qu'il fasse le calcul deux fois.
Le compilateur va bien faire le calcul 2 fois. Par contre, le programme lui ne fera pas
Hors ligne
#18 Le 25/11/2008, à 20:07
- nicolas.sitbon
Re : Petites questions de C
philou8237 a écrit :je pense (pas sur hein !) que deux "sizeof chaine_strncpy - 1" successifs est optimisé par le compilateur, je pense pas qu'il fasse le calcul deux fois.
Le compilateur va bien faire le calcul 2 fois. Par contre, le programme lui ne fera pas
Dans ce cas, il ne le fera pas deux fois, mais si au lieu d'allouer un tableau statique, je fais un tableau dynamique, dans ce cas, avec ma solution, il n'y a un calcul un offset et moins de code, en revanche avec strcnpy il y a 2 calcul, 2 offset et plus de code.
Hors ligne
#19 Le 25/11/2008, à 20:31
- robrob
Re : Petites questions de C
Je ne suis pas sur de te suivre.
Pour ma part je disais juste que l'expression "sizeof chaine_strncpy - 1" était évaluée à la compilation et non à l'exécution (si quelqu'un en doute, qu'il regarde le code assembleur généré par gcc, même sans optimisation).
Hors ligne
#20 Le 25/11/2008, à 20:55
- nicolas.sitbon
Re : Petites questions de C
Oui je suis d'accord avec toi, et je dis que cela se produit uniquement car la taille est connu à la compilation. Mais dans le cas d'une allocation dynamique, il en va autrement.
Hors ligne
Pages : 1