You are on page 1of 45

Fundamentos de Software de Comunicaciones

El lenguaje C/C++
Arrays, Cadenas, Estructuras y Punteros

Contenidos

Diferencias principales Arrays Cadenas Bibliotecas de funciones Estructuras Punteros Memoria dinmica Argumentos a funciones Constantes Punteros y arrays Punteros a funciones Convivencia de funciones C++ y C

Principales diferencias entre C y C++

C es el lenguaje original con el que se cre Unix y l mayora la d de di dispositivos ii d de comunicaciones i i se programan en l
o

Permite acceso directo a zonas de memoria

Los lenguajes de C y C++ son compatibles al 99%


o

pero tienen distintas bibliotecas de funciones (y clases en el caso de C++) Esta documentacin est basada en el estndar C99. Ya hay un estndar C11 que lo acerca ms a C++ (C++11)

Principales diferencias al compilar:


o o

ficheros .c c (con sintaxis C pura!) -> > utiliza gcc ficheros .cpp (con C++ y/o C) -> utiliza g++

Principales diferencias: E/S

En C++
o o o

#include #i l d <iostream> i t std::cout, std::cin, std::cerr operadores p << y >>

En C puro
o o

#include l d <stdio.h> d h salida por pantalla:


p printf("texto"); ( ); printf(" texto con comodines %d %x %c %s \n", variable_entera, variable_hexadecimal, variable_caracter, variable_cadena_de_caracteres);

l lectura d de teclado l d
scanf("lista de comodines (%s%d...)", direcciones_a_variables); //es una funcin que utiliza punteros a variables

Los arrays de C

Permiten la reserva de un nmero de posiciones consecutivas de memoria Declaracin:


tipo nombre[tamao]; //EL TAMAO ES FIJO

Inicializacin:
tipo nombre[tamao] = {const, const, .. const}; tipo nombre[] = {const, const, .. const};
NOTA: la asignacin de un arrays a otro array es ilegal en C char array1[50]; char array2[50]; array1 = array2; //ERROR (se ver la causa ms adelante)

Acceso a un elemento:
nombre[ndice] (donde ndice est entre [0 , tamao 1])

Ejemplo de arrays de C
#include <iostream> using namespace std; int main(){ const int TAM_ARRAY = 10; int arr[TAM_ARRAY]; t in; ; int for (int i=0; i < TAM_ARRAY ; ++i) arr[i] = i; // inicializacion con valores for (int i=0; i < TAM_ARRAY ; ++i) cout << arr[i]; // impresion del array por pantalla cout << "\nIntroduce el numero a buscar: " << endl; cin >> in; int j=0; while( (j < TAM_ARRAY) && ( arr[j] != in) ){ j++; } if (j == TAM_ARRAY) cout << "El numero " << in << "no esta en el array" << endl; else cout << "El numero " << in << "esta en la posicion " << j-1 << endl; return 0;

Resumen: arrays en C++ y en C

C++:

C:

#include <tr1/array> // o <array> en C++11 const t int i t TAM_ARRAY TAM ARRAY = 50; 50 //declaracin con tamao e inicializacin std::tr1::array<int, TAM_ARRAY> mi_array = {{1,2,3}}; //ojo a la doble llave //asignacin elemento a elemento mi_array[0] i [0] = 0; 0 //definicin como tipo typedef std::tr1::array<int, TAM_ARRAY> TipoArray; TipoArray otro_array; // //consulta lt d del lt tamao d del l array (cuantos ( t elementos l t tiene ti en uso) ) otro_array.size();

const int TAM_ARRAY = 50; //d l //declaracin i con tamao e inicializacin i i i li i int mi_array[TAM_ARRAY] = {1,2,3}; //quedan 47 huecos libres //declaracin sin tamao (lo resuelve el compilador) int mi_array2[] = {1,2,3}; //este tiene slo 3 elementos // i //asignacin i elemento l t a elemento l t mi_array[0] = 0; //definicin como tipo typedef int TipoArray[TAM_ARRAY]; Ti A TipoArray otro_array; t //NO es posible consultar el tamao ocupado de un array en C (lo cual es peligroso)

Cadenas de caracteres de C

Declaracin como arrays con tamao


char h nombre[tamao]; b [t ]

O sin tamao si se inicializan al declararlos


char cadena[] [] = { {'u', , 'n', , 'o', , '\0'}; \ }; char cadena2[] = "uno"; //aqu el compilador pone el '\0'

'u' u 'n' n 'o' o '\0' \0

El acceso se hace como un array normal, normal aunque existen tambin funciones especiales
cadena[0] = 'U';

La diferencia entre un array de C y una cadena es el terminador '\0', \0 , que ocupa una posicin, y permite entender el array de caracteres como texto

Ejemplo de manejo de cadenas en C


//Imprime la linea mas larga de entre todas las introducidas (cod1.2.cpp) #include <iostream> #include <cstring> //para strlen() using namespace std; void copia(char destino[], char origen[]); //funcion definida por el programador! int main(){ int len; // int max=0; // const int MAXLINE = 1000; char linea[MAXLINE]; // char longest[MAXLINE]; //

longitud de la linea actual maxima longitud actual linea actual linea mas larga

while(1){ cin getline(linea MAXLINE); cin.getline(linea, len= strlen(linea);//calcula la longitud en bytes de la cadena (sin contar '\0') cout << linea << ": " << len << endl; if(len > max){ max = len; copia(longest, linea); } cout << "La mas larga es de " << max << " caracteres: " << longest << endl; } return 0; } //sigue...

Ejemplo de manejo de cadenas (y II)


//...viene de la pgina anterior // copia una cadena de caracteres origen en otra destino void copia(char p ( destino[], [], const char origen[]){ g []){ int i=0; es equivalente a poner : const char * destino, const char * origen while(origen[i] ! != '\0'){ \0 ){ (se ver) destino[i] = origen[i]; ++i; } destino[i] = '\0'; }
//pero en realidad se utiliza la funcin strcpy(destino, origen)
10

Cadenas en C++ y en C C. Equivalencias


mtodo C++ string::size st g ass g string::assign (o con el operador =) string::copy (o con el operador =) string::append (o con los operadores +=, +) string::compare (o con >, <,==, !=, ...) string::find g ... funcin C strlen strcpy st cpy strcpy strcat strcmp strstr ...

11

Software de Comunicaciones guiado por modelos 11

Funciones bsicas para cadenas de caracteres


//no confundir con la clase std::string Si se usa C++: #include <cstring> En C puro: #include <string.h> Esta cabecera declara un conjunto j de funciones p para manipular p cadenas de caracteres Funciones tpicas:
Copia: memcpy, memmove, strcpy y strncpy Concatenacin: strcat y strncat Comparacin: memcmp, strcmp y strncmp Bsquedas q : memchr, strchr, strstr y strtok Otras: memset, y strlen

12

Consulta rpida: http://www.cplusplus.com/reference/clibrary/cstring/

Bibliotecas de conversiones entre formatos


C++: #include <cstdlib> C: #include <stdlib.h> Esta cabecera declara un conjunto de funciones de propsito general Funciones: u c o es
o o o o o o

atof atoi atol strtod strtol strtoul

13

Consulta rpida: http://www.cplusplus.com/reference/clibrary/cstdlib/

Bibliotecas de deteccin de caracteres


C++: #include <cctype> yp C: #include <ctype.h> Esta cabecera declara un conjunto de funciones para clasificar y transformar caracteres individuales Funciones:
o o o o o o o o o o o

iscntrl isspace isupper islower isalpha isdigit isxdigit i l isalnum ispunct isgraph i isprint i t

14

Consulta rpida: http://www.cplusplus.com/reference/clibrary/cctype/

Definicin de estructuras

Una estructura es una coleccin de variables (i l id estructuras) (incluidas )


struct nombre { tipo nombre_campo; tipo nombre_campo; ... };

En C/C++, una estructura puede utilizarse como una variable (asignacin, paso como parmetro, valor de vuelta de una funcin) L estructuras Las t t no se pueden d comparar

15

Tamao de datos

En C y C++ existe un operador unario sizeof que devuelve el nmero de bytes que ocupa una variable o un tipo de dato en memoria
o

La longitud la devuelve como natural positivo, en un tipo denominado size_t size_t longitud = sizeof(int); int var_entera; var entera; size_t size t longitud = sizeof(var_entera); sizeof(var entera);

Ejemplos:
o o

Tambin se puede utilizar para calcular el tamao en memoria de una estructura


o

16

CUIDADO: SU VALOR PUEDE SER MAYOR QUE LA SUMA INDIVIDUAL DEL TAMAO DE SUS CAMPOS

Campos de bits en estructuras

Se usan para ahorrar espacio de almacenamiento, pero depende d d d del l compilador il d cmo se almacena l la l estructura en memoria (su tamao real)
struct t t Permisos{ P i { unsigned int lectura : 1; //un bit

unsigned int escritura : 1; //un bit unsigned int ejecucion : 1; //un bit };

permisos.lectura = 0; permisos.escritura = 1; 17 sizeof(Permisos) ( ) ? NO p puede ser 3 bits!

Uniones

Superposicin en memoria de elementos h heterogneos Solo existe un espacio de memoria (el del campo con mayor sizeof) Sin embargo, el acceso a ese espacio de memoria se hace indistintamente con cualquier campo, campo como en una estructura
union i N b Nombre { tipo1 elemento1; p elemento2; tipo2 ... } variables; c.ival = 20; i C tid d { Cantidad union int ival; float fval; } c;

18

Repaso de punteros

int x = 10; int *p; p = &x;

p 10 x

p guarda la direccin de memoria de x


19

Repaso de punteros (II)

int x = 10; int *p; p = &x; *p = 20;

p 20 x

*p es el contenido al que apunta p.


20

Repaso de punteros (III)


Declara un puntero a un entero

int x = 10; int *p; p = &x; *p = 20;


Es el operador desreferencia, que obtiene el valor apuntado por p 21 & es el operador direccin, que obtiene la direccin de x

Reserva de memoria dinmica: new


tipo *p = new tipo;

new reserva memoria para almecenar una variable de un tipo concreto en el heap new devuelve el puntero a esa variable u objeto, o cero si no fue capaz de hacer la reserva Tambin en versin array:

tipo *p = new tipo[50]; // p apunta a la primera casilla // se accede a los contenidos con p[x]
o

En C++, por seguridad, se recomienda utilizar std::vector, td t que reserva directamente di t t sus elementos l t en el Heap

22

Liberacin de memoria dinmica con delete


// reserva p = new int; ; int *p ... // libera memoria delete p;

Por cada llamada a new, debe haber una (y slo una) a delete. delete libera el espacio que ocupaba el objeto/variable en memoria En versin array:

int *p p = new int[5]; [ ]; delete[] p;

23

Memoria dinmica en C++ y C

C++
new, new [] delete, delete[]
o

o bien: be
#include <cstdlib> int * p = (int *)malloc(50*sizeof(int)) free(p);

C:
#include <stdlib.h> stdlib.h int * p = (int *)malloc(50*sizeof(int)) //alternativa: int * p = (int *)calloc(50,sizeof(int)); //si usas calloc el contenido de memoria se pone a cero! free(p);

24

No mezclar nunca new-free y malloc-delete

El operador "->"
struct MisDatos{ int dato1; int dato2; }; MisDatos *p = new MisDatos; // Acceso a campos: (*p).dato1 = 5; // Es equivalente a: p->dato1 = 5;
25

Heap (montn) vs. vs Stack (pila)


En el Heap / En la Pila /
Reserva dinmica Reserva automtica

void pinta() void pinta() { { MisDatos *p = new MisDatos; MisDatos p; p->dato1 = 5; p p.dato1 = 5; p //... //... } }

Qu Q sucede d cuando d p queda d f fuera de d alcance? l ?


26

Argumentos pasados por valor


void doble(int i){ i = i+i; } i t main(){ int i (){ int i = 5; doble(i); cout << i << endl; //resultado: 5 }

27

Qu es una referencia?

Un alias, otro nombre para una variable int x = 5; int &y y = x; // y es una // referencia a x y = 10; Qu pasa con x? Qu pasa con y? Las referencias SLO existen en C++, no en C

28

Argumentos pasados por referencia


//Slo vlido en C++ void doble(int & i) { i = i+i; /* el i de esta funcion es el alias d l de la variable i bl que l le pasen como argumento t son la misma! */ } int main() { int x = 5; doble(x); cout << x << endl; //resultado: 25 return 0; }

29

Argumentos pasados por direccin


void doble(int * i){ *i = (*i)+(*i); ( ) ( ) / el i de esta funcion /* es un puntero a la variable que le pasen como co o a argumento gu e to */ / } int main(){ int x = 5; doble(&x); cout << x << endl; //resultado: 25 return 0; }

30

Argumentos pasados por direccin (II)


void nuevoValor(int * i) { i = new int; /*como el puntero se pasa por valor valor, su nuevo valor no se propaga fuera de la funcion*/ *i = 7; } int main() { int x = 5; cuadrado(&x); cout << x << endl; //resultado: 5 return 0; 0 }

31

Argumentos pasados por direccin (III)


void nuevoValor(int ** i){ *i = new int; /*ahora / si puedo reasignar el puntero*/ **i = 7; /*asignacion vlida!*/ } int main(){ int *x; cuadrado(&x); ( ) cout << *x << endl; //resultado: 7 delete x; return 0; }
32

Argumentos pasados por direccin (IV)


//Esto es lo que se hace en C++ void nuevoValor(int *& i){ i = new int; /*ahora si puedo reasignar el puntero*/ *i = 7; /*asignacion vlida!*/ } i t main(){ int i (){ int *x; cuadrado(x); cout << *x << endl; //resultado: 7 delete x; return 0; }
33

Argumentos pasados por direccin (V)


//Con typedef se entiende mejor typedef int * Pint; void nuevoValor(Pint & i){ i = new int; / /*ahora ahora si puedo reasignar el puntero*/ *i = 7; /*asignacion vlida!*/ } int main(){ Pint x; cuadrado(x); cout << *x << endl; //resultado: 7 delete x; return 0; }
34

Ms sobre punteros como argumentos

No es eficiente pasar zonas de memoria grandes (arrays) por valor a una funcin, puesto que se copian en su contexto de ejecucin El compilador pasa los arrays a una funcin siempre como punteros
void funcion(char array[]) //es equivalente a o void funcion(char *array)
o

El l programador d d debe b h hacer l lo mismo i si i piensa i mover grandes cantidades de datos entre funciones Y en C no existen las referencias: f(tipo &var)
o o

solo se vern prototipos de la forma: f(tipo *var) pero ya se ha visto que no es exactamente equivalente!

35

El modificador const
void imprimeDoble(const ( int& i){ ) i = i+i; No compila! cout t << i << endl; dl } int main(){ int i = 5; imprimeDoble(i); }

36

Declaraciones con const


const MisDatos m; //constante const MisDatos * cpm; //puntero a objeto
constante

MisDatos* const pcm;//puntero constante a objeto


mutable t bl

const t MisDatos* Mi D t * const t pccm; //puntero // t constante t t


a constante

37

Punteros y arrays

El identificador de un array o cadena es un puntero constante a su primer elemento


int i t array1[20], 1[20] array2[20]; 2[20] int * p; p = array1; //valido! array2 = p; //no valido, array2 (y array1) son punteros constantes

Se puede trabajar indistintamente con el operador [] o con aritmtica de punteros:

38

#include <iostream> int main () { int numbers[5]; int * p; p = numbers; *p = 10; p++; *p = 20; p = &numbers[2]; *p = 30; p = numbers + 3; *p = 40; p = numbers; *(p+4) = 50; for (int n=0; n<5; n++) std::cout << numbers[n] << ", "; ; return 0; }

Punteros y arrays (II)

Cuando se utiliza un std::string o std::array de C++, se puede obtener un p p puntero a sus datos en memoria, , para p manipularlos en modo C:
std::array<int,200> mi_array; int * p = mi_array.data();

Ejemplo:

39

#include <iostream> #include <cstring> cstring #include <array> int main () { const char* cstr = "Test Test string"; string ; std::array<char,12> charray; std::memcpy (charray.data(),cstr,12); std::cout << charray charray.data() data() << '\n'; \n ; return 0; }

Punteros y arrays (III)

Con std::string tambin se puede acceder a la memoria utilizando el mtodo data()


o o

Ejemplo:

Pero si no se est utilizando un compilador con el estndar C++11 esto NO est aconsejado Se recomienda el mtodo c c_str(), str() que devuelve un puntero a la cadena constante en formato C (SLO PARA OPERACIONES DE LECTURA)

40

#include <stdio.h> #include <string> int main () { std::string td t i str t ("H ("Hola l mundo d C!") C!"); printf("Contenido: %s\n",str.c_str()); return 0; }

Conversin de objetos std::string a char*

41

Punteros a funciones

Una funcin C no es una variable, pero

Se puede apuntar a la memoria donde comienza un segmento de cdigo (funcin) Se puede usar el puntero como el de una variable

Se define el tipo de las funciones


que tienen el mismo tipo de retorno y los mismos argumentos

Las funciones definidas q que lo cumplan p son valores del tipo

42

Punteros a funciones
int (*pf)(); /* puntero a funcin que devuelve un entero */ void (*pv)(); /* puntero a funcin que devuelve void */ int (*pf2)(int,float); /*puntero a una funcion que devuelva int y acepte como argumentos a gu e tos int t y float*/ oat / int (*pf3[2])(int); /* array de dos punteros a funciones que devuelvan int y acepten como argumentos int*/ int (*pv2[2][3])(); /*array de 2x3 punteros a funciones que devuelvan int */

Ej Ejemplo: l

int f(){ /*esta funcion no tiene argumentos y devuelve un entero*/ return 0; } pf = &f; p pf(); //asignacion g del p puntero a funcion //ejecucin de la funcion! (es equivalente a poner directamente f());

43

main() con parmetros

Para crear la funcin principal main existen varias formas:


o

Sin parmetros:
int main(){ return 0; }

Con parmetros (permite personalizar la ejecucin):

int main(int argc, char *argv[]){ argv[]){ for(int i=0;i<argc; ++i) cout << argv[i] << endl; } argc es el argumento que contiene el nmero de palabras (parmetros) que se pasan al ejecutable (incluyendo el nombre del programa) argv es un array de cadenas de caracteres, donde cada casilla contiene un parmetro (argv[0] contiene el nombre del programa) Ejemplo: ./miprograma param1 param2

44

argc vale 3 argv es un array de 3 casillas. En argv[0] est la cadena "miprograma", en argv[1] est "param1" y en argv[2] est "param2"

Convivencia de funciones C++ y C

Un fichero con extensin .hpp est pensado para incluirse en ficheros C++ de extensin .cpp. Sin embargo, si se programa en C puro (y con ficheros de extensin .c y .h), y luego se quiere reutilizar las funciones C definidas all en otros mdulos C++ (ficheros .cpp), cpp) los prototipos de las funciones tienen que incluir esta notacin en su .h:

#ifdef __cplusplus p p extern "C" { #endif //aqui van todos los prototipos de las funciones void f(int i, char c, float x); //... #ifdef __cplusplus } # dif #endif 45

Ms en:

http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html

You might also like