int main(int argc, char *argv[])
{
char string[100];
string = *argv[1];
}
Why doesn't this work? Do I actually need to use loops to iterate through each element and do everything the long way?
4 Réponses :
Pourquoi cela ne fonctionne-t-il pas?
Parce que c'est simplement ainsi que cela fonctionne en C. Essayer avec
string = argv [1](sans *) serait une meilleure estimation, mais vous ne pouvez pas copier des tableaux avec des affectations simples.Dois-je réellement utiliser des boucles pour parcourir chaque élément et faire tout le long du chemin?
À moins que vous ne soyez prêt à utiliser des fonctions telles que
strcpy,strncpyoustrdupou quelque chose de similaire, alors oui. Utiliserstrncpydans votre code ressemblerait à ceci:size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0) { while (--n != 0) { if ((*d++ = *s++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ }La dernière ligne est de s'assurer que
stringest terminé . Clunky? Oui c'est le cas. Il y a de meilleures fonctions dans certains compilateurs commestrlcpy, qui est disponible sur les systèmes POSIX, mais cela ne fait pas partie du standard C. Si vous utilisezstrlcpyau lieu destrncpy, vous pouvez ignorer la dernière ligne.Si vous prévoyez de faire beaucoup de copie de chaînes et de ne pas le faire. t avoir un compilateur prenant en charge
strlcpy, il peut être judicieux d'écrire votre propre implémentation (bonne pratique) ou simplement de copier une implémentation existante. En voici un que j'ai trouvé:char string[100]; strncpy(string, argv[1], sizeof(string)); string[sizeof(string) - 1] = 0;Source: https://android.googlesource.com/platform/system/core.git/+/brillo-m7-dev/libcutils/strlcpy.c a>
strncpy écrira toujours n octets, en complétant avec des zéros si la chaîne source est plus courte. strlcpy ou une implémentation personnalisée de celui-ci, qui ne fait pas le remplissage, peut être préférable.
Dans la fonction principale en C, argv est un vecteur de chaînes qui sont elles-mêmes des tableaux de caractères. Donc argv est un pointeur vers un pointeur (comme ** char ).
Votre code attribue une référence à un pointeur (vers le premier argument).
char * string = argv [1]; le ferait. Pour copier la chaîne entière (tableau de caractères), utilisez strcpy . Pour copier tous les arguments, utilisez memcpy .
Mais en général, dans un programme C, vous ne copiez pas les arguments, utilisez simplement des références à eux.
" en C argv est un vecteur de chaînes ", non c'est un tableau de pointeur vers le 1er caractère d'une "chaîne" en C .
Je l'ai écrit à partir de mes connaissances pratiques, mais vous pouvez trouver exactement mes mots par exemple: gnu.org/software/libc/manual/html_node/Program-Arguments.htm l
En C, un nom de tableau n'est pas une expression de valeur L. Par conséquent, vous ne pouvez pas l'utiliser dans une instruction d'affectation. Pour faire une copie d'un tableau de caractères, vous pouvez utiliser une instruction for ou une fonction strcpy, qui est déclarée dans le fichier d'en-tête string.h.
La réponse courte est: parce que c'est le cas. En langage C, seules les structures et les unions sont copiées par valeur à une exception près:
Initialisation du tableau
foo3:
sub sp, sp, #16
push {r4, r5, r6, lr}
mov r6, #100
sub sp, sp, #104
ldr r5, .L4
add ip, sp, #116
add r4, sp, #4
stmib ip, {r0, r1, r2, r3}
mov r2, r6
mov r1, r5
mov r0, r4
bl memcpy
mov r2, r6
mov r1, r5
ldr r0, .L4+4
bl memcpy
add r1, sp, #20
mov r2, #84
add r0, sp, #136
bl memcpy
ldm r4, {r0, r1, r2, r3}
add sp, sp, #104
pop {r4, r5, r6, lr}
add sp, sp, #16
b foo4
.L4:
.word .LANCHOR0
.word b
a:
.ascii "This string literal will be copied before main star"
.ascii "ts\000"
et le code compilé:
typedef struct
{
char str[100];
}string;
string a = {.str = "This string literal will be copied before main starts"},b;
void foo3(string c)
{
string g = a;
b = a;
foo4(g);
}
Les structures et les unions sont copiées par la valeur de sorte que l'affectation copie la structure entière dans une autre.
foo:
push {r4, lr}
sub sp, sp, #320
mov ip, sp
ldr lr, .L4
ldr r4, .L4+4
ldmia lr!, {r0, r1, r2, r3}
stmia ip!, {r0, r1, r2, r3}
ldmia lr!, {r0, r1, r2, r3}
stmia ip!, {r0, r1, r2, r3}
ldmia lr!, {r0, r1, r2, r3}
stmia ip!, {r0, r1, r2, r3}
ldm lr, {r0, r1}
str r0, [ip], #4
strb r1, [ip]
add r0, sp, #208
mov r2, #110
ldr r1, .L4+8
bl memcpy
mov r1, r4
add r0, sp, #56
mov r2, #72
bl memcpy
mov r2, #80
add r1, r4, #72
add r0, sp, #128
bl memcpy
add r1, sp, #208
mov r0, sp
bl foo1
add r1, sp, #128
add r0, sp, #56
bl foo2
add sp, sp, #320
pop {r4, pc}
.L4:
.word .LC2
.word .LANCHOR0
.word .LC3
.LC2:
.ascii "This string literal will be copied! Test it yoursel"
.ascii "f\000"
.LC3:
.ascii "This string literal will be copied as well But beca"
.ascii "use it is much loger memcpy will be used! Test it y"
.ascii "ourself\000"
et le code :
void foo(void)
{
char x[] = "This string literal will be copied! Test it yourself";
char z[] = "This string literal will be copied as well But because it is much loger memcpy will be used! Test it yourself";
float y[] = {1.0,2.0, 3,0,4.0,5.0,1.0,2.0, 3,0,4.0,5.0,1.0,2.0, 3,0,4.0,5.0};
long long w[] = {1,2,3,4,5,6,7,8,9,0};
foo1(x,z); // this functions are only to prevent the variable removal
foo2(y,w);
}
vous pouvez jouer avec vous-même:
Si vous recherchez la commodité, C n'est pas le langage à utiliser.
Remarque: les types sont différents. Mais même
string = argv [1];est interdit.Cette affectation attribuera (probablement) le premier caractère de
argv [1]au premier caractère destring.Le langage ne le permet tout simplement pas, donc oui, vous devez utiliser des boucles (directement ou indirectement via des fonctions standard comme
strcpy). Ou, étant donné que les chaînes dansargvseront valides et dans la portée pour la durée du programme, utilisez simplement des pointeurs à la place.