Doubt about pointers in C

3

So folks, I have a question here.

What does each of these statements mean?

*ponteiro = Valor do ponteiro

 ponteiro = (?)

&ponteiro = Endereço de memória do ponteiro

I would like someone to explain the use of the medium, only the "pointer" without the '*' and '&'; '

    
asked by anonymous 15.03.2018 / 01:48

3 answers

3

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);
      }
    }
    }
    
        
    15.03.2018 / 04:52
    1

    The * operator when used in the declaration of a variable indicates that that variable is a pointer:

    // Numa arquitetura 32-bit, sizeof(ptrToShort) trará como resultado 4,
    // embora o tipo short tenha tamanho 2, porque ptrToShort é um "ponteiro"
    // para uma variável do tipo short, ou seja, ele armazenará o endereço da
    // memória onde estará armazenado um valor do tipo short.
    short *ptrToShort;
    
    // Mesma coisa, sizeof(ptrToDouble) trará como resultado 4,
    // num sistema 32-bit, embora o tipo double tenha tamanho 8.
    double *ptrToDouble;
    

    The pointers point to an address in memory, where the value of some variable, for example ptrToShort == 0x053DC88C , is stored. In this case, 0x053DC88C is a valid address in memory, and should be the start address of the space allocated in memory for a variable of type short . Since short occupies 2 bytes, this short variable would be using the memory of address 0x053DC88C to 0x053DC88D ( 0x053DC88C + 1 ).

    But when the * operator is used next to a variable in a common expression, other than a variable declaration, it means that the program is accessing the value stored in the memory address where the pointer is pointing.

    And the & operator returns the address in memory of a variable, so it is used to load a value into a pointer. It is through the & operator that we get the address of a variable, so we can store it in a pointer.

    Then:

    short inteiro = 123;
    short outroInteiro = 0;
    short *ptrToShort = NULL;
    
    // A variável ptrToShort é um ponteiro para tipos short, então ela armazenará
    // um endereço da memória, que esteja armazenando um valor do tipo short.
    // O operador & retorna o endereço na memória de uma variável, então aqui
    // estamos dizendo que ptrToShort agora aponta para o endereço na memória
    // da variável inteiro.
    // Vamos supor que a variável inteiro esteja alocada no endereço 0x053DC88C
    // da memória. A expressão &inteiro irá retornar o valor 0x053DC88C, e a
    // variável ptrToShort passará a conter o valor 0x053DC88C, após a linha
    // abaixo.
    ptrToShort = &inteiro;
    
    // O operador * permite acessar o valor armazenado no endereço apontado
    // por um ponteiro, então, o comando abaixo está dizendo: "Pegue o valor
    // do tipo short, armazenado no endereço apontado por ptrToShort, e jogue
    // na variável outroInteiro". O comando abaixo é equivalente a
    // outroInteiro=inteiro, já que *ptrToShort==inteiro.
    // Após o comando abaixo outroInteiro terá o valor 123.
    outroInteiro = *ptrToShort;
    
    // O operador * permite acessar e manipular o valor armazenado no endereço
    // apontado por um ponteiro. Como o ponteiro ptrToShort aponta para o endereço
    // da variável inteiro, o comando abaixo é o mesmo que inteiro=321, logo, 
    // após o comando abaixo, a variável inteiro terá o seu valor alterado de 123
    // para 321, já que *ptrToShort==inteiro.
    *ptrToShort = 321;
    

    The third point of your question:

    &ponteiro = Endereço de memória do ponteiro
    

    This is not a valid command, because &ponteiro is a r-value , and thus can not appear on the left side of a value assignment. See more about it here:

      

    lvalue and rvalue in C language link

         

    C address of an address of a variable
    link

    And finally, answering your main question:

     ponteiro = (?)
    
      

    I would like someone to explain to me the use of the medium, only the "pointer" without the '*' and '&';

    Considering that this variable ponteiro is really a pointer, that is, it has been declared as data_type *ponteiro; , if you throw a value so directly into it, it is expected that this value is a valid address in memory , as that example of address 0x053DC88C :

     ponteiro = 0x053DC88C;
    

    If you throw some value that is not a valid address in memory, when you try to use that pointer you probably receive a memory access error, or if you play a random value that coincidentally is a valid address in memory, your pointer will be pointing to a random address in memory that may be storing any information.

        
    15.03.2018 / 06:41
    0

    I believe the other statements are incorrect. Not being a variable declaration:

    • *ponteiro would mean access to the first memory address, where the value is stored;

    • ponteiro would mean the value stored in memory;

    • and &ponteiro would create a pointer, for the existing pointer.

    In case if it is variable declaration:

    • *ponteiro would allocate memory to store the variable;

    • and ponteiro would be an invalid statement.

    15.03.2018 / 04:44