Conceptos Fundamentales de Programación en C y C++
A continuación, se presenta una colección de afirmaciones sobre programación en C y C++, manejo de memoria, estructuras de datos y comunicación por sockets. Se indica si cada afirmación es Verdadera (V) o Falsa (F).
1. Arrays, Punteros y Memoria
- Sea el vector de enteros int v[5]. Para almacenar en la última posición del vector el valor 100, ¿es correcto poner v[5] = 100;? F (La última posición válida es v[4]).
- Para crear una cadena de caracteres con el texto «hola», ¿es correcto poner char cad[4] = «hola»;? F (Se requieren 5 posiciones para incluir el terminador nulo \0).
- El operador & se puede aplicar a un entero, por ejemplo &i, para obtener la **dirección de memoria** donde se almacena el entero. V
- Para reservar **memoria dinámica** en C++ para un vector unidimensional se utiliza el operador new en combinación con el operador sizeof. F (En C++, new gestiona el tamaño implícitamente).
- En C y C++ es posible reservar **memoria dinámica** para un array bidimensional. V
- Al declarar que una función recibe como parámetro un vector, no se puede dejar vacío el tamaño del vector. Por ejemplo, esta declaración daría error al compilar: void LeerVector(float v[]). F (El tamaño es opcional para la primera dimensión).
- Al declarar que una función recibe como parámetro una matriz, se puede dejar vacío el tamaño correspondiente a la **primera dimensión** de la matriz. Ejemplo: void LeerMatriz(float m[][3]). V
- En C, los arrays se pasan por **dirección** (como punteros), es decir, no se hace una copia de los valores de los elementos del array para la función. V
- Un vector (array) en C o C++ puede definirse con **diferentes tipos de datos** para cada elemento. F (Los arrays deben ser homogéneos).
- A un puntero se le puede asignar la dirección de memoria de una variable usando el **operador de dirección** (&). F (El enunciado menciona incorrectamente el operador de indirección *).
- El paso de parámetros a una función **por referencia** es el método recomendado para pasar parámetros en C. F (C utiliza paso por valor).
- Considerando: int a[10]; int *pa; Se puede conseguir que el puntero pa apunte al vector a de cualquiera de estas formas: 1) pa = a; 2) pa = &a[0]; V
- En C no es posible crear un **vector de estructuras**, ya que solo se pueden crear vectores de tipos de datos simples. F
- El identificador de un array es en realidad un **puntero** al elemento 0 del array. V
- La sentencia en C: int vector[] = {1, 2, 3}; es correcta a pesar de que no se haya indicado el tamaño del vector entre corchetes. V
- Si dos cadenas de caracteres tienen la misma dimensión, ¿puede asignarse el contenido de la cadenaB a la cadenaA de la siguiente forma: cadenaA = cadenaB;? F (Se debe usar strcpy).
- Dado el vector int x[3] = {10, 11, 12};, el valor de *x es 10. V
- Dada la declaración int a[10];, para asignar al elemento situado en la posición 1 del vector el valor 5, se puede utilizar a[1] = 5; o *(a + 1) = 5;. V
- En C no es posible declarar un **puntero doble** (por ejemplo: int **p;), pero sí en C++. F (Es posible en ambos).
2. Programación Orientada a Objetos (POO) en C++
- En el mecanismo de herencia de C++ se permite **sobreescribir** (override) un método, es decir, en la clase derivada se puede volver a definir el método que ya estaba definido en la clase base. V
- En C++ se puede definir el operador + como un **método de una clase** o como una **función global**. V
- Una **función global amiga** de una clase (friend) puede acceder a los miembros **privados** de la clase como si fuera un método de la clase. V
- En C++, una **variable miembro estática** es común para todos los objetos de la clase (todos los objetos comparten la misma variable estática). V
- C++ permite la **herencia múltiple**, es decir, una clase derivada puede heredar de más de una clase base. V
- En C++ se pueden implementar **diferentes destructores** para la misma clase. F (Solo se permite un destructor, no puede sobrecargarse).
- Al definir el operador de asignación = en una clase, siempre se debe devolver *this (por referencia). V
- En una **función miembro** de una clase en C++, no debemos pasar explícitamente como parámetro el objeto sobre el que se aplica la función (se accede implícitamente mediante this). V
- Una **función virtual pura** se debe definir obligatoriamente en la clase base, aunque se puede volver a definir en las clases derivadas. F (No requiere definición en la clase base).
- En C++, cuando se destruye un objeto de una clase derivada, se ejecuta primero el destructor de la clase base y después el de la clase derivada. F (Se ejecuta primero el destructor de la derivada, luego el de la base).
- Una **clase abstracta** es una clase que tiene al menos una **función virtual pura**. V
- Las variables miembro de una clase base en C++ declaradas como **privadas** pueden ser accedidas desde una clase derivada de la clase base. F
- Las variables miembro de una clase base en C++ declaradas como **protected** pueden ser accedidas desde una clase derivada de la clase base. V
- En C++ no se puede sobrecargar el operador << (inserción) para poder mostrar el contenido de un objeto con cout. F (Sí se puede).
3. Entrada/Salida, Ficheros y Funciones
- La función fgets lee una cadena almacenada en un fichero, pero solo hasta encontrar el primer espacio en blanco o el final de línea \n. F (Lee hasta el final de línea o el tamaño máximo, incluyendo espacios).
- En C no es posible leer un fichero **carácter a carácter**. F (Sí es posible, usando funciones como fgetc).
- En C no es posible abrir un fichero para **escritura y lectura** simultáneamente, sino que o bien se abre para lectura o bien para escritura. F (Modos como r+, w+, a+ permiten ambos).
- En C++ se pueden dar **valores por defecto** a los parámetros de una función, de forma que dichos parámetros pueden ser omitidos en la llamada a la función. V
- En C++ se puede utilizar para mostrar el valor de una variable entera i tanto cout << i; como printf(«%d», i);. V
- La función scanf no puede utilizarse para leer una cadena de caracteres por teclado si esta contiene **espacios en blanco** (usando el especificador %s). V
- No puede utilizarse printf para mostrar una cadena de caracteres por pantalla si esta contiene **espacios en blanco**. F
- Sea c una variable tipo char que contiene un carácter. Para mostrar el **código ASCII** del carácter almacenado en c, se puede utilizar el siguiente código: printf(«%d», c); V
- Considérese char c = ‘a’;. La sentencia printf(«%d», c); produce un error de compilación ya que c no es un dato de tipo entero. F (El tipo char se promociona a int).
- En C, dentro de una función (diferente al main) no se puede llamar a otra función. F
- En C es posible actualizar el **indicador de posición de fichero** al inicio del fichero (usando rewind o fseek). V
- En C++, para leer desde teclado un entero y almacenarlo en la variable dato, ¿debería utilizarse: cin >> «%d» >> dato;? F (El formato «%d» es incorrecto para cin).
- Para declarar e inicializar un entero j con el valor 10 en C++, se puede hacer int j = 10; o int j(10); (inicialización directa). V
- Una función en C puede llamarse a sí misma (**recursividad**). V
- La sentencia continue dentro de un bucle hace que este **finalice**. F (Solo salta a la siguiente iteración).
- Si se define la variable cadena como char cadena[10];, ¿la instrucción siguiente es correcta: scanf(«%», &cadena);? F (Incorrecta sintaxis y uso de especificador).
4. Sistemas, Redes y Algoritmos
- La ventaja de utilizar el protocolo **UDP** es que es un protocolo orientado a la conexión y con control de errores en la transmisión. F (UDP es sin conexión y no garantiza fiabilidad).
- Para comunicar dos equipos mediante **sockets**, solo se puede utilizar el protocolo **TCP**. F (También se puede usar UDP).
- Para que un cliente se comunique con un servidor mediante **sockets**, el cliente no necesita conocer el puerto del servidor. F (Necesita conocer la IP y el puerto).
- Por defecto, la función recv para lectura de un socket quedará a la espera de recibir datos de forma **indefinida** (bloqueante). V
- En una **comunicación asíncrona**, el transmisor puede enviar datos en cualquier momento. V
- En una **transmisión síncrona** se requiere de bits de inicio y fin para identificar cada byte de datos. F (Esto es característico de la transmisión asíncrona).
- Para implementar una arquitectura **cliente/servidor** en C o C++, solo puede utilizarse la librería de programación de sockets. F (Existen otras tecnologías como RPC).
- El algoritmo de **búsqueda binaria** permite buscar un elemento dentro de un vector siempre y cuando el vector esté **ordenado**. V
- Para aplicar el algoritmo de **búsqueda binaria** sobre un vector, no es necesario que esté ordenado. F
- En el lenguaje C, el tipo de datos int ocupa la misma memoria independientemente del sistema en el que se use. F (El tamaño es dependiente de la implementación/arquitectura).
- Suponiendo que a y b son enteros, y que b=0, ¿se puede utilizar cualquiera de estas sentencias: a = b++; o a = ++b; para hacer que el valor de a sea 1? F (Solo a = ++b; resulta en a=1).
