Dev - C++ - dudas muy básicas de punteros

 
Vista:
sin imagen de perfil

dudas muy básicas de punteros

Publicado por Frank (3 intervenciones) el 09/02/2018 00:30:54
buenas tardes, estoy aprendiendo c++ en la conocida pagina c.conclase.net, pero de repente se me hace o que va demasiado rápido y me he perdido o saltado algo, o que le ha faltado explicar algunos detalles.
A continuación pongo el ejemplo que ha puesto y que ha sido el decisivo para venir a molestarlos aqui a pedir ayuda:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
 
int main() {
   char cadena1[] = "Cadena 1";
   char *cadena2 = "Cadena 2";
 
   cout << cadena1 << endl;
   cout << cadena2 << endl;
 
   //cadena1++; // Ilegal, cadena1 es constante 
   cadena2++; // Legal, cadena2 es un puntero 
 
   cout << cadena1 << endl;
   cout << cadena2 << endl;
 
   cout << cadena1[1] << endl;
   cout << cadena2[0] << endl;
 
   cout << cadena1 + 2 << endl;
   cout << cadena2 + 1 << endl;
 
   cout << *(cadena1 + 2) << endl;
   cout << *(cadena2 + 1) << endl;
 
   return 0;
}

dudas:

1) En la linea 6 ... char *cadena2 = "Cadena 2"; ... , tenemos lo que veo como una variable "puntero a char", que como el dice, un puntero es solamente una variable cuyo contenido sera solamente una dirección, mas NO un char (ni por lo tanto una cadena).
Ahora pues ¿porque le esta asignando el contenido de una cadena al puntero cadena2?, como el bien se encarga anteriormente de dejarlo en claro, incluso usa una analogía: cita:

"tener ese puntero no crea árboles (variables) de forma automática cuando señalemos con él. Es un puntero, no una varita mágica. "

entonces ¿puntero "cadena2" no serviría con el propósito único y exclusivo para ser vinculado a una variable char, y no para guardar una cadena? ¿cuales son los limites de los punteros?

las siguientes dudas tal vez se resuelvan con la respuesta anterior, pero:

2) ¿por que en el tercer par de "cout" ambas imprimen 'a'?

3) en el cuarto par de couts ¿esta sumando +2 a cadena1, cuando en su comentario en la linea 11 dice que no se puede?

y 4) ¿porque es que en el quinto par de couts esta usando el operador asterisco de indireccion para el arreglo cadena1, si no fue declarado como un puntero?

gracias.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 338
Ha mantenido su posición en Dev - C++ (en relación al último mes)
Gráfica de Dev - C++

dudas muy básicas de punteros

Publicado por Martín (158 intervenciones) el 09/02/2018 04:30:22
En esta expresión:
1
char *cadena2 = "Cadena 2";


Se tiene:

- cadena2 es el nombre de la variable de tipo char* (puntero a carácter).

- este puntero "apunta" a la dirección de memoria donde comienza la sucesión de caracteres "Cadena 2". A esta sucesión de caracteres se le dice "literal de cadena" (o string literal, en inglés). De nuevo: cadena2 apunta a la dirección donde comienza ese literal, de modo que efectivamente guarda la dirección de memoria donde está almacenado el carácter 'C'.

Lo que me parece que te tiene medio confundido es que con ese puntero no sólo se puede acceder al contenido de la dirección de memoria que guarda (al la 'C') sino que se puede seguir de largo, sin límite: Incrementado en uno va a apuntar a la dirección de 'a'; incrementado en 2 apuntará a la dirección de 'd' y así sucesivamente.

¿Hasta cuando se puede incrementar el puntero cadena2? Hasta el infinito y más allá.

Pero entonces, ¿cómo sabemos dónde parar?
Una "cadena de caracteres de estilo C" (que así se llaman cuando uno está en C++) está terminada en 0 (cero), para indicar que ahí es donde termina. En inglés se las llama "null terminated C strings" cadenas de estilo C terminadas en nulo.

Cuando se escribe
1
char *cadena2 = "Cadena 2";


hay un cero que no se ve pero está ahí, el compilador lo agrega gentilmente aunque sin avisar; la cadena completa es en realidad "Cadena 2\0", con ese '\0' (barra cero) representando un cero real (de valor 0, no el carácter '0') para indicar que ahí termina.

Entonces, una función como "cout" (que es una función, o mejor dicho, toda una familia de funciones, aunque todavía no te lo parezca) "sabe" dónde detenerse y mostrar sólo "Cadena 2" porque busca y encuentra ese 0 como terminador. Si no lo encontrara mostraría todo el contenido de tu disco duro, a partir de la 'C',

