elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Entrar al Canal Oficial Telegram de elhacker.net


  Mostrar Temas
Páginas: [1]
1  Programación / Programación C/C++ / [C++][?] Qt: un par de dudas en: 30 Noviembre 2010, 00:21 am
Tengo algunas dudas sobre Qt y después de buscar y buscar y mirar ejemplos no encontré nada que se adaptara y decidí, como último recurso, preguntar acá:

  • Estoy utilizando el Qt Creator y declaro algunas funciones de la API de Windows y, como consecuencia me dice que tengo que utilizar o bien la versión ANSI o la versión Unicode de estas funciones. Me gustaría poder prescindir de esta A/W y no sé cómo configurarlo.
  • ¿Me podrían explicar o pasar algún ejemplo o enlace de cómo hacer nuevas ventanas, por ejemplo al pulsar un botón?

Eso es todo. Muchas gracias por adelantado.
2  Programación / Programación C/C++ / [KERNEL MODE][?] No puedo incluir ntddk en: 16 Julio 2010, 21:11 pm
Buenas, estoy empezando a programar en Kernel Mode y, tengo ya descargado y configurado el compilador del DDK sin Visual Studio 2008. El caso es que quería probar como configurarlo para Visual Studio 2008. Seguí todos los pasos y, también he enlazado la librería ntddk. Cuando compilo me dice que no existe esta librería y, también lo probé de hacerlo con pragma aunque es lo mismo :-\

¿Alguna sugerencia?

Muchas gracias y saludos :P
3  Programación / Programación C/C++ / [C++] Iniciación al manejo de los punteros en: 10 Julio 2010, 00:04 am
INICIACIÓN AL MANEJO DE LOS PUNTEROS



INTRODUCCIÓN

Debido al miedo general que provocan los punteros y, la mala información y explicación en la mayoría de talleres que corren por Internet e incluso en algunos libros, me dispongo a crear este pequeño texto intentando explicarlos lo mejor que pueda ya que cuesta mucho encontrar información decente.



MANEJANDO LOS PUNTEROS

¿Qué es un puntero? Un puntero es una variable que hace referencia a una dirección de memoria, como puede ser 0x000F212A, en hexadecimal. Un ejemplo es:

Código
  1. int a; //Declaración de una variable entera
  2. int *ptr; //Declaración de un puntero

Pero es mejor así:

Código
  1. int a = 0; //Declaración de una variable entera
  2. int *ptr = NULL; //Declaración de un puntero

Otros ejemplos:

Código
  1. char a = 0; //Declaración de una variable de caracteres
  2. char *ptr = NULL; //Declaración de un puntero

Ya hemos visto la declaración de una variable normal y la de un puntero, pero nos preguntamos, ¿y por qué de la segunda manera? Al hacer esto, inicializamos las variables con un valor predeterminado en cambio de la primera forma las variables tienen un valor indeterminado y pueden contener, como llamamos en programación, basura. Recordemos que NULL es una constante declarada en los archivos de cabecera estándar y su valor es 0 o 0x00000000.

Antes de continuar, aclaremos dudas. Hemos visto que un puntero almacena una dirección de memoria como 0x000F212A o NULL y, también hemos dicho que si no sabemos a qué apuntar le asignamos NULL, pero claro, tener una dirección inválida es una estupidez, pero si hacemos por ejemplo:

Código
  1. a = 1;
  2. ptr = &a;

El operador "&" obtiene la dirección de memoria de una variable cuando se aplica a esta. Por lo tanto:

a = 1 => 0x000F212A (imaginemos que tiene esta dirección de memoria).
ptr = &a => 0x000F212A (consecuentemente, aplicando este operador obtenemos la misma dirección de memoria).

Podríamos decir que ptr "apunta a" a. Ahora, para comprobar lo que acabamos de hacer:

Código
  1. std::cout << "a= " << a << std::endl;
  2. std::cout << "ptr= " << *ptr << std::endl;

Lo que nos mostrará en pantalla será:

Código:
a= 1
ptr= 1

Vemos que sale lo mismo. El operador "*" aplicado a una variable de puntero obtiene el valor almacenado en una dirección de memoria indicada por este. Y además, podemos hacer lo siguiente:

Código
  1. *ptr = 2;

Estamos haciendo que el contenido apuntado por ptr almacene ahora: 2. O sea, como ptr apunta a a, es como hacer:

Código
  1. a = 2;

Luego, si hacemos:

Código
  1. std::cout << "a= " << a << std::endl;
  2. std::cout << "ptr= " << *ptr << std::endl;

Lo que nos mostrará ahora en pantalla es:

Código:
a= 2
ptr= 2



ARREGLOS Y PUNTEROS

Un ejemplo de arreglo sería:

Código
  1. int x[4] = {11, 12, 13, 14};

Para este arreglo se le asigna una memoria contigua de la siguiente manera:



A x se le asigna la dirección de memoria del primer elemento del arreglo, en este caso: 11. Ahora vamos a crear un puntero al arreglo y a enseñar lo que pasa, jugando con el puntero:

Código
  1. int *ptr = NULL;
  2. ptr = x;
  3.  
  4. std::cout << *ptr << std::endl;
  5. ptr++;
  6.  
  7. std::cout << *ptr << std::endl;
  8. ptr++;
  9.  
  10. std::cout << *ptr << std::endl;
  11. ptr++;
  12.  
  13. std::cout << *ptr << std::endl;

