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

 

 


Tema destacado: Rompecabezas de Bitcoin, Medio millón USD en premios


  Mostrar Mensajes
Páginas: 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 ... 161
111  Programación / Programación C/C++ / Re: Leer un string con memoria dinámica ? en: 17 Julio 2021, 23:56 pm
C separa la memoria en diferentes secciones para un programa. Está la pila (stack), el montón (heap), variables locales y estáticas, sólo lectura y memoria de programa. Las variables locales y los arrays (dentro de las funciones) van a la stack y de eso se encarga C de adquirir y liberar la memoria.
De hecho una vez compilado las variables de este tipo no existen: todo son operaciones con aritmética de punteros sobre el registro Base Pointer y por eso no se puede liberar memoria con free.

La que sí debes liberar es la memoria dinámica, que se guarda en el montón (heap). Lo único que hace allí C es adquirir tantos bytes como le has pedido, además de una cierta metainformación, y guarda en una tabla interna todo esto y te devuelve la dirección de memoria del inicio de memoria. Lo único que hará es mantener desde el inicio tantos bytes como lo has solicitado para que otra petición de memoria del montón no la pise. C no quiere saber nada más: si la pierdes, si la sobreescribes, lo que sea, C va a mantener esa memoria como 'ocupada' hasta que la liberes. Y por eso la memoria del montón sí debe ser liberada: le debes decir a C que elimine esa entrada de la tabla porque él no sabe, ni le importa, qué estás haciendo con ella.
112  Programación / Programación C/C++ / Re: Punteros en c++ en: 30 Mayo 2021, 11:20 am
Entiendo tu postura de dejar las cosas lo más sencillas posibles, pero tal vez esa sencillez no sea suficiente. Estarás de acuerdo conmigo que el problema del entendimiento de los punteros es recurrente en todo el que ha estudiado este lenguaje. Yo, por mi parte, hasta que no vi a los punteros de esa forma no llegué a comprenderlos del todo y por eso, creo yo, que deberían enseñarse de esa forma.

Es cierto que el programa donde se asigna una constante como dirección de memoria no le va a funcionar. Pero sirve de ejemplo para mostrar que ocurre por debajo, y de ahí la construcción progresiva hasta llegar al puntero que recoge una dirección de una variable; es decir, es para que vaya viendo el proceso natural de lo que ocurre en la máquina.

O tal vez es que por mi curiosidad me gusta saber esas cosas.

Tienes razón, tal vez no se dedique a hacer firmwares, pero quien sabe si un estudiante de electrónica si ve este post y está interesado en saber cómo funcionan los punteros en C++. Siempre intento dar las respuestas pensando en un amplio espectro de gente que pueda leerla.

Y si, tienes razón, el esquema de memoria variará de arquitectura a arquitectura y por ende el de las llamadas a funciones. Pero también es un punto a tener en cuenta.
113  Programación / Programación C/C++ / Re: Punteros en c++ en: 29 Mayo 2021, 18:00 pm
Sí, pero para entender una cosa realmente es mejor empezar desde los cimientos y los cimientos, en punteros, son que es un número que representa una dirección de memoria. Y de ahí para arriba. Estarás de acuerdo conmigo que realmente no se puede entender C sin entender el esquema de memoria. Al menos eso me sirvió a mi: entonces todo fue más fácil. Eso y la traducción a ensamblador de la convención de llamadas a funciones, para entender las variables automáticas.



Supongo que no será el caso de mucha gente que visite el foro pero este lenguaje es muy habitual verlo en microcontroladores y aquí se mapean en memoria muchos registros de configuración y los puertos E/S. En PC usar constantes para acceder a memoria no es útil, pero en el mundo del firmware es la norma.
114  Programación / Programación C/C++ / Re: Punteros en c++ en: 29 Mayo 2021, 12:55 pm
Puntero a lo easy.

Un puntero es un número (cómo todo dentro de un ordenador) y ese número representa una dirección de memoria.

Por ejemplo:
Código
  1. #include <stdio.h>
  2.  
  3. int main() {
  4.    printf("%d", *(int*)0x61FE1C);
  5. }

En el ejemplo anterior directamente le digo a C que me muestre qué hay en la dirección de memoria 61FE1C. ¿Se puede? Sí. Por cierto, ese casting (int*) es necesario para convertir el literal en un puntero. El * que hay delante nos muestra el contenido.

* Un poco más avanzado: En este caso he hecho un programa previo para ver dónde residía la memoria de datos del programa y pudiera apuntar ahí con este ejemplo. Los sistemas operativos actuales y los microprocesadores funcionan por capas. No van a dejar que un programa de usuario pueda leer o escribir fuera de su área designada. Antes sí que se podía, o en sistemas sin protección sí puede hacerse.

Podemos usar una variable para alojar esa dirección de memoria del ejemplo anterior:
Código
  1. #include <stdio.h>
  2.  
  3. int main() {
  4.    int *p = (int*)0x61FE1C;
  5.    printf("%d", *p);
  6. }

Aquí asignamos el literal a una variable puntero. Las variables puntero se denotan por anteponer el asterisco (*) delante del nombre durante su definición o declaración. Para ver la definición y declaración por separado sería así:

Código
  1. #include <stdio.h>
  2.  
  3. int main() {
  4.    int *p;
  5.    p = (int*)0x61FE1C;
  6.    printf("%d", *p);
  7. }

Nótese que cuándo se hace la definición (se le da valor) no se usa el asterisco (*), pues éste tiene la función, en sus posteriores usos, de conseguir el valor guardado en esa posición de memoria, que en este caso es la posición 0x61FE1C.

Pero cómo hemos dicho el conjunto sistema operativo/microprocesador no te deja apuntar a zonas arbitrarias de la memoria, el sistema te la tiene que dar y ahí es cuando entra C que es quien negocia con el sistema para conseguir memoria libre; nosotros no debemos preocuparnos por nada de eso (afortunadamente). Por tanto cuando haces

Código:
int n;

C se encarga de reclamar una zona de memoria donde cabe un entero y el sistema se la otorga. ¿Cuál? La verdad es que no nos importa. Ídem para

Código:
int *n = malloc(sizeof(int));

Hace lo mismo: pide al sistema una zona de memoria dónde quepa un entero y éste, si tiene, nos la da.

* Un poco más avanzado: la memoria de un programa en C está dividida en sectores que son la memoria de programa, la memoria de la pila y la memoria del montón (heap). Hay más. La pila es donde caen las variables normales como int, char, double, arrays, structs, etcétera y es C el encargado de manejarlas. En el montón van a parar los malloc, calloc y toda esa família; C no entra ahí y es el propio programador el encargado de comprobar que se ha tomado memoria, de liberarla para futuros usos demás menesteres de administración.

Lo normal de un puntero es recibir la dirección de memoria de otra variable:
Código:
int n;
int *p = &n

El ampersand (&) es un operador que (en este caso) dice 'La dirección de'.

También es muy importante de los punteros el tipo de dato al que apuntan. Has visto en todos estos ejemplos cómo siempre han sido a entero (int *), pero pueden ser de cualquier tipo de dato: char *, double *, struct mi_estructura *, etcétera. Esto es debido  a que los diferentes tipos de datos ocupan tamaños en bytes diferentes en memoria y el compilador necesita saber cuánto ocupa para recuperarlo o para guardar algo en él. Por ejemplo un char suele ser de 1 byte y un entero de 4 bytes. Si los punteros no especificaran el tamaño con su tipo podríamos guardar un número muy grande en una posición dónde se guarda un char machacando datos vecinos: intentaríamos guardar 4 bytes dónde sólo cabe 1.

Y bueno, esto es lo básico de los punteros. Hay más cosas: punteros como argumentos en funciones y porqué usarlos; similitudes y diferencias entre punteros y arrays; punteros a funciones (sí, también se pueden apuntar a funciones); punteros a punteros (por loco que parezca muchas veces son necesarios). Pero eso ya para más adelante. Ahora intenta comprender sus bases.
115  Programación / Programación C/C++ / Re: Caracteres chinos ? en: 13 Mayo 2021, 07:54 am
Tendrás que instalar ese juego de caracteres en el ordenador, después cambiar el locale en el código y en la consola. O buscar una librería que te permita usar UTF, pero recuerda tambien cambiar la consola a UTF.
116  Programación / Programación C/C++ / Re: Necesito ayuda para que el programa pueda eliminar números repetidos en: 6 Mayo 2021, 14:05 pm
La siguiente función debe usarse sobre un array ya ordenado.
array contiene el array ordenado
tam contiene el número de elementos de dicho array

