2010-02-25 7 views
7

Je lisais the following text from Stanford's Programming Paradigms class, et j'ai remarqué que lorsque l'auteur utilise la classe de chaîne, le constructeur fait un appel de fonction qui ressemble à ceci:élémentaire C++ type Confusion

string::string(const char* str) { 
    initializeFrom(str, str + strlen(str)); 
} 

Si la fonction initializeFrom prend deux char * arguments, comment le deuxième argument peut-il passer un (char * + int) à un char * et le faire fonctionner correctement? Comment le système de type interprète-t-il cette déclaration?

Merci d'avance.

+0

'strlen()' renvoie en réalité un 'size_t', pas un' int'. L'une des différences importantes est que size_t est un type non signé, c'est-à-dire qu'il ne peut contenir que des nombres positifs. Cela a du sens - les longueurs de chaîne peuvent être de 0, 1 ou 30000 caractères, mais jamais -7. – MSalters

Répondre

11

C'est ce qu'on appelle l'arithmétique du pointeur. Un char * + int résulte en un char * qui est des caractères int plus hauts en mémoire.

+1

+1 pour le nommer correctement. :) –

+0

Si le 'int' est -ve il pourrait aussi être plus bas en mémoire; il devrait donc être un '' non signé '' pour que le résultat soit * toujours * plus haut dans la mémoire. [Désolé s'il s'agit de nitpicking;] – legends2k

+0

@ legends2k Cela est vrai, bien que strlen() ne renvoie jamais une valeur négative, donc le code particulier analysé ici fera que le second argument sera toujours supérieur ou égal au premier. – ChrisH

0

Le premier argument pointe vers le début du tableau char et le second pointe le caractère NULL à la fin du tableau char.

const char *str = "abc"; 
char *start = str; // start now points to the first char. 
char *end = str + strlen(str); // end now points to the null char at the end. 

Vous pouvez confirmer par impression:

printf("%c %d",*start,*end); // will output: a 0 
0

comment se fait le deuxième argument peut passer un (char * + int)

Il est encore passer un char * pointage à strlen(str) après l'emplacement initialement pointé. Rappelez-vous qu'un pointeur est juste une variable qui contient une adresse de mémoire.

2

Vous pouvez donc ajouter des valeurs à une adresse mémoire. Une adresse mémoire est un nombre.

Lorsque vous ajoutez 1 à un pointeur d'un certain type, il ajoutera réellement 1 * sizeof (type). Lorsque vous ajoutez une valeur N, elle ajoute réellement N * sizeof (type).

Prenons l'exemple suivant:

int x[5] = {0,1,2,3,4}; 
int *p = &(x[0]);//point to the first element 
p = p + 1;//p now points to the second element. 
4

opérateurs d'additifs binaires + et - peuvent être utilisées quand un argument est un pointeur sur tout type complète (par exemple, T* p) et l'autre argument est un nombre entier (par exemple, i). Ils implémentent ce que l'on appelle l'arithmétique du pointeur .

Le compilateur suppose que le pointeur pointe vers un élément d'un tableau (par exemple, T array[N]). L'opération produit un pointeur vers un autre élément du tableau, qui est i éléments éloignés de l'élément d'origine. Il est possible de "déplacer" le pointeur dans l'une ou l'autre direction, c'est-à-dire vers le début du tableau ou vers la fin du tableau. Par exemple, si p indique array[3], alors p + 4 pointera sur array[7].

L'opération est valable uniquement lorsque les points de résultat à un élément existant du tableau ou un après le dernier élément du tableau, à savoir étant donné le tableau T array[N], il est possible de créer des pointeurs vers des éléments de array[0] à l'élément imaginaire array[N]. Toute tentative de croiser ces limites à l'aide de l'arithmétique du pointeur entraîne un comportement indéfini.

Le type T doit être complet, ce qui signifie que l'arithmétique de pointeur ne peut pas être utilisé avec des pointeurs void *, pour un exemple, même si certains compilateurs permettent cela comme une extension (traitement void * pointeurs comme équivalent à char * pointeurs).

En plus des opérateurs d'additifs binaires, le calcul de pointeur comprend également préfixe et suffixe unaires ++ et -- opérateurs (appliqué à des pointeurs), ainsi que des opérateurs d'affectation de composé += et -= (avec des pointeurs sur leur côté gauche et entiers sur le côté droit).

Dans votre cas, l'expression str + strlen(str) produira un pointeur de type char * qui pointe vers la terminaison \0 caractère de la chaîne str.

0

Je pense que cela peut être sur-répondu.

Dans:

initializeFrom(str, str + strlen(str)); 

str est un pointeur vers le début de la chaîne.

(str + strlen(str)) est un pointeur vers la fin de la chaîne.

Gardez à l'esprit que str (un pointeur de caractère) est juste un entier ((int), (long), (long long) en fonction de l'architecture) qui identifie un emplacement en mémoire.

+0

Un pointeur n'est pas (toujours) un entier. Sur x86-16 par exemple, c'est une paire d'entiers. – MSalters