PR04 - errptr

PR04 - errptr

por Bruno Carneiro da Cunha -
Número de respostas: 8

Oi professor, o tipo de errptr não seria char ** em vez de const char **? Já que precisamos atribuir um novo valor a errptr em caso de erro me parece estranho declarar como const. Obrigado!

Em resposta à Bruno Carneiro da Cunha

Re: PR04 - errptr

por Leonardo Lana Violin Oliveira -

Olá Bruno,

O ponteiro ser const não afeta a alteração de seu conteúdo e sim de seu endereço. Logo você pode atribuir valores no endereço apontado pelo errptr, mas não pode mudar o endereço que ele aponta.

Abraços,

Lana

Em resposta à Bruno Carneiro da Cunha

Re: PR04 - errptr

por José Coelho de Pina -

Oi Bruno,

Legal!
Só para ilustrar a resposta do Lana.
Na classe Node a seguir left e right são final, uma espécie de const do C.

    private static class Node {
        private Value val; 
        private final Node left, right;
        [...]
    }

Uma vez feita a atribuição a left ou right não podemos modificar essas referências.
No entando, podemos alterar os campos x.left.val e x.right.val de x.left e x.right.

Vixe!
Talvez eu tenha complicado...

P.S. Ia dar o exemplo da classe Node da trie que usamos na classe Huffman, mas lá todos os atributos eram final: char c, int freq, Node left e Node right.

Em resposta à José Coelho de Pina

Re: PR04 - errptr

por Bruno Carneiro da Cunha -

Oi Coelho, após algum estudo na web a questão ficou ainda mais complexa pra mim.

 

Rodando o seguinte teste:

    const char *ptr = "You say goodbye";

    printf("const char *ptr\n");

    printf("ANTES\t = %s\t *ptr = %p\t &ptr = %p\n", ptr, ptr, &ptr);

    ptr = "I say hello";

    printf("DEPOIS\t = %s\t\t *ptr = %p\t &ptr = %p\n", ptr, ptr, &ptr);

 

Obtive o seguinte output:

    const char *ptr

    ANTES = You say goodbye *ptr = 0x10b986f3e &ptr = 0x7fff542797c0

    DEPOIS = I say hello         *ptr = 0x10b986f82 &ptr = 0x7fff542797c0

 

O que vai de acordo com o que está na web. O ponteiro mudou o endereço pra onde aponta sem problemas.

 

O próximo teste não compila:

    printf("char * const ptr\n");

    char * const ptr2 = "You say goodbye";

    printf("ANTES\t = %s\t *ptr = %p\t &ptr = %p\n", ptr2, ptr2, &ptr2);

    ptr2 = "I say hello";

    printf("DEPOIS\t = %s\t\t *ptr = %p\t &ptr = %p\n", ptr2, ptr2, &ptr2);

 

Ou seja, "char * const" é a declaração que realmente protege o endereço pra onde se aponta. E agora? No EP, o const está protegendo o conteúdo pra onde se aponta, e não o endereço pra onde se aponta. Não entendi ainda a necessidade do const, o que é de verdade a minha dúvida. Já vi esse const em outros lugares e gostaria de entender o porque realmente do uso. Será que é pra proteger strings em uma chamada de função? Obrigado!

Em resposta à Bruno Carneiro da Cunha

Re: PR04 - errptr

por José Coelho de Pina -

Oi Bruno,

Legal Bruno! Contra fatos não há argumentos. O exemplo que você é muito legal.

Voltemos const <tipo> **.
Desculpem por ter talvez mais atrapalhado que ajudado e também pela demora.
Vejam se o exemplo abaixo ajuda.
Compilem e executem para ver o resultado. maneiro
Eu gosto de C89, por isso compilei com

   % gcc -Wall -ansi -pedantic -O2 bla.c -o bla
   % ./bla
     ....
#include <stdio.h> /* printf(), scanf(), fscanf(), ... */ 
#include <stdlib.h> /* malloc(), free(), EXIT_SUCCESS, EXIT_FAILURE, ... */ 
#include <string.h>

/* prototipo */
void f(char *s, const char** p);

int
main()
{
    char *s = "Como e bom programar em C!\0\nIsso que e linguagem\n";
    const char *p = NULL;
    printf("%s", s);    
    f(s, &p);
    printf("%s", p);
    return 0;
}    

void
f(char *s, const char **p)
{
    *p = s + strlen("Como e bom programar em C!\n\0");
}    

P.S. Por favor, não direcionem a pergunta.
Deve ter gente aqui no fórum que pode responder qualquer pergunta melhor que eu.

Em resposta à José Coelho de Pina

Re: PR04 - errptr

por Vitor Santa Rosa Gomes -

Nos exemplos a seguir, as linhas comentadas geram erro de compilação:


#include <stdio.h>
#include <stdlib.h>


int main() {

char* a = (char*) malloc(6*sizeof(char)); // ponteiro de char = início de array de char = string
a[0] = 'a'; a[1] = 'a'; a[2] = 'a'; a[3] = 'a'; a[4] = 'a'; a[5] = '\0';
char* b = (char*) malloc(6*sizeof(char));
b[0] = 'b'; b[1] = 'b'; b[2] = 'b'; b[3] = 'b'; b[4] = 'b'; b[5] = '\0';

const char* c = a; // ponteiro de caracteres inalteráveis
char* const d = a; // ponteiro inalterável de caracteres
const char* const e = a; // ponteiro inalterável de caracteres inalteráveis

printf("%s\t%s\t%s\t%s\t%s\n", a, b, c, d, e);

a[0] = 'A';
b[1] = 'B';
// c[2] = 'C';
d[3] = 'D';
// e[4] = 'E';

printf("%s\t%s\t%s\t%s\t%s\n", a, b, c, d, e);

c = b;
// d = b;
// e = b;

printf("%s\t%s\t%s\t%s\t%s\n", a, b, c, d, e);

char* tmp = a;
a = b;
b = tmp;

printf("%s\t%s\t%s\t%s\t%s\n", a, b, c, d, e);

return EXIT_SUCCESS;

}