Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - elgilun

#1
Hola MAFUS;

Una de la diferencias que señalo en mi respuesta anterior se refiere al comportamiento frente a la
lectura de un miembro de la union que no haya sido el más recientemente escrito.

Mientras que para el C es de comportamiento definido por la implementación ("implementation defined"), para el C++ es de comportamiento indefinido ("undefined behavior").

Esto es, para el caso del C, es una cuestión práctica; para el caso del C++ es una cuestión moral:


  • En C puedes hacerlo, el lenguaje no lo prohíbe, sólo que el resultado dependerá del compilador (simplemente no es portable).

  • En C++ no debes hacerlo, el lenguaje lo prohíbe, el resultado es indefinido, puede suceder cualquier cosa, casi siempre mala.


#2
Ya que en la pregunta está especificado que se trata de C++, conviene decir que hay diferencias importantes entre C y C++.

Una union en C++ siempre tiene un miembro activo, que es el último que se ha escrito, y tratar de leer un miembro que no sea el activo está calificado como "UB" (undefined behavior). Puede ser que algún compilador en particular lo implemente como una extensión al lenguaje, pero eso ya es otro cuento.

En el ejemplo:

#include <cstdio>

union por_partes {
    int entero;
    unsigned char trozo[sizeof(int)];
};

int main()
{
    por_partes mi_numero;

    mi_numero.entero = 4789432;  // el miembro activo es "entero"

    // puede ser que algún compilador lo acepte como una
    // extención al lenguaje, pero para el C++
    // tratar de leer un miembro que no sea el activo es
    // UB - "undefined behavior"
    printf("%X\n", mi_numero.trozo[0]);  // UNDEFINED BEHAVIOR

    mi_numero.trozo[0] = 128;
    // ahora el miembro activo es "trozo", y pretender leer
    // "entero" sería otra vez UB.

}


Otra diferencia importante es que el C++ permite funciones miembro de una union, incluidos constructores y un destructor.

También, una union puede tener miembros que sean clases, con o sin constructores o destructores definidos por el usuario, en ese caso habrá que instanciar al miembro activo usando placement new e invocar a su destructor antes de cambiar de miembro activo.

Otra diferencia importante es la forma de inicialización. En C se puede hacer
por_partes un_numero = {.numero=128};
pero hay que esperar al C++20 para hacer lo mismo en C++.
#3
Programación C/C++ / Re: Programa de divisas
8 Noviembre 2018, 22:26 PM
Puedo comentarte un par de cosas que veo.

1) Deberías poder usar un debugger, que es una herramienta (normalmente disponible desde el mismo editor de código o IDE). Usando un debugger podrás poner "puntos de parada", o como se llamen en tu pueblo, y seguir el flujo de ejecución del código, paso a paso, con lo que podrás ver claramente qué es lo que hace que el programa se comporte como se comporta. Debugger, todo el mundo los usa. No puedes llamarte programador si no los usas. No hay excusas.

2)
Citar#include <iostream>
#include<stdlib.h>
O tu programa es C++ (<iostream>) o es C (<stdlib.h>); no puede ser las dos cosas. No puede, no, nunca. ¿Te han dicho que no sé qué sobre C/C++? Bueno, no, es mentira, o C o C++, decídete.

3)
Citar/*USD= 7.72, EUR= 8.80, CAD= 5.89, GBP= 10.03, CHF= 7.71, AUD=5.58 , NZD= 5.13*/
Si tienes estas cosas ya definidas desde el principio, podrías declararlos como macros (lenguaje C) o como constantes (C++), pero recuerda decidirte primero si tu programa va a ser C o C++.

4) defines primero
Citardouble moneda[7]
y luego usas mon[0], mon[1], ... ? (¿necesitas una secretaria para esas tareas menores?)

5) if ... else if... else if... else... con pruebas de condición sobre enteros, debes usar switch / case.

Creo que ya corrigiendo estas cositas ya quedará.
#4
Acá se reserva memoria para la cadena de entrada y para el array de números (ints)

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

#define N 32 /* supone hasta 32 dígitos para cada número */