Lo que nos mostrará en pantalla será:

Código:
11
12
13
14

Antes de empezar, una cosa importante: para que un puntero apunte a un arreglo, no hace falta que tenga el operador "&", ya que un arreglo es un puntero constante y por la misma razón no se puede tampoco incrementar un arreglo.

Bien, ptr apunta al primer elemento del arreglo, en el cual su dirección de memoria es 0x0012FF60. Lo mostramos por pantalla y, lógicamente como hemos puesto el operador "*" antes de ptr nos saldrá el contenido almacenado en esta posición de memoria: 11. Seguidamente, hacemos un postincremento al puntero, por lo tanto aumentará la dirección de memoria y apuntará al segundo elemento del arreglo; la dirección de memoria será 0X0012FF64, recordemos que un entero ocupa 4 bytes. Luego mostramos el contenido de esta dirección de memoria: 12. Hacemos esto hasta llegar al último elemento.



MEMORIA DINÁMICA

Comprendiendo todo lo explicado hasta ahora nos sirve para comprender el funcionamiento y las características más básicas de los punteros, ahora bien, entrando en el sector de la memoria dinámica, profundizamos y obtenemos una mayor potencia de estos mismos. Recordemos que se crea un puntero de la siguiente manera:

Código
  1. int *ptr = NULL;

Recordemos también, que al hacer esto el puntero apunta a una dirección inválida de memoria por lo que hacer:

Código
  1. *ptr = 1;

Sería inválido. Si queremos reservar memora exclusivamente para que nuestro puntero apunte a algo lo hacemos con el operador new. Por ejemplo:

Código
  1. int *ptr = new int;

Con el operador new reservamos memoria dinámica y, se le pasa como operando el tipo de variable a reservar. Luego de esto, se retorna la dirección de esta memoria reservada, por lo que necesitamos obligatoriamente un puntero para acceder a esta memoria.

Pero, al igual que reservamos memoria dinámica, también la podemos borrar o destruir. Y es obligatorio borrar toda esta memoria reservada ya que si no podemos ocasionar un agotamiento de memoria. Por ejemplo:

Código
  1. int *ptr = new int;
  2. delete ptr;

Reservamos memoria exclusivamente para el puntero con el operador new y, la eliminamos al final con el operador delete (el nombre del puntero es el que debe acompañar a delete).



ARREGLOS DINÁMICOS

Ya hemos visto el funcionamiento de la memoria dinámica y cómo utilizarla pero, aún podemos sacarle más jugo al tema. La aplicaremos a los arreglos. Un ejemplo de arreglo utilizando dinámico:

Código
  1. int *ptr = new int[5];

En este caso, reservamos cinco celdas consecutivas, o sea un arreglo y, cada de una de ellas tiene la memoria de un entero, 4 bytes.

Código
  1. for(int n = 0; n < 5; n++) std::cout << ptr[n] << std::endl;

Así ya accedemos a los elementos del arreglo.

La ventaja de utilizar arreglos dinámicos es que puedes establecer su tamaño en tiempo de ejecución, justo al contrario que los arreglos normales. Para establecer el tamaño de un arreglo dinámico, se puede hacer por ejemplo:

Código
  1. int n = 0;
  2.  
  3. std::cin >> n;
  4.  
  5. int *ptr = new int[n];

De la misma forma que se puede eliminar la memoria dinámica normal, también se puede eliminar los arreglos dinámicos. Un ejemplo sería:

Código
  1. int *ptr = new int[5];
  2. delete[] ptr;

La única diferencia con el delete de antes es que sólo se le añaden estos signos "[]" después del delete.



DESPEDIDA

Aquí termina este escrito y, espero que me haya explicado bien y que os haya servido para comprender un poquito más los punteros. Podéis contactar conmigo para cualquier duda que tengáis o simplemente, comentarlo acá.

Saludos :P
4  Programación / Programación C/C++ / [C++][?] Error en ReadConsole() en: 18 Junio 2010, 22:36 pm
Bueno, tengo este código que compila perfectamente y no crashea, pero siempre me termina al MessageBox() de error:

Código
  1. #include <windows.h>
  2.  
  3. int main()
  4. {
  5.        HANDLE hHeap = GetProcessHeap();
  6.  
  7.        LPSTR lpBuffer = "Escribe la ruta del fichero: ";
  8.        WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, lstrlen(lpBuffer), 0, 0);
  9.  
  10.        LPSTR lpFileName = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
  11.        DWORD nNumberOfCharsRead = 0;
  12. ReadConsole(GetStdHandle(STD_INPUT_HANDLE), lpFileName, &nNumberOfCharsRead, 0, 0);
  13.  
  14. HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  15.  
  16. if(hFile == INVALID_HANDLE_VALUE) MessageBox(0, "Error", "Error", 0);
  17.  
  18. else MessageBox(0, "Funciona", "Funciona", 0);
  19.  
  20. return 0;
  21. }

El caso es que al escribir la ruta del fichero, me dice error aunque exista. ¿Alguna solución? Seguramente se tiene que recurrir al debuggeo pero aun no sé.

Muchas gracias y saludos :P
Páginas: [1]
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines