Curso completo de programación con lenguaje C

joked9

Tengo una pregunta super básica, ¿con float puedes insertar un número entero o es sólo y únicamente para decimales? Porque entonces int no hace falta ¿me explico?

Gracias de antemano :psyduck:

1 respuesta
herre

#481
Puedes asignar un entero a un float pero va a ser representado en coma flotante.

La representacion en memoria de un número de coma flotante y un entero es totalmente distinta.

Lo más importante: hay números que no tienen representacion exacta en coma flotante, por lo que cargarte los enteros es una Mala Idea.

1 respuesta
joked9

#482 entonces, para que me aclare, siempre que sepa que voy a utilizar números enteros, meto un int pero si por ejemplo tengo un fscanf ¿sería mejor poner float para la variable que inserte este?

2 respuestas
herre

#483
Bueno en ese caso concreto depende: con fscanf puedes leer tanto un float como un entero.

Pero en general, si sabes que sólo vas a usar valores enteros, usa una variable de tipo entero. Las operaciones matemáticas con floats no son 100% intuitivas. (El mítico 0.1 + 0.2 != 0.3)

1 respuesta
gonya707

#484 las aritméticas no hay demasiado problema, es en las comparativas como la que has puesto donde pueden pasar cosas raras

#483 La explicación intuitiva es que en un int reservas una serie de bits y cualquier combinación de 1s y 0s será un número entero, exactamente

sin embargo float y double no son fixed point, sino en coma flotante, lo que quiere decir que es altamente posible que el número 2.00000000000 (es decir, el número entero 2) no sea posible de almacenar en esa variable, pero si haces

float f = 2;

el numero que se esta metiendo en f, en realidad es 1.99999999978, que si que es posible almacenar y que es prácticamente 2

jorge96

Buenas he estado buscando por el foro y no he encontrado nada, asi que lo pregunto aqui. Sabeis si hay un hilo similar a este pero de java? Donde aprender, preguntar dudas,etc.

1 respuesta
B

#486

Si es por 'aprender', intenta aprender otra cosa, personalmente creo que el día que google decida utilizar Go o algún otro lenguaje para android, java se muere, la máquina virtual apesta y con C# open source no va a tener nada que hacer. Aunque eso si, si es por simplemente aprender OOP la sintaxis está bien y es un buen lenguaje para quedarte con esos conceptos.

Asi que eso, si es por aprender, ve a #1 y all glory to the ANSI C xD.

1 respuesta
jorge96

#487 era básicamente por que es con lo que me toca programar en la carrera este año xD Y ver un sitio donde aprender, solucionar dudas y tal.
En cuanto a lo demás si tuvieses que elegir un lenguaje seria C? Me mola la programación y en la carrera no la tocare más, así que igual en un futuro me tenéis por aquí xD

2 respuestas
SevenOfThem

¿Este curso me serviría para entender los fundamentos del C++? Sin contar las librerías, claro está. Lo pregunto porque sé cosas de C++, pero no lo suficiente para aprobar. Porque si es así, mañana mismo me pongo con ello :psyduck:

1 respuesta
cabron

#488

No voy a contestar a lo de Java por que me parece desviar el hilo sin sentido, así que me ceñiré a C.

Como uso real, a día de hoy C 'solo' se usa para programación de bajo nivel (drivers, kernels de sistemas operativos, software empotrado), para software donde la eficiencia sea crítca y para mantener software existente escrito en C (que no es poco). Además en el mundo del software libre y linux C todavía es muy usado.

#489

Sí y no, C++ es un superconjunto de C, eso significa que tiene todo lo que tiene C y luego aparte añade más cosas. Lo que aprendas de C lo puedes usar en C++ ya que ahí también existe, pero para la programación orientada a objetos, el uso de templates y la programación funcional (que ahora también está soportada en C++) no te valdrá de nada.

1 respuesta
herre

#490 C++ no es un superset de C. http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B

Gran parte de lo que aprendas en C va a servir en C++. Pero son lenguajes distintos de paradigmas distintos y también vas a tener que aprender con cuidado cuales son sus diferencias.

2
B

#488

Nah... Si te entiendo, a mi también me está tocando java en la carrera, pero no me llama profundizar más que lo que nos dan en clase xD. Digo lo de C porque a día de hoy como comentan sigue siendo de los más utilizados, sirve para todo y incluso usando lenguajes de alto nivel, en sistemas grandes como reddit, amazon, ... Se necesita C para optimizar el rendimiento de determinadas partes del sistema. Además que me parece que para ser un buen programador tienes que saber cuando estás llenando la memoria, cuando liberarla y como funciona todo en cada momento (punteros!). Me parece que todo programador debería ser un master class en C.

No lo decía por ser un hater de java, simplemente porque para aprender OOP está bien, pero sin más, a menos que vayas a usarlo para software a gran escala y que necesite ser multiplataforma, android, ... Existen alternativas mejores para muchas cosas, no para todo.

Si tuviese que elegir un lenguaje sería C? Eso ya no se puede contestar, no hay un lenguaje 'único' mejor que el resto, cada cual vale para lo que vale, si te vas a dedicar a desarrollo web tirarás por javascript (tanto lado cliente como servidor con node.js), python, ruby on rails, ... Si te vas a dedicar a administrar sistemas shell, python o perl, si vas a programar grandes apps C#, C++ o java (espero que por poco tiempo xD), bajo nivel C, robotica LISP/Haskell, ... Hay muchas areas y cada uno tiene su fuerte.

Un saludo.

1
herre

Tengo una pregunta.

He hecho un emulador del Space Invaders, lo que involucra un emulador del Intel 8080. El procesador tiene varios registros de 8 bits que pueden accederse en parejas como si fuesen un sólo registro de 16 bits. (Por ejemplo si B = 0x12 y C = 0x34, BC = 0x1234)

Ahora que lo tengo funcionando he estado comparando el código con otros emus y he visto este truquito para acceder a los registros individualmente o en parejas fácilmente:

struct cpu {
    union {
        struct {
            uint8_t C;
            uint8_t B;
            uint8_t E;
            uint8_t D;
            uint8_t L;
            uint8_t H;
            uint8_t F;
            uint8_t A;
        };
        struct {
            uint16_t BC;
            uint16_t DE;
            uint16_t HL;
            uint16_t AF;
        };
    };
} cpu;

Así el ejemplo anterior sería:

cpu.B = 0x12;
cpu.C = 0x34;
cpu.BC  // => 0x1234

Mi pregunta es: ¿cuánto te puedes fiar de que los structs de los registros individuales y los pares vayan a estar "alineados" dentro de la union? Es decir, que el compilador vaya a colocarlos así en memoria (O de forma equivalente mientras que siga funcionando)

0x1000 C BC
0x1001 B

0x1002 E DE
0x1003 D
0x1004 ...

Tengo pendiente de leer The Lost Art of Structure Packing y todo el tema de que los structs van alineados de cierta forma en memoria me hace pensar que esto puede fallar fácilmente fuera de este caso concreto o en alguna otra arquitectura.

Ya de primeras se me ocurre que solamente sería válido en CPUs little endian.

2 respuestas
cabron

#493

http://stackoverflow.com/questions/891471/union-element-alignment

1 respuesta
herre

#494 Eso sólo garantiza el alineamiento de los structs.

Pero combinado con este párrafo del artículo que linkeo:

Storage for the basic C datatypes on an x86 or ARM processor doesn’t normally start at arbitrary byte addresses in memory. Rather, each type except char has an alignment requirement; chars can start on any byte address, but 2-byte shorts must start on an even address, 4-byte ints or floats must start on an address divisible by 4, and 8-byte longs or doubles must start on an address divisible by 8. Signed or unsigned makes no difference.

ya tengo una información más completa.

B

#493

No sé si te ayudaré, pero sin entrar a fiarte o no de las structs, a nivel de hardware los pares de registros BC, DF, HL se utilizan de forma individual para guardar datos de 8 bits, pero a pares si es necesario almacenar una dirección por lo general. Concretamente el HL, en la documentación a veces referenciado solo como M, es el que se utiliza como puntero y tiene sus instrucciones particulares, siempre que referencias a M como par o con algunas instrucciones el bit alto H (high y L de low) también te aseguraras de referenciar al par. Es decir, a nivel de procesador no es lo mismo una instrucción para asignar un dato a un registro que utilizar un par de registros como punteros o como par, las hay especificas para aumentar/decrementar/comparar el contenido de un registro o para un par, en este caso en C supongo que también habrá esa diferencia.

En resumen, no se suele hacer de forma automática la asignación, se suele hacer según tu le indiques que es un par/dirección o dato que vas a tratar, una cosa es que utilices un puntero para recorrer posiciones con datos y que a partir de x dirección tengas un dato de n bits y otra utilizar pares de registros para guardar datos de n bits, por lo menos a nivel ensamblador.

Eso si, lo de AF creo que es una 'parida' ya que lo normal es que el registro A quede libre siempre ya que es el acumulador y es el que se utiliza para el 99% de operaciones.

