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!
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
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
.
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!
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.
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.
Perfeito, professor. Acho que entendi como vamos usar o errptr. Obrigado!
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;
}
Victor e Bruno, muito legal os exemplos e referência.