|Lo que no hay que hacer en C/C++. Nivel basico|

Iniciado por Littlehorse, 12 Diciembre 2009, 18:15 PM

0 Miembros y 1 Visitante están viendo este tema.

skan

Hola

Había leído esto hace un tiempo en el libro "effective c++" y algún otro sitio.
Hoy he querido consultar otra vez este tipo de comandos (como fgets o strncpy) pero no aparecen en libros modernos como Prata 6th edition o Professional C++.
¿Quiere eso decir que ya no son necesarios?
Lo digo porque get, strcpy...   aceptan también un  parámetro especificando el número de caracteres. ¿Qué ventaja hay ahora por ejemplo entre fgets y get?

saludos

fakundo (sylas)

Buen post aun que yo no me entero mucho pero comprendo algo pero es normal jeje aun hago la eso
el conocimiento es libre

somos anonymous

somos legion

nosotros no olvidamos

nosotros no perdonamos

DéstroReflex

Gracias por la explicación, son el tipo de cosas que te enseñan "por defecto" pero no tienes ni idea de que función realmente cumplen y qué podrían afectar.
Siempre tonto, cada vez mejor maestro.

Peregring-lk

Nota: Respecto a los ejemplos que voy a poner aquí: ¡¡no lo hagáis en casa!! Son prácticas permitidas pero ¡antigüas, deprecated e incluso mal vistas!

Respecto al `void main()` que se cita en la guía, si programas en C++, un compilador de C++ decente te dirá que es un error de compilación y no te dejará continuar. No es que sea una mala costumbre, es que es un programa con un error sintáctico.

Sin embargo, si `main` tiene tipo `int main()`, pero no escribes un `return`, no te dará ningún error de compilación porque el estándar dice que el compilador debe añadir al final del `main` un `return 0` si no lo tiene ya. Y los compiladores obedecen al estándar como buenos esclavos.

En C, sin embargo, la cosa es aún más permisiva. Puedes no escribir el `return`, y el compilador lo añadirá. Puedes hacer que su tipo de retorno sea `void`, y el compilador también añadirá el `return 0`: ¿pero eso no puede ser? ¿un `void` no puede devolver un `int`? Ya, pero es que ese `return` se añade a nivel de ensamblador, y en ensamblador no existen tipos.

Incluso en C puedes no escribir tipo de retorno:


main() {}


El compilador solo te lanzará un warning diciendo que el tipo de retorno por defecto es `int` (y también te añadirá el `return 0`). De hecho, en C puedes declarar cualquier cosa sin tipo (tipos de retorno, parámetros o variables; todas serán por defecto `int`, eso sí, con warnings por doquier):


void f(a) {}


Y `a` tendrá por defecto tipo `int` (con su correspondiente warning). Y llevando al extremo las cosas raras, ésto también es C estándar (se permite por retrocompatibilidad con versiones antigüas de C):


void f(a) int a;
{}


Aquí, el tipo de `a` se declara a posteriori, entre el nombre de la funcion y su cuerpo. No hace falta decir que todo ésto no se puede hacer en C++ (un compilador de C++ gritará como una loca).

Y repito, no hagáis nada de ésto en casa si no queréis que mate a un gatito.




Seyro97

Otra es no usar namespaces (sobre todo cuando solo vas a usar cout xD). Pongo un ejemplo:

Código 'malo':

Código (cpp) [Seleccionar]
#include <iostream>

using namespace std;

int main() {
cout << "HOLA" << endl;

cin.get();
return 0;
}


Código 'bueno':

Código (cpp) [Seleccionar]
#include <iostream>

int main() {
std::cout << "HOLA" << std::endl;

std::cin.get();
return 0;
}
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

engel lex

Cita de: Seyro97 en 30 Mayo 2015, 16:47 PM
Otra es no usar namespaces (sobre todo cuando solo vas a usar cout xD). Pongo un ejemplo:

Código 'malo':

Código (cpp) [Seleccionar]
#include <iostream>

using namespace std;

