Pseudopunteros

Iniciado por 85, 19 Marzo 2013, 10:26 AM

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

85

Estaba mirando este topic
http://foro.elhacker.net/programacion_cc/es_posible_hacer_esto_sin_arreglos-t385430.0.html
y se me ocurrió una idea, ya que había dicho chistosamente que se puede resolver con 10 variables, lo cual es cierto pero nunca se trata de usar tantas variables.

Lo que se me ocurrió es utilizar el mismo problema y utilizar las 10 variables
para resolverlo, pero usando aritmética de punteros.

El tema es que en realidad me propuse no usar variables de tipo puntero sino variables simples que guarden valores, en este caso, variables enteras.

una variable ocupa un espacio y tiene una dirección de memoria, eso lo sabemos todos. también sabemos que una variable almacena un valor.
pero ese valor puede ser una dirección de memoria también, tal como
los punteros.

Por eso en este topic voy a mostrar como hacer que con variables simples podamos tratarlas como punteros, obviamente sin usar variables de tipo puntero.

Esto se me ocurrió llamarlo "Pseudopunteros" porque en realidad no son variables de puntero.

En realidad no hay ninguna necesidad de hacer esto, ya que el lenguaje
nos da las variables de puntero para hacer esto. Pero ya que es posible
me parece correcto dejar en claro como se puede hacer.

Tampoco estoy seguro si el término "pseudopunteros" sea el correcto,
estuve buscando por google acerca de esta expresión pero sólo sale
algo relacionado a objetos.

por ejemplo:
http://www.ehow.com/info_11400371_difference-between-static-method-class-method.html
http://users.auth.gr/users/6/9/076096/public_html/courses/DataStructures/Implementations.html

pero no hablan de ninguna definición formal, por lo tanto me parece bien llamar a estas variables así XD.

El problema se trata de ingresar 10 números, listarlos, y decir cuáles se
repitieron y cuántas veces.

Para eso vamos a usar 10 variables enteras, que se van a almacenar en forma una seguida de la otra. Vamos a tomar en cuenta para este ejemplo que un entero son 4 BYTES. y con eso vamos al código directamente:

MODIFICADO
Como no se puede garantizar que las variables locales se almacenen de forma contigua en memoria o en un orden determinado (especificaciones de C++), y por el hecho de que los tamaños de los tipos de datos y de las direcciones de memoria no son iguales en diferentes sistemas (ej: x64), se hicieron algunas modificaciones en el código de la demostración.
No se tomaron en cuenta todos los tipos de datos tampoco porque para la demostración tampoco era necesario.

main.cpp
Código (cpp) [Seleccionar]
//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

//#include<windows.h>
#include<stdio.h>
#include<stdlib.h>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test1();
void Test2();
void Test3();

/////////////////////////////////////////////////////////////////////////////////////////////////