int main()
{
    int size;    /* cantidad de números a ingresar */
    char *nums;  /* cadena de texto con los números de entrada */
    int *arr;    /* array de char* para la serie de números resultante */
    char *p;     /* referencia para strtok */
    int i;       /* índice del array */

    scanf("%d ", &size);

    nums = (char*)malloc(N * size); /* cada numero podría ser de N-1 dígitos */
    fgets(nums, N*size, stdin);

    arr = (int*)malloc(size * sizeof(int)); /* espacio para size ints */


    i = 0;
    p = strtok(nums, " ");
    while (p != NULL) {
        arr[i] = atoi(p); /* guarda cada número como int */
        i++;
        p = strtok (NULL, " ");
    }


    /* muestra el array */
    for(i = 0; i<size; ++i) {
        printf("%d) %d\n", i, arr[i]);
    }
    free (arr); /* liberar la memoria del array */
    free(nums); /* y libera la memoria de la cadena de entrada */

    return 0;
}

#5
Codeblocks no es un compilador, es un editor para código que usa un compilador.

Deberías poder actualizar tu compilador (un gcc 8, por ejemplo) y verificar que en las propiedades de tu proyecto se incluya la opción "-std=c++1z" o "-std=c++17".

Suerte
#6
<filesystem> es estándar C++, es como usar cout o cin, nada más portable.
#7
Desde C++17 está disponible la librería <filesystem> o para algún estándar anterior está también boost::filesystem

Se puede usar directamente file_size()

#include <filesystem>

uintmax_t getFileSize(const std::string& fileName)
{
    return std::filesystem::file_size(fileName);
}

#9
Programación C/C++ / Re: como ofuscar código
28 Octubre 2018, 17:46 PM
Tu sistema debería tener en cuenta a qué tipo de "cracker" quieres frustrar. Un programa siempre puede crackearse; si vale la pena, tus claves se leerán.

Muchas veces ni siquiera es necesario leer ni descifrar ninguna clave, sólo tocando un "if" para que la condición sea siempre "true" ya queda resuelto (o provocando un salto que pase de largo de cualquier comprobación).

En términos prácticos, lo que me parece más razonable es dedicar la cantidad de energía "protectora" necesaria para dejar fuera a la mayor cantidad de parásitos.

Puedes verlo como una pirámide, donde abajo está la masa inocente que ni siquiera lo intentaría; después, a medida que subes, te encontrarás con los que intentarán algo y desistirán prontamente; luego los que googlearán con algo más de criterio y malicia; y así subiendo hasta los niveles en que "si vale la pena, se hará". Prevenir el primer escalón es gratis, por el segundo algo hay que pagar, ... y el precio sube en forma exponencial hacia la punta, en que para simples como nosotros se vuelve infinito (No dejes de tener en cuenta el nivel de las otras preguntas y respuestas :).

Después de aclara lo que me parecía moralmente necesario... Hay varios sistemas más o menos prácticos que apuntan a distintos escalones de esa pirámide:

El primero consiste en "jamás poner las claves sin transformar en el código".

Otro: "nunca depender de un puto if".

Y así, lo que google y tu imaginación te dicten.

Conozco un sistema razonable, que deja fuera a una buena proporción de esa pirámide sin un esfuerzo monumental, que consiste en generar un hash del programa compilado y guardar ese mismo hash en el programa. De este modo tu programa puede chequearse a sí mismo y si detecta que fue modificado, bueno, tú sabrás.

La dificultad consiste en guardar ese hash en un espacio predeterminado del ejecutable e ir iterando las compilaciones hasta obtener un ejecutable con el mismo hash que se haya integrado. No es fácil pero tampoco es un proceso eterno, con criterio, práctica y un buen procesador (refrigerado) en unos días lo tienes.

Suerte, y no nos cuentes.

#10
CitarMmm, comparar printf con cout es trampa
No, usando el objeto cout es la forma habitual "C++" de escribir una cadena de texto en la salida estándar.

Pero no quisiera centrar una discusión en un ejemplo elemental, la idea expresada en mi respuesta usa un "Hola Mundo" como ejemplo de las enormes diferencias entre un programa elemental escrito en C++ y otro escrito en C.

De todos modos, si quieres usar printf en C++ debes tener en cuenta que las cabeceras del C fueron declaradas obsoletas (deprecated) ya en el estándar C++98, lo que quiere decir que nadie debería escribir código nuevo como lo haces tú.

Sí es posible respetando el estándar C++ pero haciendo:
#include <cstdio>

int main()
{
std::printf("Hola Mundo!");
}



(Y ah, por cierto, el sitio que pones como referencia es sin duda uno de los más destacados y donde se ha puesto mucho y buen esfuerzo, pero es famoso también por la gran cantidad de errores que contiene. Fíjate, en este caso, dice que la cabecera de printf es <cstdio> pero en el ejemplo --que tú copias -- usa <stdio.h>. Lástima, ¿verdad?)