Espero haberte ayudado.

Un saludo!

1 respuesta
herre

#496 I know!

En realidad ya tenía hecho el emulador. Pero tenía una interfaz mucho más fea y la idea de arriba me la ha limpiado un huevo. Al final he acabado con esto:

struct cpu {
    uint8_t  ir;  // Instruction register
    uint16_t pc;  // Program counter
    uint16_t sp;  // Stack pointer
    union {
        struct {
            uint8_t c;  // general purpose registers
            uint8_t b;
            uint8_t e;
            uint8_t d;
            uint8_t l;
            uint8_t h;
            uint8_t z;  // temporary registers
            uint8_t w;
            union {
                uint8_t f;  // Status Register
                struct {
                    uint8_t cy:1;   // Carry
                    uint8_t   :1;
                    uint8_t  p:1;   // Parity
                    uint8_t   :1;
                    uint8_t ac:1;   // Auxiliary Carry
                    uint8_t  i:1;   // Interrupt
                    uint8_t  z:1;   // Zero
                    uint8_t  s:1;   // Sign
                } flags;
            };
            uint8_t a;  // Accumulator
        };
        struct {
            uint16_t bc;
            uint16_t de;
            uint16_t hl;
            uint16_t wz;
            uint16_t af;
        };
    };
}

Lo de poder acceder a los flags bits como un registro es util porque hay un par de instrucciones (PUSH PSW y POP PSW) que exan y sacan AF de la stack.

8 días después
joked9

Lección 3

Me estoy dando cuenta de lo estúpido que soy, nada me sale bien ._.

1 respuesta
gonya707

#498 no desesperes hombre :) si hay algo que no entiendes estare(mos) encantados de ayudar

1 respuesta
B

#499 estare(mos)

1 respuesta
gonya707

#500 si, es que muchas veces estoy escribiendo y se me adelantan (╯°□°)╯︵ ┻━┻

1
joked9

joer gracias tios, tengo una pregunta tonta. Por ejemplo, en el teorema de pitagoras, no puedo hacer

hip = sqrt(pow(2,cat1)+ pow(2,cat2));

por ejemplo para ahorrar tener que poner dos variables mas?

1 respuesta
gonya707

#502 claro, el resultado es el mismo

1 respuesta
joked9

#503 pues no me da bien no se que ocurre.

Mira

spoiler

Me he quedado ahi porque llevo rayandome media hora...

1 respuesta
herre

#504 pow(x, y) es xy

1 respuesta
joked9

#505 XDXDXD me siento muy tonto, he mirado eso como 30 veces, ya que en el ejemplo pone pow(x,y) como yx omgomg gracias herre.

herre

Si acabáis con el curso y queréis un proyecto ya importante pero asequible, os recomiendo que os créeis vuestro propio emulador de Space Invaders. Aprenderéis un huevo de pato.

Empezad en emulator101

La implementación que hacen ahí es para OS X, así que si lo hacéis para Windows o Linux tendréis que buscaros la vida. Os recomiendo SDL.

Os dejo mi emulador si queréis echarle un vistazo: https://github.com/herrecito/invaders

Si os animáis y necesitáis ayuda ya sabéis! Y si alguien quiere más info sobre como empezar también pedidlo.

1
Camp1

alguien me puede echar un cable con ficheros? quiero mostrar mi fichero linea por linea y editar el ultimo caracter de cada linea después de ser mostrada.

ejemplo: mi fichero seria el siguiente

cocacola 3
fanta 2
agua 8
cerveza 7

Y yo quiero poder editar ese caracter despues de ser mostrado por pantalla de modo que la ejecución sea tal que:

cocacola 3
introduce el nuevo numero
fanta 2
introduce el nuevo numero
agua 8
introduce el nuevo numero
cerveza 7
introduce el nuevo numero

1 respuesta
gonya707

#508 existe el modo r/w al abrir un fichero, en el que puedes tanto leer como escribir, pero no te lo recomiendo. Por sencillez el mejor método es que uses dos ficheros, uno rt y otro wt, leas el fichero que tienes y crees uno nuevo, un buffer, llamemoslo en el que vas copiando del primero y modificando las partes que quieras.

al terminar el proceso borras el fichero viejo con system() y renombras el anterior

1
joked9

me mola mucho tío tener un problema e intentar solucionarlo con código, que bonito. Me quiero poner a saco ossssssssstia. Pero lo de las decenas centenas no tengo ni idea de como empezarlo.

1 respuesta