Cuando la función ha terminado

array contiene los elementos sin duplicar en su parte más baja
tam marca el índice más alto a partir del cual los datos son inválidos. Indica el nuevo tamaño del array.

El código es en C:

Código
  1. void array_eliminar_duplicados(int array[], size_t *tam) {
  2.    size_t k = *tam;
  3.    for(int i=0, j=1; j<k; ++i, ++j) {
  4.        if(array[i] >= array[j]) {
  5.            --*tam;
  6.            while(array[i] >= array[j] && j<k) {
  7.                ++j;
  8.            }
  9.        }
  10.        array[i+1] = array[j];
  11.    }
  12. }
117  Programación / Programación C/C++ / Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa en: 30 Abril 2021, 13:12 pm
Sigues teniendo muchos fallos lógicos, por ejemplo:

Línea 98, falta '&&especiales' en la condición de continuación
Código:
for (int i=0; i<strlen(CARACTERES_ESPECIALES) && especiales; i++)

Línea 109, usas *argv[1] cómo valor para dimensionar el un array dinámico. Está mal porque ves el entero que representa el primer carácter de la cadena argv[1], no el entero que debería ser. Habíamos dicho que quien guardaba el tamaño de la contraseña era la variable longitud_clave
Código:
char*clave = (char*)malloc((longitud_clave+1)*sizeof(char));

Algo parecido lo anterior en la línea 110, 120 y 130.

Línea 114, usas argc en vez de i para poner el carácter nulo. Tendrás que trabajar en ello porque i, tal y como está, no puede verse fuera del bucle. Tienes una solución a un bucle anterior en el que usas 'index'.

Ya con esto tienes unas pautas para seguir arreglando el código.
[code]clave[i] = 0;
[/code]
118  Programación / Programación C/C++ / Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa en: 29 Abril 2021, 21:06 pm
Es por la línea 103:
Código:
for( int i=0; i<argc; i++){
Lo que haces es usar argc en vez del valor conseguido por argv[1]
119  Programación / Programación C/C++ / Re: [C][isdigit] Pequeña cuestión función isdigit en mi programa en: 29 Abril 2021, 20:05 pm
Muy buenas. Prueba el siguiente código, he añadido unas líneas para controlar que los parámetros son más de uno:

Código
  1. // Comprobamos que existe más de un parámetro (el nombre) en la línea de comandos
  2. if(argc < 3) {
  3.    fprintf(stderr, "%s\n", "Debe introducir la longitud de la clave...");
  4.    exit(EXIT_FAILURE);
  5. }
  6.  
  7. /*El 1º parámetro siempre va a ser la longitud de la clave*/
  8. if(sscanf(argv[1], "%u", &longitud_clave) == 0) {
  9.    fprintf(stderr, "%s\n", "El primer parámetro debe ser un entero. Indica la longitud de la clave...");
  10.    exit(EXIT_FAILURE);
  11. }
  12.  
120  Programación / Programación C/C++ / Re: Problema con comparar cadenas en: 29 Abril 2021, 11:03 am
En según qué construcciones a mi me gusta usar la función fseek después de un scanf:

Código
  1. #include <stdio.h>
  2.  
  3. int main() {
  4.    char str[1024];
  5.    printf("> ");
  6.    scanf("%1024[^\n]", str);
  7.    printf("%s\n", str);
  8.  
  9.    fseek(stdin, 0, SEEK_END);
  10.  
  11.    puts("");
  12.    printf("> ");
  13.    scanf("%1024[^\n]", str);
  14.    printf("%s\n", str);
  15. }

fseek lleva el puntero al final del archivo stdin, pero como es un stream lo que ocurre es que se descarta todo su contenido y queda preparado para nuevas entradas. El ejemplo anterior funciona para gcc y su contrapartida MinGW64 de Windows. Desconozco si otros compiladores aceptan esta instrucción.
Páginas: 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 ... 161
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines