Problema de puntero

Iniciado por erest0r, 7 Noviembre 2013, 02:03 AM

0 Miembros y 1 Visitante están viendo este tema.

erest0r

Buenas noches, tengo una duda para entender este simple codigo

Código (cpp) [Seleccionar]

#include <iostream>

void modificar( int *, int);

int main( int argc, char* args[] )
{
   const int fil = 2;
   const int col = 6;
   int a[fil][col] = {};
   int *b;
   b = *a;

   modificar(*a,fil*col);

   for(int i = 0; i < fil*col; i++)
       cout << *(b+i) << " ";;

   
   cin.get();
   cin.get();
   return 0;
}

void modificar( int *a, int tamanio)
{
   int j;
   for(j = 0; j < tamanio; j++)
       *(a+j) = j;
}



1) ¿Que esta sucediendo cuando b = *a?

2) Los arreglos unidimensionales que he practicado se le pasan a la funcion solamente con su nombre, y ¿Por que aqui paso el arreglo con puntero? modificar( *a, fil*col );

En realidad pregunto esto, porque estaba probando y me funciono eso, pero no entiendo esas 2 lineas :S

Gracias
Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.

Almapa

A ver es un poco lioso, de hecho a mi también me cuestan bastante los punteros dichosos.
En la línea:
b = *a;

lo que se hace es guardar en la variables b el valor de la memoria donde se empieza a guardar la variable "a" que es una matriz 2x6.  Vamos a suponer que el valor de "b" es 4000.
(a==[2]x[6];     *a==4000;   b=4000)

Bien, a la función "modificar" se le pasan dos datos:  *a == 4000  y  fil*col==2*6==12.
void modificar( int *a, int tamanio)
{
   int j;
   for(j = 0; j < tamanio; j++)
       *(a+j) = j;
}


En la función se definen las posiciones de memoria que apuntarán al valor  (a+j) es decir, se define *(a+j), y se define igualándolo a j.
(Si j=0  ->   *(a+j)==*(4000+0)=0;   Si j=1  ->   *(a+j)==*(4000+1)=1;   etc.)


for(int i = 0; i < fil*col; i++)
       cout << *(b+i) << " ";

Al volver de la función hay otro bucle que en el que se mostrarán los valores de  *(b+i) dónde como sabemos b=4000 y "i" irá desde 0 a 12 por lo que mostrará:
(Si i=0  ->   *(b+i)==*(4000+0)  --> 0;   Si j=1  ->   *(b+i)==*(4000+1)  --> 1;   etc.   tal y como se había definido en la función modificar).


Espero haberte ayudado y si me he equivocado corrijanme así aprenderé yo también.

Un saludo!

vangodp

#2
b = *a; En esta linea lo que quiere decir es que a b le asignamos el "valor" de a, con el operador * usamos el valor, y el operador & usamos su dirección.
Si fuera: b = &a entonces a la b se le asignaba el numero de la dirección de memoria.
Esos operadores se utilizan mucho para punteros, los punteros son algo que lían un poco al programadores nuevos pero son de mucha utilidad para trabajar con la memoria del ordenador.
Con los punteros o trabajas con la dirección o trabajas con el valor de una variable, entonces * es valor y & es su dirección.(Esta claro que no es así de simple pero tampoco mucho mas complicado no es)
Si una funcion es asi: takeA(int *A) Esta función esta esperando el valor entonces deberíamos pasar la dirección de esta manera takeA(&A), al saber que la función va  trabajar con el valor de lo que le vamos pasar pues simplemente le pasamos la dirección.
Si la función es así: take(&B); La función  espera la dirección ahora, sabemos que va modificar la variable directo a la dirección memoria, o sea que le tenemos que pasar normalmente el valor take(B);
Esto se usa para cambiar desde una función a una variable que esta dentro de otra función como en este ejemplo.
En tu pregunta nº 2 creo que le pasas 2 parámetros enteros, el 1º es el valor de a, y el segundo es fil multiplicado por col
Busca leer sobre paso por referencia.
O mira este vídeo, es sobre el tema este.
http://minidosis.org/C++/Subprogramas/Valor%20vs%20Referencia/

Aquí dejo algunos vídeos mas relacionados con este tema tan delicado :D
http://minidosis.org/C++/Subprogramas/Acciones%201/
http://minidosis.org/C++/Subprogramas/Acciones%202/
http://minidosis.org/C++/Subprogramas/Devolver%20M%C3%A1s%20de%20un%20Resultado/
http://minidosis.org/C++/Subprogramas/Definici%C3%B3n%20de%20Acci%C3%B3n/
Te recomiendo que veas todos estos videos de aqui:
http://minidosis.org/C++/Punteros%20y%20Referencias/
Si tienes ganas de aprender los verias todos que Paueky es la caña  ;-)
http://minidosis.org/C++/