Hay más cosas que tener en cuenta con estos punteros a carácter para usar al manjar textos, que vienen heredados del C. Pero como todo esta mecánica es una desgracias hasta de mal gusto, el C++ difícilmente usa estos punteros (se los llama "punteros crudos" o raw pointers), y son realmente de un uso marginal, muy rara vez se los ve un código real. El C++ tiene clases como los "smart pointers", los vectores, las strings, que hacen que los programadores no necesiten usar algo tan desagradable (A no ser que te dediques a escribir bibliotecas o trabajes programando compiladores, pero para eso creo que falta bastante).

En mi opinión, es una lástima que comiences a estudiar el lenguaje dedicando tanto tiempo a algo que es de uso marginal. Quizás deberías aprender a leer inglés (al menos) y conseguir un buen libro.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
2
Comentar
sin imagen de perfil

dudas muy básicas de punteros

Publicado por Frank (3 intervenciones) el 11/02/2018 03:42:18
Hola. muchas gracias por su consejo, lo voy a tomar en cuenta; yo creo que si no encuentro respuestas rápidas a mis dudas y veo que todo lo de punteros es un tema extenso y que requerirá mucho tiempo que mejor ahora necesito aprender otros temas mas importantes, entonces mejor si dejare para después este tema.

solamente para no dejar esto así nada mas, le cito:

"apunta" a la dirección de memoria donde comienza la sucesión de caracteres "Cadena 2"

pues es que en ese caso sí se estarían creando espacios de memoria para contener tal cadena, y por lo tanto si se estaría "creando arboles cuando señalamos con el puntero", como niega el profesor en su pagina, ¿verdad?

lo que me tiene confundido es que, como según lo había entendido yo, es que, como digo mas arriba, un puntero solo servia con el propósito único y exclusivo para ser vinculado (señalar), y nada mas; esa era la duda central.

pd.: unas disculpas por el retraso.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 338
Ha mantenido su posición en Dev - C++ (en relación al último mes)
Gráfica de Dev - C++

dudas muy básicas de punteros

Publicado por Martín (158 intervenciones) el 11/02/2018 16:36:03
"pues es que en ese caso sí se estarían creando espacios de memoria para contener tal cadena, y por lo tanto si se estaría "creando arboles cuando señalamos con el puntero", como niega el profesor en su pagina, ¿verdad?"

No, el puntero es una variable, que toma memoria del sistema para sí mismo, pero no para lo que apunta. En concreto, el operador sizeof devuelve el tamaño de una variable, y si lo aplicas al puntero y a la cadena tienes:

1
2
3
4
5
char* cadena = "Una cadena";
 
std::cout << sizeof(cadena) << '\n';  //  muestra 8 en mi sistema (un puntero a carácter ocupa 8 bytes) (en tu sistema puede ser distinto)
 
std::cout << sizeof("Una cadena") << '\n';  // muestra 11, que son los 10 caracteres que se ven más el último '\0' que pone el compilador

Como ves, la variable cadena, que es el puntero, ocupa una cantidad de memoria para sí mismo, como lo hace un int, o un double, o cualquier tipo de variable, mientras que el literal de cadena "Una cadena" ocupa en memoria 11 bytes, uno para cada carácter que la compone. Son dos objetos distintos, uno es el puntero, el otro es el apuntado.

Se necesita asignar memoria para las dos cosas, tanto para el puntero como para el literal apuntado. Así que creo que estás en lo cierto cuando dices "un puntero solo servia con el propósito único y exclusivo para ser vinculado (señalar), y nada mas;", esa es la idea.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

dudas muy básicas de punteros

Publicado por Frank (3 intervenciones) el 12/02/2018 07:55:57
okok... entonces tenemos que aun estando en un contexto declarativo-asignativo, en si la literal "Una cadena" es un niño perdido huérfano en la memoria del sistema que no pertenece ni es guardada realmente en ninguna variable, y que el símbolo "igual a" en dicha sentencia de declaración del puntero, como con las variables normales, esta ahí mas o menos para confundir a los programadores noobs como yo, cuando pudieron haber designado la misma buena sintaxis con el ampersand ...
1
char* cadena = &"Una cadena";
...

muchas gracias nuevamente, queda entendido ese pequeño detalle, un saludo, +1.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 338
Ha mantenido su posición en Dev - C++ (en relación al último mes)
Gráfica de Dev - C++

dudas muy básicas de punteros

Publicado por Martín (158 intervenciones) el 12/02/2018 15:18:11
En realidad es:

1
const char* cadena = &"Una cadena"[0];

Aquí se tiene:

- Como decíamos antes, cadena apunta a la dirección de memoria donde comienza "Una cadena"; o sea, apunta a la dirección de memoria donde se encuentra la 'U'.

- El literal "Una cadena" va a estar incluido en el ejecutable en su "Data Segment", en algún lugar de la memoria de sólo lectura.

- El puntero cadena es constante (no puede modificar el contenido de lo que apunta). (Porque el literal es de sólo lectura)

Como te decía: punteros crudos y arrays de estilo C son elementos del lenguaje de un uso realmente marginal. Comenzar a estudiar por los márgenes no parece ser una buena estrategia.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar