La aritmética de punteros es la mayor magia del C. Puede que no te guste, pero para otra gente es una maravilla, y desde luego no se podría eliminar del lenguaje porque es su alma.
Sí, efectivamente es el alma del C, y así va.
No es una maravilla, lo que es una maravilla es recorrer un array por indices y que el compilador se ocupe de gestionarlo internamente por punteros. Jugar con la dirección de memoria de una variable y cuanto espacio ocupa es una operación delicada que rara vez es necesario hacer. El programador no debería perder el tiempo en saber si físicamente son direcciones contiguas o cuanto espacio ocupa, y menos aún hacerlo rutinariamente.
Lo peor de los errores con punteros es que provocan errores impredecibles (entre ellos el famoso buffer overflow), es una sobreescritura nadie sabe donde. Usando indices de arrays, daría "error te has salido", corregirías el bug y ya está. De hecho, hay buenos programas que llevan años con un bug de ese estilo. Van bien, y de vez en cuando hacen una cosa rara. Pero a ver quien lo encuentra.
Lamentable.
¿Estás seguro de que no se puede considerar como de tipado fuerte?
Segurísimo. ¿puedes asignar byte a un char sin error?. ¿Puedes asignar un puntero a un int a un puntero a un char?. ¿Puedes asignar un float a un int?
Otra cosa es que luego el lenguaje te permita hacer burradas
Casi todos los lenguajes te permiten hacer burradas...si se lo pides. La cuestión es la facilidad con que puedes hacer una burrada sin pretenderlo. En pascal, p.ejm. si quieres asignar un puntero a integer a un puntero a un fichero, no te deja. Ahora, si te empeñas porque lo consideras necesario, le fuerzas la conversión explícitamente, y ya está.
Las asignaciones de la línea if sólo están haciendo lo que tú le has dicho. Una vez asimilas que = es asignar e == es comparar no te vuelves a confundir.
Esos errores los sigo cometiendo en PHP, y lo que es peor, cuesta un huevo de pillar. No soy yo el único, en el Kernel de Linux hubo un caso de estos.
El 99.9% de los casos en una condición quieres hacer una comparación, no una asignación, por tanto, lo lógico es que la sintaxis los diferencia claramente y evite la confusión.
no recuerdo ahora cómo se hacía en otros lenguajes que no tomen la sintaxis de C.
Muy simple, asumen que siempre hay un break. Evidentemente no se puede hacer una ejecución en cascada como en C (si se cumple B, ejecuta B, si se cumple A ejecuta A y B) ¿Pero quién quiere esto? ¿cuántas veces se necesita? Es heredado del ensamblador.
Otras cuestiones Vaya por delante, que las macros, llaves y mayúsculas/minúsculas, los considero más cuestión de gustos que defectos.
Las macros es cierto que no las uso mucho,
Las macros pueden ser útiles. Pero se ha abusado de ellas. En cualquier caso hay otras alternativas, de modo que cuando ves una instrucción no te despista porque está redefinida con una macro.
Lo de las llaves perdóname pero es una tontería.
Perdonado;-)
El problema se lo veo también al pascal con begin/end. Cada estructura debería cerrarse de una manera, p.ejm. en for/next while/wend case/cend funcion/eif. Significa captar que estructura no cerrada en 5 segundos a tardar 30 segundos si se ha liado.
Lo de las mayúsculas y minúsculas tampoco es para tanto, puede dar lugar a errores.
No es que dé errores, es que me repatea no acordarme si este identificador es MiFuncionInt o MiFuncionINT o miFuncionInt o miFuncionINT.
Por el otro lado se te ha olvidado mencionar las cadenas de caracteres.. peligrosas
Sí, esa es otra.
Y poco eficiente. Para llegar al final de la cadena, te la has de recorrer de principio a fin: Para saber el tamaño de una cadena, operación bastante frecuente. Para concatenar cadenas. Por no hablar de que el ascii 0 no puede ser parte de una cadena.
Al final vuelvo a lo mismo: el C es para lo que es
El problema es que sigue utilizándose para muchas cosas, y ha pasado sus genes otros lenguajes como C++.
Lo problemas son tan antipáticos que el java, python o ruby, lenguajes interpretados lo están sustituyendo. Es lamentable que otro lenguaje compilado no se haya convertido en un estándar de facto como el C/C++.
Voy a soltar obviedades, pero el uso implícito de break te permite hacer el equivalente en pascal de:
case var of
1,2,3:...
end;
en esta forma:
switch(var) {
case 1:
case 2:
case 3:...; break;
}
Y no veo que sea algo poco frecuente.
Sobre las macros, imagino que fueron hechas para lo que se usan, ahorrar fragmentos de código, aunque me parece que pudieron habérselo currado un poco más, por ejemplo si defines una macro de esta forma:
#define ADD(a, b) a+=b
y se te ocurre llamarla en dos líneas:
ADD(a,
b);
obtendrás un lindo mensaje de error, cortesía del preprocesador. Además me sorprende que nadie haya mencionado al tratamiento de booleanos.
Aún así creo que si C han llegado al lugar donde está no ha sido cuestión de gustos, sino por ser el equilibrio perfecto entre un lenguaje que no abusa de la verborrea y la eficiencia sin tener que llegar a ensamblador, sólo diré que nadie aquí ha obligado a Larry Wall o a James Gosling a copiar su sintaxis.
Usando indices de arrays, daría "error te has salido", corregirías el bug y ya está.
Pero eso incluye la sobrecarga de hacer que el ordenador compruebe en cada acceso, además de tener que guardar el valor dentro de la estructura de datos.
Quizás el problema es que no exista una biblioteca estándar como en C++ o Java (quizás no tan extensa) que te resuelva los problemas más comunes.
Segurísimo. ¿puedes asignar byte a un char sin error?. ¿Puedes asignar un puntero a un int a un puntero a un char?. ¿Puedes asignar un float a un int?
Me pillas un poco oxidado en teoría de los lenguajes, pero yo entiendo tipado débil cuando, por ejemplo, una variable almacena distintos tipos sin problemas o puedes pasarle un int a una función que espera un float (eso seguro que no ocurre).
Las cosas que pones tienen sentido en el mundo C. En el orden que me conviene:
Al asignar un float a un int se toma la parte entera. Es como realizar una conversión.
Un byte se puede asignar a un char porque al fin y al cabo char es el nombre bonito que en C se da a los bytes. De hecho, el tipo byte creo que no forma parte del lenguaje de por sí.
Dos punteros se pueden asignar porque son del mismo tipo: el tipo puntero (dirección de memoria). El tipo del puntero sólo sirve para saber cómo tiene que hacer los incrementos. Aún con eso el compilador te saca un warning: no es un error porque estás haciendo algo válido, pero te avisa.
Lo que me lleva a una nueva concesión para ti: es una basura que no esté establecido qué tamaño tienen un short, un int, un long, etc, y dependa de la máquina y el compilador.
Si te empeñas porque lo consideras necesario, le fuerzas la conversión explícitamente, y ya está.
Si haces eso en C el compilador te suelta un warning como una catedral. Puedes ajustar el compilador para que considere errores los warnings o bien proponerte a ti mismo dejarlo todo sin warnings.
El 99.9% de los casos en una condición quieres hacer una comparación, no una asignación
No estoy de acuerdo. En C y derivados es muy común sustituir:
f = fopen("archivo", "r"); if (f!=null) { ... } else {
error("No se puede abrir el archivo");
exit(1); }
por
if (f = fopen("archivo", "r")) { ... } else {
error("No se puede abrir el archivo");
exit(1); }
Entiendo tus reticencias, yo lloré sangre en mis primeras prácticas de C por un error debido a eso mismo, pero una vez te acostumbras no ocurre. ¿Una vez en el kernel ente cuántas miles de líneas contribuídas?
Evidentemente no se puede hacer una ejecución en cascada como en C (si se cumple B, ejecuta B, si se cumple A ejecuta A y B) ¿Pero quién quiere esto? ¿cuántas veces se necesita?
No es que no tengas parte de razón, pero yo he usado esta característica varias veces.
ada estructura debería cerrarse de una manera, p.ejm. en for/next while/wend case/cend funcion/eif.
Puede, pero a mí se me antoja incómodo de leer, nunca me ha ayudado mucho esta sintaxis. Admito que debe ser por costumbre.
En este aspecto la sintaxis que me parece genial es la de python, que se hace mediante la tabulación de las sentencias, aunque con la gran pega de la confusión espacios vs tabuladores (aspecto que parece imposible de llevar bien para alguna gente).
Re:Estoy de acuerdo, pero...
(Puntos:2)( http://barrapunto.com/ | Última bitácora: Viernes, 29 Diciembre de 2017, 18:26h )
Sí, efectivamente es el alma del C, y así va.
No es una maravilla, lo que es una maravilla es recorrer un array por indices y que el compilador se ocupe de gestionarlo internamente por punteros. Jugar con la dirección de memoria de una variable y cuanto espacio ocupa es una operación delicada que rara vez es necesario hacer. El programador no debería perder el tiempo en saber si físicamente son direcciones contiguas o cuanto espacio ocupa, y menos aún hacerlo rutinariamente.
Lo peor de los errores con punteros es que provocan errores impredecibles (entre ellos el famoso buffer overflow), es una sobreescritura nadie sabe donde. Usando indices de arrays, daría "error te has salido", corregirías el bug y ya está. De hecho, hay buenos programas que llevan años con un bug de ese estilo. Van bien, y de vez en cuando hacen una cosa rara. Pero a ver quien lo encuentra.
Lamentable.
Segurísimo. ¿puedes asignar byte a un char sin error?. ¿Puedes asignar un puntero a un int a un puntero a un char?. ¿Puedes asignar un float a un int?
Casi todos los lenguajes te permiten hacer burradas...si se lo pides. La cuestión es la facilidad con que puedes hacer una burrada sin pretenderlo. En pascal, p.ejm. si quieres asignar un puntero a integer a un puntero a un fichero, no te deja. Ahora, si te empeñas porque lo consideras necesario, le fuerzas la conversión explícitamente, y ya está.
Esos errores los sigo cometiendo en PHP, y lo que es peor, cuesta un huevo de pillar. No soy yo el único, en el Kernel de Linux hubo un caso de estos.
El 99.9% de los casos en una condición quieres hacer una comparación, no una asignación, por tanto, lo lógico es que la sintaxis los diferencia claramente y evite la confusión.
Muy simple, asumen que siempre hay un break. Evidentemente no se puede hacer una ejecución en cascada como en C (si se cumple B, ejecuta B, si se cumple A ejecuta A y B) ¿Pero quién quiere esto? ¿cuántas veces se necesita? Es heredado del ensamblador.
Otras cuestiones Vaya por delante, que las macros, llaves y mayúsculas/minúsculas, los considero más cuestión de gustos que defectos.
Las macros pueden ser útiles. Pero se ha abusado de ellas. En cualquier caso hay otras alternativas, de modo que cuando ves una instrucción no te despista porque está redefinida con una macro.
Perdonado ;-)
El problema se lo veo también al pascal con begin/end. Cada estructura debería cerrarse de una manera, p.ejm. en for/next while/wend case/cend funcion/eif. Significa captar que estructura no cerrada en 5 segundos a tardar 30 segundos si se ha liado.
No es que dé errores, es que me repatea no acordarme si este identificador es MiFuncionInt o MiFuncionINT o miFuncionInt o miFuncionINT.
Sí, esa es otra.
Y poco eficiente. Para llegar al final de la cadena, te la has de recorrer de principio a fin: Para saber el tamaño de una cadena, operación bastante frecuente. Para concatenar cadenas. Por no hablar de que el ascii 0 no puede ser parte de una cadena.
El problema es que sigue utilizándose para muchas cosas, y ha pasado sus genes otros lenguajes como C++.
Lo problemas son tan antipáticos que el java, python o ruby, lenguajes interpretados lo están sustituyendo. Es lamentable que otro lenguaje compilado no se haya convertido en un estándar de facto como el C/C++.
Re:Estoy de acuerdo, pero...
(Puntos:1)( Última bitácora: Domingo, 07 Marzo de 2010, 15:03h )
case var of
1,2,3:
end;
en esta forma:
switch(var) {
case 1:
case 2:
case 3:
}
Y no veo que sea algo poco frecuente.
Sobre las macros, imagino que fueron hechas para lo que se usan, ahorrar fragmentos de código, aunque me parece que pudieron habérselo currado un poco más, por ejemplo si defines una macro de esta forma:
#define ADD(a, b) a+=b y se te ocurre llamarla en dos líneas:
ADD(a,
b);
obtendrás un lindo mensaje de error, cortesía del preprocesador. Además me sorprende que nadie haya mencionado al tratamiento de booleanos.
Aún así creo que si C han llegado al lugar donde está no ha sido cuestión de gustos, sino por ser el equilibrio perfecto entre un lenguaje que no abusa de la verborrea y la eficiencia sin tener que llegar a ensamblador, sólo diré que nadie aquí ha obligado a Larry Wall o a James Gosling a copiar su sintaxis.
Be yourself
Re:Estoy de acuerdo, pero...
(Puntos:2)( http://press.asqueados.net/ | Última bitácora: Jueves, 17 Abril de 2014, 09:50h )
Pero eso incluye la sobrecarga de hacer que el ordenador compruebe en cada acceso, además de tener que guardar el valor dentro de la estructura de datos.
Quizás el problema es que no exista una biblioteca estándar como en C++ o Java (quizás no tan extensa) que te resuelva los problemas más comunes.
Me pillas un poco oxidado en teoría de los lenguajes, pero yo entiendo tipado débil cuando, por ejemplo, una variable almacena distintos tipos sin problemas o puedes pasarle un int a una función que espera un float (eso seguro que no ocurre).
Las cosas que pones tienen sentido en el mundo C. En el orden que me conviene:
Lo que me lleva a una nueva concesión para ti: es una basura que no esté establecido qué tamaño tienen un short, un int, un long, etc, y dependa de la máquina y el compilador.
Si haces eso en C el compilador te suelta un warning como una catedral. Puedes ajustar el compilador para que considere errores los warnings o bien proponerte a ti mismo dejarlo todo sin warnings.
No estoy de acuerdo. En C y derivados es muy común sustituir: por Entiendo tus reticencias, yo lloré sangre en mis primeras prácticas de C por un error debido a eso mismo, pero una vez te acostumbras no ocurre. ¿Una vez en el kernel ente cuántas miles de líneas contribuídas?
No es que no tengas parte de razón, pero yo he usado esta característica varias veces.
Puede, pero a mí se me antoja incómodo de leer, nunca me ha ayudado mucho esta sintaxis. Admito que debe ser por costumbre.
En este aspecto la sintaxis que me parece genial es la de python, que se hace mediante la tabulación de las sentencias, aunque con la gran pega de la confusión espacios vs tabuladores (aspecto que parece imposible de llevar bien para alguna gente).
Envíos descartados por Mu [barrapunto.com]