Hack x Crack - Comunidad de Seguridad informática

Programación => C / C++ => Mensaje iniciado por: Pino1952 en Noviembre 30, 2014, 06:56:28 pm

Título: Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Pino1952 en Noviembre 30, 2014, 06:56:28 pm
Hola a todos, que tengan un muy buen día.
Como es mi primer post voy a presentarme:
Me llaman Daniel, tengo 62 años y vivo en Argentina -> Santa Fé -> Arequito, como comprenderán por mi edad ya no concurro a la universidad y todos mis conocidos ni saben prender una pc  y mucho menos programar, el único recurso que me queda es el manual con el que estoy estudiando y muchas molestias en los foros.-
El caso es que estoy en el capítulo punteros y cree un programita que dejo a continuación de un apuntador a un arreglo de 10 enteros, me parece que la manera de cargar los datos es correcta pero en lo que estoy lidiado es con imprimirlos.-
Compilo en línea de comando con MinGW (gcc)  y como editor de texto utilizo notepad++.-

Código: [Seleccionar]
#include <stdio.h>

#define MAX 10

int main(void){
int *ptrVector[MAX], i;

for(i=0; i<MAX; i++){
*(ptrVector + i) = &i;
}

for(i=0; i<MAX; i++){
printf("%d ", *(ptrVector + i));
}


printf("\n\n Pulse una tecla para finalizar..."); getchar();
return 0;
}

Citar
C:\ProgramasNotepad\Punteros.c: In function 'main':
C:\ProgramasNotepad\Punteros.c:13:3: warning: format '%d' expects argument of type 'int', but argument 2 has type 'int *' [-Wformat=]
   printf("%d ", *(ptrVector + i));
   ^
Es todo, espero que puedan ayudarme a encontrar la solución.-
Saludos.
Daniel
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: bum3r en Noviembre 30, 2014, 07:13:00 pm
Hola que tal Daniel.

Aca esta el problema, estas diciendo :  *(ptrVector + i ) = Direccion memoria de I..
   for(i=0; i<MAX; i++){
      *(ptrVector + i) = &i;   
   }
Esta seria una de las formas de hacerlo correctamente , saca tus conclusiones y si necesitas ayuda avisa, saludos.

   for(i=0; i<MAX; i++){
      *(ptrVector + i) = i;   
   }
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Calantra en Noviembre 30, 2014, 07:29:21 pm
Buenas,

No se si es esto lo que quieres hacer:

Código: [Seleccionar]
int vector[MAX];
    int *ptrVector = &vector[0];
for(int i=0; i<MAX; i++){
*(ptrVector + i) = i*128;
}

for(int i=0; i<MAX; i++){
printf("%d ", vector[i]);
}

En este caso el puntero(ptrVector) apunta a la dirección de inicio del vector de enteros (vector). Vamos incrementando la dirección del puntero y grabando el valor de i. Luego vemos que el resultado es correcto imprimiendo desde el vector de enteros.

Un saludo.
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Pino1952 en Noviembre 30, 2014, 08:07:58 pm
Hola bum3r
Muchas gracias por ocuparte, totalmente de acuerdo es que estaba tan embotado buscando y practicando que fue el último intento y así lo publique.-
Igual te dejo los 2 warning que me arroja el compilador, si tenes un poco de tiempo tal vez puedas decirme como solucionarlos.-   

Citar
C:\ProgramasNotepad\Punteros.c: In function 'main':
C:\ProgramasNotepad\Punteros.c:9:20: warning: assignment makes pointer from integer without a cast [enabled by default]
   *(ptrVector + i) = i+1; 
                    ^
C:\ProgramasNotepad\Punteros.c:13:3: warning: format '%d' expects argument of type 'int', but argument 2 has type 'int *' [-Wformat=]
   printf("%d ", *(ptrVector + i));
   ^

Saludos.
Daniel
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: bum3r en Noviembre 30, 2014, 08:31:24 pm
Perdon, le conteste algo que quzas le  servia, pero no era del todo correcto, eso pasa por leer tan rapido XD.
Vamos por partes .
Código: [Seleccionar]
#include <stdio.h>

#define MAX 10