int main(){

system("cls");
printf("Test1:\n");
Test1();
system("pause");

system("cls");
printf("Test2:\n");
Test2();
system("pause");

system("cls");
printf("Test3:\n");
Test3();
system("pause");

return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////


pseudopointers1.cpp
Código (cpp) [Seleccionar]


//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <typeinfo>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// No tenemos garantía de que sean almacenadas contiguamente!
static int entrada1=0;//entrada1+0x0
static int entrada2=0;//entrada1+0x4
static int entrada3=0;//entrada1+0x8
static int entrada4=0;//entrada1+0xC
static int entrada5=0;//entrada1+0x10
static int entrada6=0;//entrada1+0x14
static int entrada7=0;//entrada1+0x18
static int entrada8=0;//entrada1+0x1C
static int entrada9=0;//entrada1+0x20
static int entrada10=0;//entrada1+0x24

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test1(){
/*
////////////////////////////////////
// Basic check (Designed for 10 variables no more)

//int entrada10=0;// Hacerlo cagar XD
printf("Estas direcciones deben estar en forma contigua!\n");
printf("0x%X\n",&entrada1);
printf("0x%X\n",&entrada2);
printf("0x%X\n",&entrada3);
printf("0x%X\n",&entrada4);
printf("0x%X\n",&entrada5);
printf("0x%X\n",&entrada6);
printf("0x%X\n",&entrada7);
printf("0x%X\n",&entrada8);
printf("0x%X\n",&entrada9);
printf("0x%X\n",&entrada10);
int flag_exit=0;
if( ((&entrada2)-((&entrada1)+0x1)) !=0){flag_exit=1; goto error;}
if( ((&entrada3)-((&entrada2)+0x1)) !=0){flag_exit=2; goto error;}
if( ((&entrada4)-((&entrada3)+0x1)) !=0){flag_exit=3; goto error;}
if( ((&entrada5)-((&entrada4)+0x1)) !=0){flag_exit=4; goto error;}
if( ((&entrada6)-((&entrada5)+0x1)) !=0){flag_exit=5; goto error;}
if( ((&entrada7)-((&entrada6)+0x1)) !=0){flag_exit=6; goto error;}
if( ((&entrada8)-((&entrada7)+0x1)) !=0){flag_exit=7; goto error;}
if( ((&entrada9)-((&entrada8)+0x1)) !=0){flag_exit=8; goto error;}
if( ((&entrada10)-((&entrada9)+0x1)) !=0){flag_exit=9; goto error;}
error:
if(flag_exit>0){
printf("It seems they are not stored contiguously. Error %d\n", flag_exit);
system("pause");
return;
}*/

////////////////////////////////////

#define XPOINTERTYPE unsigned long
#define XVARTYPE int
//if(sizeof(XVARTYPE) != sizeof(entrada1)) return;
unsigned char OFFS = (unsigned char)sizeof(XVARTYPE);// Up to 255
XPOINTERTYPE entradaX=(XPOINTERTYPE)&entrada1;// Una especie de puntero THIS
XPOINTERTYPE inicio_bloque=(XPOINTERTYPE)&entrada1;
XPOINTERTYPE fin_bloque=(XPOINTERTYPE)&entrada10;
int rep = 0;
const int MAX_NUMB =10;
char* format;
if(!strcmp(typeid(XVARTYPE).name(), "int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) format="%X";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) format="%f";
else return;

for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un número\n");
scanf(format,(XPOINTERTYPE*)entradaX);

rep=0;
XPOINTERTYPE apuntador1=(XPOINTERTYPE)&entradaX;//Doble puntero

for(XPOINTERTYPE j=inicio_bloque;j<(inicio_bloque+(OFFS*i));j+=OFFS)
{
XPOINTERTYPE apuntador2=(XPOINTERTYPE)&j;//Doble puntero

if(**(XVARTYPE**)apuntador1 == **(XVARTYPE**)apuntador2){
rep++;
}
}

if(rep)
{
char* info;
if(!strcmp(typeid(XVARTYPE).name(), "int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) info="%X had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) info="%f had %d repetitions\n";
printf(info,**(XVARTYPE**)apuntador1,rep);
//while(getchar()!='\n');
system("pause");
}

entradaX+=OFFS;
}
entradaX=(XPOINTERTYPE)&entrada1;//Arreglar el pseudopuntero THIS

for(int k=1;k<=MAX_NUMB;k++)
{
printf(format,*(XVARTYPE*)entradaX);

entradaX+=OFFS;
}
printf("\n");
entradaX=(XPOINTERTYPE)&entrada1;//Arreglar el pseudopuntero THIS
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


pseudopointers2.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <typeinfo>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Vamos a usar un array para asegurarnos de que los 10 enteros
// sean almacenados de forma contigua.
static int entradas[10] = {0};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test2(){

#define XPOINTERTYPE unsigned long
#define XVARTYPE int
//if(sizeof(XVARTYPE) != sizeof(entradas[0])) return;
unsigned char OFFS = (unsigned char)sizeof(XVARTYPE);// Up to 255
XPOINTERTYPE entradaX=(XPOINTERTYPE)&entradas[0];// Una especie de puntero THIS
XPOINTERTYPE inicio_bloque=(XPOINTERTYPE)&entradas[0];
XPOINTERTYPE fin_bloque=(XPOINTERTYPE)&entradas[9];
int rep = 0;
const int MAX_NUMB =10;
char* format;
if(!strcmp(typeid(XVARTYPE).name(), "int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) format="%X";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) format="%f";
else return;

for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un número\n");
scanf(format,(XPOINTERTYPE*)entradaX);

rep=0;
XPOINTERTYPE apuntador1=(XPOINTERTYPE)&entradaX;//Doble puntero

for(XPOINTERTYPE j=inicio_bloque;j<(inicio_bloque+(OFFS*i));j+=OFFS)
{
XPOINTERTYPE apuntador2=(XPOINTERTYPE)&j;//Doble puntero

if(**(XVARTYPE**)apuntador1 == **(XVARTYPE**)apuntador2){
rep++;
}
}

if(rep)
{
char* info;
if(!strcmp(typeid(XVARTYPE).name(), "int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) info="%X had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) info="%f had %d repetitions\n";
printf(info,**(XVARTYPE**)apuntador1,rep);
//while(getchar()!='\n');
system("pause");
}

entradaX+=OFFS;
}
entradaX=(XPOINTERTYPE)&entradas[0];//Arreglar el pseudopuntero THIS

for(int k=1;k<=MAX_NUMB;k++)
{
printf(format,*(XVARTYPE*)entradaX);

entradaX+=OFFS;
}
printf("\n");
entradaX=(XPOINTERTYPE)&entradas[0];//Arreglar el pseudopuntero THIS
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


pseudopointers3.cpp
Código (cpp) [Seleccionar]

//
// By 85
// elhacker.net
// etalking.com.ar
// boyscout_arg@hotmail.com
// 2013
//

/////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <typeinfo>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Vamos a usar una estructura para asegurarnos de que los 10 enteros
// sean almacenados de forma contigua.
struct Entradas{
int a,b,c,d,e,f,g,h,i,j;
};

static struct Entradas entradas;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Test3(){

#define XPOINTERTYPE unsigned long
#define XVARTYPE int
//if(sizeof(XVARTYPE) != sizeof(entradas.a)) return;
unsigned char OFFS = (unsigned char)sizeof(XVARTYPE);// Up to 255
XPOINTERTYPE entradaX=(XPOINTERTYPE)&entradas.a;// Una especie de puntero THIS
XPOINTERTYPE inicio_bloque=(XPOINTERTYPE)&entradas.a;
XPOINTERTYPE fin_bloque=(XPOINTERTYPE)&entradas.j;
int rep = 0;
const int MAX_NUMB =10;
char* format;
if(!strcmp(typeid(XVARTYPE).name(), "int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) format="%X";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) format="%d";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) format="%f";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) format="%f";
else return;

for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un número\n");
scanf(format,(XPOINTERTYPE*)entradaX);

rep=0;
XPOINTERTYPE apuntador1=(XPOINTERTYPE)&entradaX;//Doble puntero

for(XPOINTERTYPE j=inicio_bloque;j<(inicio_bloque+(OFFS*i));j+=OFFS)
{
XPOINTERTYPE apuntador2=(XPOINTERTYPE)&j;//Doble puntero

if(**(XVARTYPE**)apuntador1 == **(XVARTYPE**)apuntador2){
rep++;
}
}

if(rep)
{
char* info;
if(!strcmp(typeid(XVARTYPE).name(), "int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long long")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned long")) info="%X had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned int")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "unsigned short")) info="%d had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "float")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "double long")) info="%f had %d repetitions\n";
else if(!strcmp(typeid(XVARTYPE).name(), "long double")) info="%f had %d repetitions\n";
printf(info,**(XVARTYPE**)apuntador1,rep);
//while(getchar()!='\n');
system("pause");
}

entradaX+=OFFS;
}
entradaX=(XPOINTERTYPE)&entradas.a;//Arreglar el pseudopuntero THIS

for(int k=1;k<=MAX_NUMB;k++)
{
printf(format,*(XVARTYPE*)entradaX);

entradaX+=OFFS;
}
printf("\n");
entradaX=(XPOINTERTYPE)&entradas.a;//Arreglar el pseudopuntero THIS
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


--------------------------------------------------------------------------
EXPLICACIÓN ANTERIOR
--------------------------------
Explico algunas cosas:

Considerando las 10 variables como un bloque de memoria de 10 * 4 BYTES, vamos a guardar la dirección de memoria de comienzo de bloque y la de fin.
Código (cpp) [Seleccionar]
int inicio_bloque=(int)&entrada1;
int fin_bloque=(int)&entrada10;


Esta variable guarda la dirección de memoria de la primer variable que
guarda el primer número. Esta variable es como un puntero THIS por así
decirlo, porque se desplaza a lo largo del bloque de 10 variables,
es decir va cambiando su valor al de la dirección de cualquier de las
10 variables enteras. Por lo tanto no tengo drama en llamarla "pseudopuntero" THIS XD.
Código (cpp) [Seleccionar]
int entradaX=(int)&entrada1;

Para ingresar 10 números hacemos 10 ciclos, pero el scanf guarda el dato
en la dirección contenida en la variable entradaX. Noten el 'casting', para
que scanf sepa que se trata de un puntero.
Código (cpp) [Seleccionar]
for(int i=0;i<MAX_NUMB;i++)
{
printf("Introduzca un numero\n");
scanf("%d",(int*)entradaX);
       ...
}


Citando esta parte, es donde se hace la comparación de cada ingreso contra todos los números ingresados hasta el momento.
Nótese que se utiliza una variable local llamada 'apuntador1' que en realidad hace de doble puntero o puntero a puntero, porque guarda la dirección de otra variable que al mismo tiempo guarda otra dirección de memoria. Por eso para acceder al valor final (un número) se utiliza la notación de doble puntero. En lo que respecta al FOR, como dijimos que son 10 enteros de 4 BYTES cada uno, entonces el FOR cuenta de a 4 BYTES para realizar 10 ciclos.
Código (cpp) [Seleccionar]
...
int apuntador1=(int)&entradaX;//Doble puntero
for(int j=inicio_bloque;j<(inicio_bloque+(0x4*i));j+=0x4)
{
int apuntador2=(int)&j;//Doble puntero

if(**(int**)apuntador1 == **(int**)apuntador2){
c++;
}
}

...


También se incrementa la variable entradaX o pseudopuntero THIS,
que apunta al último número o al número actual.
Eso se logra incrementándola en el FOR

Código (cpp) [Seleccionar]
entradaX+=0x4;

El tema es que esta variable se reutiliza, por lo cual se debe arreglar su
dirección para que siempre apunte a la primer variable entera.

Código (cpp) [Seleccionar]
entradaX=(int)&entrada1;

Inclusive todo esto tiene cierta analogía con el puntero THIS.
Pero quiero aclarar que no es el puntero THIS, es una comparación solamente por eso se le dijo "PSEUDO"

Para listar lo mismo, se le pase a printf el contenido del pseudopuntero.
Código (cpp) [Seleccionar]
for(int i=1;i<=MAX_NUMB;i++)
{
printf("%d\n",*(int*)entradaX);

entradaX+=0x4;
}


Si por casualidad les parece que mi publicación es una bldez, sepan que entiendo que no estoy descubriendo América, pero está claro que existen las variables de tipo puntero para hacer algo como esto, y no es normal hacerlo con variables comunes, por eso.

CODE:
http://www.mediafire.com/?q3l5yqplduxpfi6

Salu2
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/