Pourquoi est le premier argument de getline un pointeur de pointeur de char**” au lieu de “char*”?
- Je utiliser getline
fonction pour lire une ligne de STDIN
.
Le prototype de getline
est:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
Je l'utiliser comme un programme de test qui obtenir de http://www.crasseux.com/books/ctutorial/getline.html#getline
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int atgc, char *argv[])
{
int bytes_read = 1;
int nbytes = 10;
char *my_string;
my_string = (char *)malloc(nbytes+1);
puts("Please enter a line of text");
bytes_read = getline(&my_string, &nbytes, stdin);
if (bytes_read == -1)
{
puts ("ERROR!");
}
else
{
puts ("You typed:");
puts (my_string);
}
return 0;
}
Cela fonctionne bien.
Mes doutes sont?
-
Pourquoi utiliser
char **lineptr
au lieuchar *lineptr
en tant que paramètre de la fonctiongetline
? -
Pourquoi c'est mal quand j'utilise le code suivant:
char **my_string; bytes_read = getline(my_string, &nbytes, stdin);
-
Je suis confus avec
*
et&
.
Ici une partie de avertissements:
testGetline.c: In function ‘main’:
testGetline.c:34: warning: pointer targets in passing argument 2 of
‘getline’ differ in signedness
/usr/include/stdio.h:671:
note: expected ‘size_t * __restrict__’ but argument is of type ‘int *’
testGetline.c:40: warning: passing argument 1 of ‘putchar’ makes integer
from pointer without a cast
/usr/include/stdio.h:582: note: expected ‘int’ but argument is of
type ‘char *’
J'utilise GCC version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5).
- BTW, vous faute de frappe, la déclaration de
bytes_read
. Et ce qui sur terre est "l'incertitude"? - Désolé, j'ai corrigé.
- J'utilise "l'incertitude" qui signifie "l'puzzles, de l'incompréhension des parties". Désolé.
Vous devez vous connecter pour publier un commentaire.
Imaginer le prototype pour
getline
ressemblait à ceci:Et vous l'avez appelé comme ceci:
Avant d'appeler
getline
,buffer
est nulle:Quand
getline
est appelé,line
obtient une copie debuffer
parce que les arguments d'une fonction sont passés par valeur en C. à l'Intérieur degetline
, nous n'avons plus accès àbuffer
:getline
alloue de la mémoire avecmalloc
et pointsline
au début du bloc:Après
getline
retourne, nous n'avons plus accès àline
:Et nous sommes de retour là où nous avons commencé. Nous ne pouvons pas re-point
buffer
à la nouvelle-mémoire allouée à l'intérieur degetline
parce que nous n'avons qu'une copie debuffer
.Le prototype pour
getline
est en réalité:Et vous l'appeler comme ceci:
&foo
retourne un pointeur versfoo
, nous avons donc:Quand
getline
est appelé,lineptr
obtient une copie de&buffer
parce que C est en appel par valeur.lineptr
points à la même place que&buffer
:getline
alloue de la mémoire avecmalloc
et les points de la pointee delineptr
(c'est à dire la choselineptr
points) au début du bloc:Après
getline
retourne, nous n'avons plus accès àlineptr
, mais on peut toujours accéder au nouveau-mémoire allouée parbuffer
:Parce que
getline()
va allouer de la mémoire pour vous si vous passez un pointeur vers un pointeur null.De la page de man:
Vous devez passer dans un
char**
(c'est à dire un pointeur vers un pointeur vers un char), de sorte que la fonction est en mesure de mettre à jour la valeur de lachar*
qu'il indique.Vous pourriez avoir utilisé:
N'oubliez pas que si vous faites cela, vous êtes responsable de la
free()
-ing la mémoire allouée pargetline()
.getline(&my_string, &nbytes, stdin);
est incorrecte,int nbytes
est de type incorrect.Therefromhere réponse est bonne pour votre première question. Vérifiez la page de manuel dans l'avenir, il a les informations dont vous avez besoin.
Votre deuxième ligne ne fonctionne pas parce que le pointeur n'est pas initialisé. Si vous voulez le faire, vous devez écrire:
Essentiellement, lorsque vous êtes la création de une variable, * les moyens d'un pointeur, lorsque vous êtes référencement une variable, cela signifie déréférencer le pointeur (obtenir ce que le pointeur pointe vers). & signifie "Le pointeur qui pointe vers ce".
Avoir un code existant à mon nouveau concert, je pense que je devrais offrir une mise en garde contre l'appel de calloc et retournant un pointeur de pointeur. Cela devrait fonctionner, mais il ignore comment getline() fonctionne. Le & opérateur indique clairement que vous êtes de passage à l'adresse du pointeur de retour de malloc(), calloc(). Bien que techniquement identiques, déclarant foo comme char **foo, au lieu de char *toto, et puis l'appel de getline(foo,,) au lieu de getline(&foo,,) obscurcit ce point important.
getline() permet d'allouer du stockage et de passer getline() un pointeur vers le pointeur de la fonction malloc(), calloc() retourne à vous, que vous attribuez à votre pointeur. Par exemple:
char *foo = calloc(size_t arbitrarily_large, 1);
il est possible de passer &foo=NULL, auquel cas, il va faire une aveugle d'allocation de stockage pour vous discrètement l'appel de malloc(), calloc(), caché de la vue.
char *toto, **p_foo=&foo serait aussi travailler. Puis appeler foo = calloc(size_t, size_t), puis d'appeler getline(p_foo,,); je pense que getline(&foo,,), c'est mieux.
Aveugle allocations sont très mauvaises, et une invitation à la problématique des fuites de mémoire, parce que nulle part dans VOTRE code faites-vous appel à malloc(), calloc(), de sorte que vous, ou quelqu'un qui, plus tard, est chargé de l'entretien de votre code, de ne pas savoir à free() le pointeur de stockage, parce que certains de la fonction vous avez appelé alloue de la mémoire, sans le savoir (sauf pour la lecture de la description de la fonction et de la compréhension qu'il fait à l'aveugle de répartition).
Depuis getline() va realloc() la mémoire de votre appel à malloc(), calloc() fournie si elle est trop petite, il est préférable de répartir votre meilleure estimation, à la de stockage nécessaire, un appel à la fonction calloc(), et de le rendre clair ce que le pointeur char *toto est en train de faire. Je ne crois pas que getline() ne fait rien avec rangement, tant que vous avez calloc()d est suffisante.
Gardez à l'esprit que la valeur de votre pointeur peut être changée si getline() doit appeler le realloc() pour allouer plus d'espace de stockage, le stockage SERA probablement à partir d'un autre emplacement sur le tas. C'est à dire: si vous avez pass &toto et toto adresse de l'est 12345, et getline() realloc()s de stockage, et dans un nouvel emplacement, foo nouvelle adresse peut être 45678.
Ce n'est pas un arguement à l'encontre de votre propre appel à calloc(), parce que si vous définissez foo=NULL, vous êtes garanti que getline() va appeler le realloc().
En résumé, faire un appel à calloc() avec un peu de bonne conjecture quant à la taille, à laquelle il sera évident pour quiconque lecture de votre code, que la mémoire EST ALLOUÉE qui doit être libre()d, peu importe ce que getline() qui fonctionne ou ne pas le faire plus tard.
(size_t *)&len
est tout simplement faux. Utiliser le bon typesize_t
pour la déclaration delen
.int nbytes = 10; ... bytes_read = getline(&my_string, &nbytes, stdin);
Unint
etsize_t
ne sont pas nécessairement de la même taille ni le même alignement exigence. Qui mène à(size_t *)&len
comme un comportement indéfini. Exempleint
est de 4 octets etsize_t
est 8. À l'aide de(size_t *)&len
auragetline()
écrit à la mémoire, elle n'est pas propre.char **lineptr
est utilisé parce quegetline()
demande l'adresse du pointeur qui pointe à l'endroit où la chaîne sera stocké.Vous utilisez
char *lineptr
sigetline()
prévu le pointeur lui-même(qui ne fonctionne pas, voir pourquoi dans ThisSuitIsBlackNot réponse)La suivante devrait fonctionner:
La
*
a un double sens.Lorsqu'utilisé dans une déclaration d'un pointeur, par exemple, un pointeur vers char, il signifie que vous voulez un pointeur vers char au lieu d'un char.
Lorsque utilisé ailleurs, il obtient la variable à laquelle un pointeur de points.
La
&
obtient l'adresse en mémoire d'une variable(ce que les pointeurs ont été créés pour tenir comme une valeur)&*ptr_to_letter
moyens de me donner l'adresse(&
) de la variable à laquelleptr_to_letter
points(*
), et est le même que l'écritureptr_to_letter
Vous pouvez penser
*
comme le contraire de&
, et qu'ils annulent les unes les autres.