int main(void){

//Esta declaración es innecesaria.. serviria con declarar un simple array[] de una dimension.
//int *ptrVector[MAX], i;
//Esta forma es las correcta para este ejemplo.
int ptrVector[MAX],i;

for(i=0; i<MAX; i++){
//Aca, *(ptrVector+i)=[u]&i[/u] , no es del todo correcto para este ejemplo, ya que *(ptrVector+i) espera un valor entero, y [u]&i [/u] le proporciona una dirección de memoria.
//*(ptrVector + i) = &i;
//Esto seria correcto.
          *(ptrVector + i) = i;
}

for(i=0; i<MAX; i++){
//Aqui   ya no  da ningun warning.
printf("%d ", *(ptrVector + i));
}

Seria cosa de fijarse con su compilador si sigue dando el warning..
Saludos
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Pino1952 en Noviembre 30, 2014, 08:57:59 pm
Hola.
A los dos muchas gracias y les comento que el programa de ambos compila a la perfección, al de Calantra le hice una pequeña modificación en el printf con notación de punteros (fue el que tome como referencia, por ser el primero que me funcionó).-

Código: [Seleccionar]
#include <stdio.h>
#include<stdlib.h> 
#include<time.h>

#define MAX 10

int main(void){
int vector[MAX], *ptrVector = &vector[0], i, hora = time(NULL); 

srand(hora);

for(i=0; i<MAX; i++){
*(ptrVector + i) =  rand()% 100;
}

printf("\n\n");
for(i=0; i<MAX; i++){
printf("%d ", *(ptrVector + i));
}

printf("\n\n Pulse una tecla para finalizar..."); getchar();
return 0;
}

Ahora les pido unos minutos más para que me digan que pasa con lo que dice en esta página y porque no funciona (es con la cual tome la referencia para hacer el primer programita).-
   
http://www.cimat.mx/~alram/cpa/pointersC.pdf (http://www.cimat.mx/~alram/cpa/pointersC.pdf)
Poner en la búsqueda: int (*p1d)[10];

Saludos.
Daniel
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Calantra en Noviembre 30, 2014, 09:06:11 pm
Enas de nuevo...

Aunque ya te están ayudando, me gustaría aclarar unas cositas para los mas curiosos.

A lo que puse antes también se le puede añadir otro modo de inicializar el puntero. Usaremos malloc para reservar memoria para el puntero:

   
Código: [Seleccionar]
int *puntero;               
    puntero = (int*) malloc (10);

Hemos reservado el espacio en memoria equivalente a 10 enteros. Si cada entero ocupa 4 bytes en memoria, pues un total de 40 bytes en memoria.
Ahora el puntero apunta al la dirección que devuelve malloc. Esto lo he querido hacer mas gráfico y lo he pasado por un depurado, yo uso olly:
Código: [Seleccionar]
CPU Disasm
Address   Hex dump          Command                                  Comments
00401453  ³> C70424 0A00000 MOV DWORD PTR SS:[LOCAL.30],0A           ; Úsize => 10.
0040145A  ³. E8 41510100    CALL <JMP.&msvcrt.malloc>                ; ÀMSVCRT.malloc
0040145F  ³. 8945 C0        MOV DWORD PTR SS:[LOCAL.16],EAX
EAX= 007510A8

Como podemos observar la direccion que devulve malloc se almacen en el registro de direcciones EAX, que apunta al direccion de memoria 007510a8. Veamos que hay en esa zona antes de lanzar el código:
Código: [Seleccionar]
CPU Dump
Address   Hex dump                                         ASCII
007510A8  0D F0 AD BA|0D F0 AD BA|EE FE AB AB|AB AB AB AB|
ð­º
ð­ºîþ««««««
007510B8  AB AB EE FE|EE FE EE FE|00 00 00 00|00 00 00 00| ««îþîþîþ
007510C8  7E A0 5B 83|76 86 00 00|A8 37 75 00|F8 0F 75 00| ~ [ƒv†  ¨7u øu

Ahora el resto del código:
Código: [Seleccionar]
    for (int i=0;i<10;i++,puntero++) {
        *puntero=i*128;
        printf ("valror%d direccion:0x%x \n",*puntero,puntero );
    }
   
    free (puntero);

La dirección del puntero la incremento en el propio for, pero esto se puede hacer perfectamente de otro modo.
Imprimimos el valor de la memoria apuntada por el puntero(*puntero) y a continuación la dirección de memoria (puntero). Lógicamente la primera dirección sera la que nos devolvio malloc ( 007510A8)

y si hacemos un volcado de esa zona de memoria con nuestro depurador :
Código: [Seleccionar]
CPU Dump
Address   Hex dump                                         ASCII
007510A8  00 00 00 00|80 00 00 00|00 01 00 00|80 01 00 00|     €      €
007510B8  00 02 00 00|80 02 00 00|00 03 00 00|80 03 00 00|    €     €
007510C8  00 04 00 00|80 04 00 00|A8 37 75 00|F8 0F 75 00|    €  ¨7u øu

Los datos hay que interpretarlos teniendo en cuenta el tipo de procesador, los x86 son little endian (http://es.wikipedia.org/wiki/Endianness (http://es.wikipedia.org/wiki/Endianness)) por lo que los valores se almacenan en la memoria al revés. Así tenemos que el segundo valor seria interpretado como 00 00 00 80 (128) , en ve de 80 00 00 00 (2147483648).

Un saludo.
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Calantra en Noviembre 30, 2014, 09:18:18 pm
Enas again, jae jae jae

Código: [Seleccionar]
int (*p1d)[10];
es la declaración apropiada, es decir p1d es aquí un apuntador a un arreglo de 10 enteros tal y como era como
cuando fue declarado usando el tipo de datos Arreglo. Observa que es diferente de hacer:
p1d apuntara a un vector(o array, como prefieras) de 10 enteros, en este caso typedef int Arreglo[10]; como indica el texto cuando añadamos  p1d = &arreglo[0];
P1d = direccion en memoria de arreglo en su posicion 0. y *p1d contiene el valor del entero contenido en arreglo[0], asi como p1d+1 causaria que *p1d fuera  = a arreglo[1]. Ten en cuenta, como expliqué en el anterior post un poco mas técnicamente, cada entero ocupa 4 bytes en memoria, así que si la direccion de p1d es 0000, la de p1d+1 sera 0004.


Código: [Seleccionar]
int *p1d[10];
lo que haría de p1d el nombre de un arreglo de 10 apuntadores al tipo entero.
Es sencillo, p1d en este caso es un vector(array) de 10 punteros.

Se entiende?

Pd. Resumiendo... una variable o vector(array) es un espacio asignado en la memoria.
Un puntero es una etiqueta que contiene la dirección de memoria, de una variable, de un vector, de lo que queramos. También podemos asignarle memoria directamente con la funcion malloc.
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Pino1952 en Diciembre 01, 2014, 08:56:31 pm
Hola Calantra.
Muy buenos los dos post, el primero no entiendo nada porque todavía no practique con algo tan importante como depurar los programas, no obstante me baje el programa que usas y me voy a poner a aprenderlo a pesar de que está en inglés, en cuanto al segundo sí que me resultó sumamente interesante me aclaró conceptos desconocidos para mí.- 
Si en algún momento te place desearía me des un paso a paso cortito para empezar a utilizar el OLLYDBG, lo básico.-

Desde ya muchas gracias y Saludos.
Daniel
Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Calantra en Diciembre 02, 2014, 09:35:19 am
Hola Daniel,

Olly es un depurador de propósito general,  hace su trabajo a nivel de ensamblador. El ensamblador es un lenguaje de bajo nivel, lo que implica que se suele entender peor que uno de nivel medio o alto. Para comenzar con la depuración de tu código tienes dos opciones, como pasa con el lenguaje C, puedes usar un IDE, que te facilita la tarea enormemente o usar la linea de comandos.

Te dejo unos enlaces para que vayas entendiendo como va el tema:
http://www.genbetadev.com/cc/como-funciona-un-depurador-de-c-c-parte-i (http://www.genbetadev.com/cc/como-funciona-un-depurador-de-c-c-parte-i)
http://www.genbetadev.com/cc/como-funciona-un-depurador-de-c-c-parte-ii (http://www.genbetadev.com/cc/como-funciona-un-depurador-de-c-c-parte-ii)
http://www.genbetadev.com/cc/como-funciona-un-depurador-de-c-c-parte-iii (http://www.genbetadev.com/cc/como-funciona-un-depurador-de-c-c-parte-iii)

Un saludo.


Título: Re:Error en sintaxis al imprimir un apuntador a un arreglo de enteros[C].
Publicado por: Pino1952 en Diciembre 04, 2014, 11:09:52 pm
Hola calantra.
Muchas gracias por la info, ni bien tenga tiempo me pongo a estudiarla.-

Saludos.
Daniel