There is a little confusion among the operators here. But first, I need to talk about what a variable is.
According to the author of the book Programming Lingaugens Concepts Robert Sebesta, a variable is a memory region that has type and name. Simple as that.
So the dereferencing operator &
is only applicable to variables. The result of this is not the address of the pointer, but the address (a number that points to the memory region) of the variable. In this case, &ponteiro
is the address where the ponteiro
variable is.
The referencing operator *
meanwhile applies to values. This operator will retrieve what it has in the memory address of the variable. So, in the event that there is a variable ponteiro
that points to the first house of the {42,2,10}
vector, *ponteiro
would return 42
.
Having said that, I can now stay with your question:
I would like someone to explain the use of the medium, only the "pointer" without the '*' and '&'; '
This can be more formally understood as:
I would like someone to explain to me the use of references, other than using the &
or referencing *
You usually need this when you're using shared structures. In case, the structure exists and you only have the reference to it. You can get this reference in two ways:
If it is a variable and you use &
if it is a dynamically allocated memory region
In general, you only have a difference between these two forms in the creation (said above) and the time to undo the data, in which dynamic memory needs an explicit free
to release the memory back. But you do not have to worry further, the general manipulation of the data is the same regardless of the source of the reference.
So let's say you have a tree used to store words. Let's say it is a binary tree, where each point in the tree has a parent point and up to two child points (creatively called esquerdo
and direito
). The structure of this tree is something like this:
struct arvore {
char *conteudo;
struct arvore *esquerdo;
struct arvore *direito;
};
Adding a word to the tree will make a call like this:
struct arvore* inserir_palavra(struct arvore *raiz, char *palavra);
At some point, you will need to define whether the word goes to the node that will live in raiz->esquerdo
or raiz->direito
. If it is a search tree, it is a lexicographic order. So you'll need to do something like this:
int cmp_palavra = strcmp(palavra, raiz->conteudo);
if (cmp_palavra == 0) {
// a palavra já existe, pode desencanar
return raiz;
} else if (cmp_palavra < 0) {
// palavra vem antes, portanto a esquerda
// se não tiver nada a esquerda, vou inserir o novo ponto na esquerda
if (raiz->esquerdo == NULL) {
struct arvore* nodo_palavra = cria_nodo(palavra);
raiz->esquerdo = nodo_palavra;
return nodo_palavra;
} else {
// bem, não está no ponto atual e o ponto de destino está ocupado, então vou descer nesse destino
return inserir_palavra(raiz->esquerdo, palavra);
}
} else {
// não é igual nem é anterior, então é posterior, está à direita
// se não tiver nada a direita, vou inserir o novo ponto na direita
if (raiz->direito == NULL) {
struct arvore* nodo_palavra = cria_nodo(palavra);
raiz-> direito = nodo_palavra;
return nodo_palavra;
} else {
// bem, não está no ponto atual e o ponto de destino está ocupado, então vou descer nesse destino
return inserir_palavra(raiz-> direito, palavra);
}
}
Have you seen how I'm only using the pointer itself when navigating the tree? I was only interested in the reference, I did not have to navigate within the content of the structure for this.
The case here of the direito
and esquerdo
pointers illustrate what you would like to know when using a pointer without referencing and dereferencing operators.
The most complete code in the insert operation for the example above follows after this paragraph. To get rid of the tree call the liberar_arvore
function. Note that I am doing code intrinsically single thread , so do not blame me if I try to run a program with parallel operations and things start to fail.
struct arvore {
char *conteudo;
struct arvore *esquerdo;
struct arvore *direito;
};
char* copia_char_dinamico(char *original) {
char *copia = calloc(strlen(original) +1, sizeof(char));
return strcpy(copia, original);
}
struct arvore* cria_nodo(char *palavra) {
// o calloc já cria com todos os bytes zerados, não tenho então preocupação com estar esquerdo e direito para NULL
struct arvore *novo_nodo = calloc(1, sizeof(struct arvore));
novo_nodo->conteudo = copia_char_dinamico(palavra);
return novo_nodo;
}
struct arvore* inserir_palavra(struct arvore *raiz, char *palavra) {
if (raiz == NULL) {
return cria_nodo(palavra);
}
int cmp_palavra = strcmp(palavra, raiz->conteudo);
if (cmp_palavra == 0) {
// a palavra já existe, pode desencanar
return raiz;
} else if (cmp_palavra < 0) {
// palavra vem antes, portanto a esquerda
// se não tiver nada a esquerda, vou inserir o novo ponto na esquerda
if (raiz->esquerdo == NULL) {
struct arvore* nodo_palavra = cria_nodo(palavra);
raiz->esquerdo = nodo_palavra;
return nodo_palavra;
} else {
// bem, não está no ponto atual e o ponto de destino está ocupado, então vou descer nesse destino
return inserir_palavra(raiz->esquerdo, palavra);
}
} else {
// não é igual nem é anterior, então é posterior, está à direita
// se não tiver nada a direita, vou inserir o novo ponto na direita
if (raiz->direito == NULL) {
struct arvore* nodo_palavra = cria_nodo(palavra);
raiz-> direito = nodo_palavra;
return nodo_palavra;
} else {
// bem, não está no ponto atual e o ponto de destino está ocupado, então vou descer nesse destino
return inserir_palavra(raiz-> direito, palavra);
}
}
}