Programmation en C : pointeurs

Je me pose une question concernant les pointeurs en C, quelle est la différence entre ces deux codes ? Lequel est à privilégier / éviter ?

Version 1

char a[] = "hello world!\n"; char *c = malloc(sizeof(a)); memcpy(c, a, sizeof(a));

Version 2

char a[] = "hello world!\n"; char *c = a;

chgi.developpez.com/pointeur/

Dans le deuxième cas, un tableau, deux pointeurs, dans le premier cas deux tableaux différents ayant le même contenu au départ.

Effectivement, puisque memcpy fait une copie, j’aurai du tilter :slightly_smiling:

Merci.

[quote=“uobes”]Je me pose une question concernant les pointeurs en C, quelle est la différence entre ces deux codes ? Lequel est à privilégier / éviter ?

Version 1

char a[] = "hello world!\n"; char *c = malloc(sizeof(a)); memcpy(c, a, sizeof(a));

Version 2

char a[] = "hello world!\n"; char *c = a;[/quote]

Premier cas, a est alloué a la compilation, et a une taille fixe. c est alloué par la libc de manière dynamique, et a est copié dans c.

Dans le 2° cas, tu fais pointer c sur le début de a, donc a et c représentent exactement la meme chose.

Quizz: Que fais ce code ?

#include <stdlib.h>
#include <stdio.h>
#define C char
#define A for(argc=1
#define B argc

int main(int argc, char **argv){C c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; A;ca!=-1;ca+=(c[B]),B++) putchar(ca);return 0;}

:slightly_smiling:

Il imprime COBOL mais c’est tordu
Le code développé (j’ignorais qu’on pouvait faire de telles cochonneries avec le préprocesseur) est

[code]#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv){
char c[]={67,12,-13,13,-3,-66,-11,1};
char ca=*c;
for(argc=1;ca!=-1;ca+=(c[argc]),argc++)
putchar(ca);
return 0;}

	/*

67='C’
67+12='O’
67+12-13='B’
67+12-13+13='O’
67+12-13+13-3='L’
67+12-13+13-3-66=Linefeed
67+12-13+13-3-66-11=-1=stop
*/[/code]

ca vaut toujours c[0]

[edit: poufff, particulièrement tordu celui là]

[code]#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv){
char c[]={67,12,-13,13,-3,-66,-11,1};
char ca=c[0];
int i;

for(i=1 ; ca!=-1 ; i++) {
    ca+=c[i];
    putchar(ca);
}
return 0;

}
[/code]

Ben sa écrit un bidule, avec des valeur ASCII relatives par rapport à celle du caractère précédent.

EDIT: arf, pas asser rapide…

héhéhé, oué le préprocesseur permet des trucs sympa :slightly_smiling:

Mais non, super simple à vérifier (si quelqu’un sait comment se passer du a.out pour faire de la compil c “à la volée”, ça m’interesse):

[code]matt@emeraude ~ $ cc -x c - <<EOF && ./a.out && rm a.out

#include <stdlib.h>
#include <stdio.h>
#define C char
#define A for(argc=1
#define B argc

int main(int argc, char **argv){C c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; A;ca!=-1;ca+=(c[B]),B++) putchar(ca);return 0;}
EOF
COBOL[/code]et pour la version préprocessée:[code]matt@emeraude ~ $ cpp <<EOF
#include <stdlib.h>
#include <stdio.h>
#define C char
#define A for(argc=1
#define B argc

int main(int argc, char **argv){C c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; A;ca!=-1;ca+=(c[B]),B++) putchar(ca);return 0;}
EOF [/code]un peu long pour être mis ici, mais en version courte on retrouve bien:

[code]matt@emeraude ~ $ cpp <<EOF

#define C char
#define A for(argc=1
#define B argc

int main(int argc, char **argv){C c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; A;ca!=-1;ca+=(c[B]),B++) putchar(ca);return 0;}
EOF

1 “”

1 “”

1 “”

1 “”

int main(int argc, char **argv){char c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; for(argc=1;ca!=-1;ca+=(c[argc]),argc++) putchar(ca);return 0;}
[/code]

[quote=“MattOTop”]
Mais non, super simple à vérifier (si quelqu’un sait comment se passer du a.out pour faire de la compil c “à la volée”, ça m’interesse)[/quote]

Tu triches :slightly_smiling: . Pour ton pbm, tu dois pouvoir rediriger vers la sortie en donnant /dev/stdout comme argument à -o, un truc genre

$ cat <<EOF | gcc -o /dev/stdout | /lib/ld-linux.so.2

EOF
mais je n’ai essayé

c’est pas encore ça:

[code]matt@emeraude ~ $ cc -x c - -o /dev/stdout <<EOF | file -

#include <stdlib.h>
#include <stdio.h>
#define C char
#define A for(argc=1
#define B argc

int main(int argc, char **argv){C c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; A;ca!=-1;ca+=(c[B]),B++) putchar(ca);return 0;}
EOF
/dev/stdin: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
matt@emeraude ~ $ cc -x c - -o /dev/stdout <<EOF | /lib/ld-linux.so.2 -
#include <stdlib.h>
#include <stdio.h>
#define C char
#define A for(argc=1
#define B argc

int main(int argc, char **argv){C c[]={67,12,-13,13,-3,-66,-11,1};char ca=*c; A;ca!=-1;ca+=(c[B]),B++) putchar(ca);return 0;}
EOF
-: error while loading shared libraries: -: cannot open shared object file
[/code]

p’tet que :

cat <<EOF | gcc -o /dev/stdout | /lib/ld-linux.so.2 /dev/stdin ?
Ben non :

un petit strace de /lib/ld-linux.so.2 :

open("/dev/stdin", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\2\0\3\0\1\0\0\0\260\202"..., 512) = 512 fstat64(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 mmap2(0x8048000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = -1 ENODEV (No such device)
Je crois pas que l’on peut projeter en mémoire un pipe, non?

Edit: Trouvé ! : alohakun.blog7.fc2.com/blog-entry-462.html
(Vous aussi vous avez du mal a lire ? :smiley: )

Par contre je n’ai encore jamais vu cette syntaxe là…

nan, c’est pas trés loin je crois: le compilo me semble sortir un executable aout, alors que ld-linux.so.2 attend un elf. Je ne trouve pas de ld.so (qui est censé loader les aout en lieu et place de ld-linuc.so.2) et coté compilo, je suis étonné qu’il me sorte du aout, et si je lui passe un -melf, il râle:

/lib/ld-linux.so.2 =(cat <<EOF | gcc -o /dev/stdout )ne fonctionne pas…

Ben pourtant :

$ file a.out a.out: [b]ELF[/b] 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.4.1, dynamically linked (uses shared libs), for GNU/Linux 2.4.1, not stripped

oui. tu as raison, j’avais mal lu.
Il n’empêche que chez moi, la syntaxe fournie par le bolg que tu indique ne passe pas en bash.

Effectivement, c’est une syntaxe propre à zsh…

$ echo =(echo) /tmp/zshYKpLlm

C’est simplement le passage par un fichier temporaire…
Mais le billet du blog ne propose pas d’autre solution apparament…