erest0r

#3
Si, yo conozco eso, lo que no entiendo es por qué si es un arreglo unidimensional se le pasa a la funcion

funcion( arreglo );

En cambio para arreglo de 2 dimensiones se le pasa

funcion( *arreglo );

Y cuando se asigna la direccion de memoria de un arreglo unidimensional se suele hacer

Código (cpp) [Seleccionar]

int a[2];
int *b;
b = a;


En cambio en este ejemplo

Código (cpp) [Seleccionar]

int a[2][6];
int *b;
b = *a;


Se supone "b" debe contener la direccion de memoria de "a" y pareciese que le estoy es asignando su valor  :-\
Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.

xiruko

int a[2][6];
int *b;
b = *a;


a es un array de punteros a entero, o lo que es lo mismo es una matriz bidimensional de enteros (int**).

b es un puntero a entero, o lo que es lo mismo es un array de enteros (int*).

Así pues, cuando haces b=*a es porque estas desreferenciando el puntero a un nivel, por lo que le estas pasando a b la dirección de la primera fila de la matriz a. Es lo mismo que si hicieras b=a[0] o b=&a[0][0].

En la función modificar, le pasas como parámetro *a, y como a es del tipo int**, lo que le pasas a la función es del tipo int* (porque desreferencias una vez con el asterisco), por lo que a la función solo le llega un vector de enteros que en este caso sería la primera fila de la matriz a.

Saludos.

rir3760

Cita de: erest0r en  7 Noviembre 2013, 12:25 PMlo que no entiendo es por qué si es un arreglo unidimensional se le pasa a la funcion

funcion( arreglo );

En cambio para arreglo de 2 dimensiones se le pasa

funcion( *arreglo );

Y cuando se asigna la direccion de memoria de un arreglo unidimensional se suele hacer
Código (cpp) [Seleccionar]
int a[2];
int *b;
b = a;


En cambio en este ejemplo
Código (cpp) [Seleccionar]
int a[2][6];
int *b;
b = *a;


Se supone "b" debe contener la direccion de memoria de "a" y pareciese que le estoy es asignando su valor
La regla que aplica en este escenario es: en C y C++ cuando se nombra a un array de tipo "T [N]" mediante su identificador o una expresion ello resulta (salvo excepciones, por ejemplo sizeof) en la direccion en memoria del primer elemento del array y este puntero es de tipo "T *".

Los pasos al evaluar la expresion "b = *a" son:

1) "a" es una array de tipo "int [2][6]" y resulta en la direccion en memoria del elemento "a[0]" y es de tipo "int (*)[6]", un puntero a array.

2) Al aplicar indireccion con "*a" ya no tratamos con el puntero a array sino con el array. Este es de tipo "int [6]" y aplica lo mismo: la expresion denotando un array resulta en la direccion en memoria de su primer elemento (de a[0][0]) y el tipo del puntero es "int *".

3) La direccion en memoria de a[0][0] y de tipo "int *" se almacena en la variable "b", como los tipos coinciden no hay problema.

Por ultimo hay que tener mucho cuidado y no confundir arrays con punteros, tienen una relación estrecha pero son distintos. Una buena analogía aquí es el trabajo del cartero: nunca confunde la dirección de una casa (de nuestro lado un puntero) con la casa en si (para nosotros el objeto apuntado).

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

vangodp

¿Entonces aquí  se esta pasando a dereferenciado y fil multiplicado por col? 
modificar(*a,fil*col);

rir3760

Cita de: vangodp en  7 Noviembre 2013, 14:47 PM¿Entonces aquí  se esta pasando a dereferenciado
Casi. La indirección no se aplica a "a", se aplica al puntero resultante de evaluar "a" (ya se que raya en la pedantería pero mejor ser tan precisos como sea posible).

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

erest0r

#8
Entonces  como "a" es del tipo (int **) [Debi haberle colocado otro nombre a ese arreglo], contiene la direccion de memoria de por decirlo asi "*a", y este a su vez tiene la diereccion de memoria de "a"

Código (cpp) [Seleccionar]

int **a0;
int *a1;
int a2;

a1 = &a2;
a0 = &a1;

// *a0 obtiene la direccion de memoria que contiene a1



Y cuando pase por parametro "*a0" que en este caso es "*a", estoy es pasando la direccion de memoria de la primera posicion de "a2" que es del arreglo.

No se si me explique bien y si fue la mejor forma de explicarlo, pero lo veo asi.

Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.

erest0r

Bueno por lo que lo probe sí es así, entonces se pasa el puntero todo como un arreglo unidimensional a la función, gracias por la explicación.  :D
Cruzar la calle junto a mucha gente cuando el semáforo sigue en rojo da seguridad y espíritu de equipo... o cruzamos todos o morimos juntos.