paulo1205
(usa Ubuntu)
Enviado em 23/02/2019 - 19:43h
Steve escreveu:
Eu também sou iniciante como você e nunca entendi de verdade o que é um ponteiro.
Ponteiro é um valor que tem duas características:
• representa um endereço de memória, e
• traz associado a si o tipo de dado que pode ser encontrado no endereço representado.
Esses tipos de valores podem ser armazenados em variáveis declaradas com a finalidade específica de armazenar tais valores, mas um valor de um tipo ponteiro pode ser obtido de várias formas, sem necessariamente estar associado a uma variável de um tipo ponteiro.
Explicitamente, ponteiros, sendo valores, podem ser obtidos das seguintes maneiras:
• por meio do operador unário
& , que devolve um ponteiro que indica o endereço de um elemento alocado como dado na memória e carrega a informação do tipo de dado do elemento cujo endereço foi obtido;
• como decaimento automático de um dado de um tipo
array (em C, um
array só é tratado como tal no momento de sua declaração e quando é passado como argumento para os operadores unários
& e
sizeof ; em todos os outros contextos, ele decai para ponteiro, produzindo um valor ponteiro que é idêntico ao que seria produzido se o operador unário
& tivesse sido aplicado ao seu primeiro elemento);
• como valor de retorno de uma função que devolve um valor ponteiro;
• quando se obtém o valor de uma variável declarada com um tipo ponteiro; e
• pela conversão de tipo (em inglês chamada de
type casting ), forçada ou implícita, de um valor inteiro qualquer ou de um ponteiro para dados de outro tipo para um tipo ponteiro.
Os casos acima podem ser ilustrados em código.
int n; // n é uma variável que contém um dado do tipo “int”.
const long l=5; // l é uma “variável” com valor constante igual a 5.
char nome[]="Paulo"; // nome é um array com 6 elementos do tipo char.
char *pc; // pc é uma variável que contém um dado do tipo “ponteiro para dado do tipo char”.
char **ppc; // ppc é uma variável que contém um dado tipo “ponteiro para dado do tipo ‘ponteiro para dado do tipo char’”.
&n; // produz um valor do tipo “ponteiro para dado do tipo int”: o endereço é aquele onde n está armazenada, e o tipo de dado associado é “int”.
&l; // produz um valor do tipo “ponteiro para dado constante do tipo long”: o endereço é aquele onde l está armazenada, e o tipo de dado associado é “const long”.
&nome[0]; // produz um valor do tipo “ponteiro para dado do tipo char”: o endereço é aquele onde nome[0] está armazenado, e o tipo de dado associado é “char”.
nome; // produz, por decaimento do array para ponteiro, um valor idêntico ao produzido por “&nome[0]”.
&nome; // não há decaimento pois o operador & foi aplicado ao array: nesse caso produz um valor do tipo “ponteiro para dado do tipo ‘array com 6 elementos do tipo char’”:
// o endereço é aquele de onde o array começa, e o tipo de dados associado é “array com 6 elementos do tipo char”.
pc=strdup(nome); // A função strdup() aloca uma nova região de memória e copia para ela o conteúdo do array nome (que decaiu para ponteiro antes de se chamar
// a função) e retorna um ponteiro para o primeiro elemento da área alocada, cujo tipo de dado associado é “char”.
ppc=&pc; // produz um valor do tipo “ponteiro para dado do tipo ‘ponteiro para dado do tipo char’” e o atribui a ppc: o endereço é aquele onde pc está armazenado
// (não o valor contido em pc) e o tipo de o dado associado é “ponteiro para dado do tipo char”.
#define NULL ((void *)0) // Definição padrão de NULL em C: a conversão explícita para “ponteiro para dado de qualquer tipo” (qualquer, aí, indicado por “void”) do valor
// inteiro 0: o tipo de dados associado é “ponteiro para dado de qualquer tipo” (pode ser convertido implicitamente de e para qualquer outro ponteiro).
free(pc); // O valor de pc é implicitamente convertido para “ponteiro para qualquer tipo” (o parâmetro de free() é do declarado como “void *”) e é passado como argumento
// para a função; o endereço é o mesmo endereço representado por pc (obtido do retorno de strdup(), acima), mas seu tipo associado foi agora convertido para
// “ponteiro para dado de qualquer tipo”.
Eu acredito que ponteiros sejam exatamente o que dizem. Eles não recebem nenhum valor e não fazem nada. São apenas um atalho do programa para um objeto no sistema operacional, igual mesmo um atalho do windows.
Como você viu acima, na verdade ponteiros
são valores, e pode haver variáveis que recebem, armazenam e devolvem tais valores.
Atalhos do Windows não são a mesma coisa que (ou, como você disse, iguais a) ponteiros. Pode ser que, em alguns aspectos, possamos fazer analogias (por exemplo: o ponteiro e o atalho oferecem maneiras de chegar a um objeto original na memória ou no sistema de arquivos, respectivamente, e eles próprios podem ocupar espaço, respectivamente, na memória ou no disco, ondes esses apontamentos possam ser armazenados). Mas, sendo coisas distintas e com propósitos distintos, nenhuma entre eles será analogia será perfeita (por exemplo: um atalho é uma entidade presente no disco; um ponteiro nem sempre será explicitamente armazenado numa região de memória dedicada a ele).
Como o programa não pode ler o arquivo sem algum comando, parece que o ponteiro indicaria onde o arquivo está para ele ser lido.
É mais complexo que isso. Na verdade, o tipo “
FILE ” de <stdio.h> esconde um dado composto de múltiplos campos diferentes, que normalmente são preenchidos quando se chama
fopen () para receber um objeto que representa um tipo de interação com o sistema operacional. Internamente, dados desse tipo contêm informações tais como:
• uma representação para que o sistema operacional possa manipular o objeto;
• quais operações são possíveis sobre ele (leitura, escrita, operações de terminal e possivelmente outras, dependendo do sistema envolvido);
• indicadores de possíveis erros e estado da última operação válida;
•
buffers de entrada e/ou saída;
• índíces que indicam a última posição a que se fez a acesso e/ou próxima posição a aceder no
buffer e/ou no próprio objeto do sistema operacional;
• etc.
Acho que no caso do fgets abaixo, ele deve ter instruções para acessar VIA ATALHO no caso o ponteiro, o arquivo verdadeiro do seu computador para então ler as linhas do arquivo. talvez por isso que qdo você tentou ler a variável ela é vazia, pq não é um armazenador de nada, e sim apenas um atalho para outro lugar.
Num sistema como o UNIX ou Linux, tipicamente o ponteiro para dado do tipo
FILE contém um descritor de arquivo fornecido pelo sistema operacional e informações sobre
buffers em memória. Quando se chama
fgets () ou qualquer outra função de leitura, a função primeiro examina se o
buffer em memória contém os dados solicitados. Se os contiver, copia os dados para o local indicado pelo usuário e retira esses dados do
buffer . Se faltarem dados no
buffer , uma operação de leitura a partir do arquivo é solicitada ao sistema operacional, de modo a encher de novo todo o
buffer , mesmo que isso exceda a quantidade de dados solicitada pelo usuário, na esperança de que uma próxima operação de leitura não tenha de ir ao disco de novo (porque ir ao disco é sempre uma operação custosa).
Caso, ao longo do processo, alguma dessas operações falhe, como por se ter atingido o fim do arquivo ou o sistema operacional ter encontrado um erro, os respectivos campos sinalizadores dessas condições são preenchidos no dado do tipo
FILE indicado pelo ponteiro (que, no caso de
fgets (), é passado como seu terceiro argumento).
Bom, como eu disse, eu não sei a resposta, apenas escrevi o que parece ser para mim, outras pessoas vão te ajudar com explicações verdadeiras sobre a questão.
Espero que eu tenha sido bem sucedido nesse mister.
... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)