int main() {
cout << "HOLA" << endl;

cin.get();
return 0;
}


Código 'bueno':

Código (cpp) [Seleccionar]
#include <iostream>

int main() {
std::cout << "HOLA" << std::endl;

std::cin.get();
return 0;
}


explicate las razones
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Stakewinner00

Eso de los namespace si que esta prácticamente prohibido al programar librerías , porque el código de la librería podría entrar en conflicto con la del usuario. Pero no entiendo porque un programa sencillo no se puede usar eso...

Peregring-lk

Cita de: Stakewinner00 en 30 Mayo 2015, 19:32 PM
Eso de los namespace si que esta prácticamente prohibido al programar librerías , porque el código de la librería podría entrar en conflicto con la del usuario. Pero no entiendo porque un programa sencillo no se puede usar eso...

De hecho, como bien dices, yo lo uso en código de usuario, y si hubiese un conflicto con una librería que no utilice yo directamente (librería utiliza indirectamente por las librerías que yo he añadido conscientemente), siempre puedo "evitar el conflicto con `::mivariable`, para indicar que la variable `mivariable` está en el espacio de nombres global.

En código de librería también estoy de acuerdo contigo en que no se debería usar, pero con un matiz: sólo en ficheros de cabecera. En ficheros de implementación (los `.cpp` de la librería), sí que creo que se podría utilizar sin problemas.

Aunque yo no domino mucho los matices de los espacios de nombres, he visto que muchas librerías importantes (sí, a veces me enfado tanto con los errores de ejecución que a veces me embarco en la horrorosa aventura de mirar el código fuente de una librería), utilizan nombres de espacio anónimos en los `.cpp`, porque los espacios de nombres anónimos hacen que todos los símbolos en él tenga enlazado estático, lo que significa que desde otras unidades de compilación no se puedan acceder a ellos:

Código (cpp) [Seleccionar]

// libreria.hpp
namespace libreria {

    class loquesea {
    public:
         void fun1();
         void fun2();
    };
}

// libreria.cpp
#include "libreria.hpp"

namespace {
   using namespace std; // Al fin y al cabo, ahora el usuario es el implementador de la librería.

   // Clases y funciones auxiliares que realmente hacen el trabajo.
}

namespace libreria {

    void loquesea::fun1() { /* Implementacion utilizando las clases/funciones auxiliares */ }
    void loquesea::fun1() { /* Implementacion utilizando las clases/funciones auxiliares */ }

}


De ésta forma, todo aquello que vaya más allá de la interfaz pública con el usuario, es innacesible desde fuera, debido a que los símbolos del espacio de nombres anónimo tienen enlazado estático, y por tanto, pertenecen solamente a "ésta unidad" de compilación, como cuando declaras una función externa "static". Incluso los símbolos de la `std`, como se han "introducido" dentro de un espacio de nombres anónimo, desde fuera tampoco están visibles, y el usuario final (a no ser que escriba `using namespace std` en su código), no tendrá conflictos ni con la librería, ni con la `std`.

Es una forma se reduce muchísimo la cantidad de símbolos que el enlazador tiene que buscar.

Seyro97

Cita de: Stakewinner00 en 30 Mayo 2015, 19:32 PM
Eso de los namespace si que esta prácticamente prohibido al programar librerías , porque el código de la librería podría entrar en conflicto con la del usuario. Pero no entiendo porque un programa sencillo no se puede usar eso...


Era un ejemplo :P
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!

Seyro97

#69
Cita de: engel lex en 30 Mayo 2015, 17:16 PM
explicate las razones

Casi nunca miro este tema xDD. Siento no haber respondido antes. Las razones son una tontería, pero ya que C++ nos provee una estructura lógica, pues vamos a usarla... Vamos, eso pienso yo. Otra razón, aunque casi ni es razón, imaginemos que una librería que no conoce cout (? jaja), y usa cout para crear una clase, pues entonces habría un conflicto xD
Carlos Peláez González. visita http://www.taringa.net/EnjoyC para muchos tutoriales!