Introducción a C Gorka Guardiola M zquiz

Anuncio
Introducción a C
Gorka Guardiola Múzquiz
paurea@lsub.org
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 1
C
C no hace nada automáticamente como
lenguaje (lo mínimo)
Si no entiendo algo de C me va a morder
C es relajado, tengo que ser ordenado
C es fácil de entender completamente
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 2
Primer programa
#include <u.h>
#include <libc.h>
//comentario en una linea
/* comentario
en mas de una linea*/
void
main(int argc, char *argv[])
{
print("hello world\n");
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 3
Punto de entrada
#include <u.h>
#include <libc.h>
→void
→main(int argc, char *argv[])
{
print("hello world\n");
exits(nil);
}
main es el punto de entrada del programa
Es una función con un prototipo concreto y un
nombre especial main
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 4
Punto de entrada
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
print("hello world\n");
exits(nil);
}
No devuelve nada (void), recibe dos parámetros
Dos partes, cabecera/prototipo y cuerpo
El cuerpo es un bloque, entre llaves
Dentro van más bloques, entre llaves
O sentencias acabadas en ;
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 5
funciones
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
→ print("hello world\n");
exits(nil);
}
print es una función
Se usa para imprimir por pantalla
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 6
Antes de usar funciones de librería
Primero mirar en la página de manual
lookman para buscar si no sé qué busco
$ lookman floppy
$ lookman copy
man N intro
Introducción a la sección N del manual
la 1 el sistema
man N bla
Para buscar bla en la sección N del manual
$ man 2 print
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 7
manual
Hay que buscar funciones y llamadas en la
página de manual
Nos interesan las secciones:
Ë 1 comandos
Ë 2 llamadas al sistema y funciones de librería
man N intro
Para información acerca de la sección N.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 8
include
Lo primero que viene es qué debo incluir
→#include <u.h>
→#include <libc.h>
void
main(int argc, char *argv[])
{
print("hello world!");
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 9
include
Luego veremos más, pero:
Ë Cada librería requiere unos include
Ë En el orden que dice la página de manual
Ë No repetidos
Si miro en la página de manual, exits y print
requieren u.h y libc.h.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 10
Compilación, intro
Primero se compila el fichero
Ë $ 8c -FTVw main.c
Ë Genera el objeto main.8
Si hubiese otros, se generan igual
Ë $ 8c -FTVw bla.c
Ë $ 8c -FTVw otro.c
Luego se hace el enlazado (linking):
Ë $ 8l -o programa main.8 otro.8 bla.8
Ë Los objetos de las librerías del sistema como
libc se enlazan automáticamente sin que
tengamos que decir nada
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 11
Compilación, intro
El resultado es el programa ejecutable
Para ejecutarlo:
Ë $ ./programa
Ë hello world!
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 12
Compilación, intro
Errores y warnings
Los errores son fatales (no compila)
Los warnings no son fatales (compila)
Compilación, intro
El compilador se lo traga casi todo!!!
Ojo, en C los warning son como errores!!
Warnings ’ comportamiento impredecible
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 13
C: tipos básicos, estructuras de control
Gorka Guardiola Múzquiz
paurea@lsub.org
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 1
Enteros
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
int i;
i = 10;
print("hello world, %d\n", i);
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 2
Compilado y ejecutado
$ 8c -FTVw main.c
$ 8l -o main main.8
$ ./main
hello world, 10
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 3
¿Qué significa?
int i;
es la declaración. i es un entero.
es la definición. reserva memoria para i aquí.
i = 10;
asigna 10 al entero
¡Ojo! las variables de la pila hay que
inicializarlas
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 4
¿Qué significa?
print("hello world, %d\n", i);
La función recibe una string (veremos más
adelante) con el formato
%d significa "me pones aquí el segundo
argumento en decimal como si fuese un
entero", la d es de decimal
si hubiese otro parámetro, se pone otro
formato y se mete como tercer parámetro
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 5
Se pueden hacer más cosas:
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
int i, j;
i = 10;
print("i = %d\n", i);
i = i+1;
j = 35;
print("i = %d, j vale %d\n", i, j);
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 6
Se pueden hacer más cosas:
Compilado
$ 8c -FTVw main.c
$ 8l -o main main.8
Ejecutado
$ ./main
i =10
i = 11, j vale 35
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 7
El \n
Al final del formato hemos puesto \n
Algunos carácteres de control especiales se
ponen con una notación especial
El tabulador, por ejemplo es \t y nueva línea \n
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 8
Char, enteros más pequeños
char c;
c = 3;
print("c vale %d\n", c);
c = ’x’;
print("c vale %c\n", c);
$ 8c -FTVw main.c
$ 8l -o main main.8
$ ./main
c vale 3
c vale x
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 9
Char
Son enteros, simplemente más pequeños
(normalmente 1 byte)
Se pueden asignar y usar con y como enteros
Tienen un formato para print como carácteres
%c
Hay una forma especial de definir constantes
entre comillas simples ’c’
Se puede indicar que un número en realidad es
un carácter: ’\0’, es igual que 0
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 10
Tamaños de variables y tipos de dato
C no define tamaños concretos de tipos
Se debe usar siempre sizeof
sizeof (tipo) me da el tamaño de un tipo,
cuanto espacio hay reservado para él en
memoria
sizeof variable me da el tamaño de una
variable
Si meto un tipo más grande en uno más
pequeño, hay sorpresas
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 11
Tamaños de variables y tipos de dato
void
main(int argc, char *argv[])
{
int i;
char c;
print("sz char %d ", sizeof (char));
print("sz i %d\n", sizeof i);
i = 342;
c = i;
print("c = %d\n", c);
c = 300;
print("c = %d\n", c);
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 12
Tamaños de variables y tipos de dato
Compilando y ejecutando imprime:
sz char 1 sz i 4
c = 86
c = 44
El char se ha desbordado!!!.
El número que da está mal.
Asignar un int a un char no da ningún warning!!
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 13
Operaciones y tipos con signo
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
int i;
i = 10;
print("i vale %d\n", i);
i = i-11;
print("i = %d\n", i);
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 14
Operaciones y tipos con signo
$ 8c -FTVw main.c
$ 8l -o main main.8
$ ./main
i vale 10
i = -1
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 15
Operaciones y tipos con signo
Normalmente los enteros tienen signo
Para todos los tipos enteros se puede
especificar que tengan o no tengan signo
signed o unsigned
Sólo cambia las comparaciones (y shifts), no te
protege
Normalmente basta con usar int o char
simplemente.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 16
Operaciones y tipos con signo
int i;
unsigned int j;
i = -10;
print("i vale %d\n", i);
j = i;
print("j = %d\n", j);
print("j = %u\n", j);
Imprime:
i vale -10
j = -10
j = 4294967286
De nuevo ningún warning ni protección ¡Ojo!
El formato %u para imprimir sin signo
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 17
Operaciones variadas
int i;
i = 0;
print("i++ vale %d\n", i++);
print("++i vale %d\n", ++i);
print("i vale %d\n", i);
print("i = 3 vale %d\n", i = 3);
i += 8;
print("i vale %d\n", i);
Imprime:
i++ vale 0
++i vale 2
i = 3 vale 3
i vale 11
Cada expresión devuelve un valor (incluyendo
la asignación)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 18
Postincremento es: primero valor luego se
incrementa i++
Preincremento: primero incremento luego valor
++i
Tambien hay predecremento y postdecremento
−−
Asignación: evalúa al valor que se asigna
Ë a = 2 evalúa a 2
a = a + c; se puede poner cómo a += c;
Hay para todos los operadores += *= /= etc.
ojo las operaciones sobre enteros son enteras
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 19
Operaciones variadas
int i;
i = 13;
i = i / 2;
print("i vale %d\n", i);
i = 13;
i %= 2;
print("i vale %d\n", i);
i vale 6
i vale 1
/ es la división entera
% es el resto o módulo (mod)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 20
Operaciones variadas
No hay tipo booleano, un entero diferente de 0
es cierto
0 es falso
Los operadores de comparación son <= >= == >
< !=
Devuelven un entero que cumple lo de arriba
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 21
if
if (0)
print("es cierto\n"));
else
print("es falso");
Imprime:
es falso
la sentencia o bloque de sentencias del else se
ejecutan si es falsa la condición.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 22
Operaciones variadas
int i;
i = 13;
if (i == 13){
print("es igual\n"));
print("la la la\n");
}
Imprime
es igual
la la la
if considera el entero de forma lógica
i == 13 es una expresión y como tal retorna un
valor, algo diferente de 0
Se ejecuta el bloque, entre llaves.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 23
Operaciones variadas
int i;
i = 13;
if (i != 13)
print("es igual\n"));
print("la la la\n");
Imprime:
la la la
Obsérvese que el if solo afecta a una línea
porque no hay llaves y la sentencia es sólo el
print
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 24
Operaciones variadas
Los operadores "lógicos" son && || !
if ((10 == 13) || (3 > 2) || 0)
print("es cierto\n"));
Imprime:
es cierto
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 25
Operaciones variadas
Los operadores sobre bits son:
Ë ~ >> <<^ & | ^ ~ >> <<
¡Ojo! & es diferente de &&
¡Ojo! tienen poca precedencia
Ë a&b == c agrupa a & (b == c)
mejor no depender y poner paréntesis.
print("%x\n", 0xff & ~0x1);
fe
Imprime:
El formato %x imprime en hexadecimal
& hace el bitwise and (| hace el or)
~ es not bit a bit
<< >> son shifts con signo (si el tipo es con
signo)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 26
Bucles
int i;
i = 10;
while (i != 2){
print("i vale %d\n", i));
i/=2;
}
Imprime:
i vale 10
i vale 5
Es un bucle que se ejecuta mientras dura la
condición
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 27
Bucles
int i;
for(i = 0; i < 3; i++)
print("i vale %d\n", i));
Imprime:
i vale 0
i vale 1
i vale 2
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 28
Bucles
El for de C no es un bucle al uso
tiene dentro de los paréntesis dos sentencias
cualesquiera y una expresión:
Ë for(sentencia; expresión; sentencia){}
la primera sentencia una vez al comenzar
la comparación se evalúa al comenzar cada
vuelta para ver si "se continúa
la última sentencia al terminar cada vuelta
conviene no ser innovador y utilizar "idioms"
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 29
Bucles, for y while equivalente
El bucle:
for(i = 0; i < 5; i++){
print("hola\n");
}
Es equivalente a:
i = 0;
while(i < 5){
print("hola\n");
i++;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 30
break y continue
break
continue
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 31
continue
int i;
for(i = 0; i < 5; i++){
if(i == 3)
continue;
print("i vale %d\n", i));
}
Imprime:
i vale 0
i vale 1
i vale 2
i vale 4
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 32
break
int i;
i = 40;
while (i != 2){
print("i vale %d\n", i));
i/=2;
if(i < 20)
break;
}
Imprime:
i vale 40
i vale 20
i vale 10
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 33
Hay también un do while
Como el while, pero entra una vez al menos
do{
i++;
}while (i < 2)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 34
C: funciones, memoria
Gorka Guardiola Múzquiz
paurea@lsub.org
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 1
Funciones, declaración
int
mifuncion(int numero)
{
int otro;
otro = 3;
numero += otro;
print("el num es: %d", numero);
return otro;
}
mifuncion es una función como main
recibe como parámetro un entero
retorna un entero
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 2
Funciones, declaración
si no retornase nada, el tipo es void
si no recibe nada, el tipo es void
ojo, void tiene otros significados
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 3
Cabecera, declaración
la definición de una función tiene dos partes
cabecera y cuerpo
La cabecera declara la función, da su tipo
El bloque de código es el cuerpo (entre {})
similar a la declaración/definición de un int
Ë declaración ’ cabecera, "tipo argumentos,
tipo resultado"
Ë en un int sería "esta variable es int"
Ë definición ’ código (entre {})
Ë en un int sería "reserva aquí sizeof(int)
bytes"
Se puede escribir la cabecera sola:
int mifuncion(int numero);
véase el ;
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 4
Cabeceras y tipos de datos
No se puede usar una función sin haberla
declarado antes, la cabecera, o entera
en el fichero o en otros que se incluyen antes
que éste.
Esto no es especial para funciones
El compilador necesita haber visto el tipo de
datos antes de usarlo para hacer
comprobaciones. El enlazador sólo mira
símbolos, no comprueba tipos (bueno, salvo
por el -T).
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 5
Uso de la función
void
main(int argc, char *argv[])
{
mifuncion(4);
exits(nil);
}
int
mifuncion(int numero)
{
int otro;
otro = 3;
numero += otro;
print("el num es: %d", numero);
return otro;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 6
Uso de la función
Compilo:
$8c -FTVw func.c
$8l -o func func.o
bla.c:8: function args not checked: mifuncion
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 7
Así sí
int
mifuncion(int numero)
{
int otro;
otro = 3;
numero += otro;
print("el num es: %d", numero);
return otro;
}
void
main(int argc, char *argv[])
{
mifuncion(4);
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 8
Así tambien
int mifuncion(int numero);
void
main(int argc, char *argv[])
{
mifuncion(4);
exits(nil);
}
int
mifuncion(int numero)
{
int otro;
otro = 3;
numero += otro;
print("el num es: %d", numero);
return otro;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 9
La memoria
cat /proc/12/segment
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 10
0x00001000-0x0002e000 Text Segment R
0x0002e000-0x00037000 Data Segment
0x00037000-0x0017d000
Bss
0xdefff000-0xdffff000
Stack/Pila
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 11
La memoria
Los números son direcciones de memoria (no
nos importan mucho cuales concretamente,
sino su organización)
Una idea de la situación y cómo funciona
Pila/stack, montón/heap, texto, datos.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 12
¿Dónde va la memoria?
0x00001000-
Text’código
0x0002e000-
Data’globales i.
0x00037000-
Bss’globales n.i.
-
Bss’Heap
0xdefff000-
Stack’locales
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 13
La memoria
La flecha indica lo que voy a ejecutar, PC
#include <u.h>
#include <libc.h>
int global;
void
main(int argc, char *argv[])
{
→
global = 2;
global = 4;
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 14
La memoria
Texto
PC
global = 2
global = 4
exits(nil);
Datos
.............................................................................................................................................
global
© Gorka Guardiola Múzquiz C Introducción
0
Mar 4, 2009
Pg. 15
La memoria
#include <u.h>
#include <libc.h>
int global;
void
main(int argc, char *argv[])
{
global = 2;
→
global = 4;
exits(nil);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 16
La memoria
Texto
PC
global = 2
global = 4
exits(nil);
Datos
.............................................................................................................................................
global
© Gorka Guardiola Múzquiz C Introducción
2
Mar 4, 2009
Pg. 17
La memoria y las funciones
¿Y la memoria de las funciones?.
Argumentos y variables locales van a la pila
El valor de retorno va en un registro (AX, en
intel)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 18
Uso de la función en ejecución
void
main(int argc, char *argv[])
{
→ mifuncion(4);
exits(nil);
}
int
mifuncion(int numero)
{
numero = 3;
return 1;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 19
La memoria
Texto
main
PC
mifuncion(4);
exits(nil);
mifuncion
numero = 3;
return 1;
.............................................................................................................................................
Pila
...
SP’
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 20
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 21
Uso de la función en ejecución
void
main(int argc, char *argv[])
{
mifuncion(4);
exits(nil);
}
int
mifuncion(int numero)
{
→ numero = 3;
return 1;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 22
Texto
main
PC
mifuncion
mifuncion(4);
exits(nil);
numero = 3;
return 1;
Pila
.............................................................................................................................................
...
SP’
numero
4
PC (el exit)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 23
Uso de la función en ejecución
void
main(int argc, char *argv[])
{
mifuncion(4);
exits(nil);
}
int
mifuncion(int numero)
{
numero = 3;
→ return 1;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 24
Texto
main
mifuncion(4);
exits(nil);
mifuncion
PC
Pila
numero = 3;
return 1;
.............................................................................................................................................
...
SP’
numero
3
PC (el exit)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 25
Uso de la función en ejecución
void
main(int argc, char *argv[])
{
mifuncion(4);
→ exits(nil);
}
int
mifuncion(int numero)
{
numero = 3;
return 1;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 26
Texto
main
PC
mifuncion
mifuncion(4);
exits(nil);
numero = 3;
return 1;
.............................................................................................................................................
Pila
...
numero
SP’
© Gorka Guardiola Múzquiz C Introducción
3
PC (el exit)
Mar 4, 2009
Pg. 27
Observaciones
La pila no se borra, sólo avanza y retrocede el
puntero de pila, SP, sobreescribiendo las
antiguas posiciones.
El valor de retorno no está en la pila sino en un
registro (AX en un PC).
Nuestra función no tiene variables locales, pero
si las tuviese también van a la pila, como ya
hemos visto.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 28
Inicialización
La pila viene a un valor cualquiera, hay que
inicializar
Las variables globales siempre están
inicializadas a 0 (salvo que las inicialice).
Se inicializa poniendo, por ejemplo:
int a = 3;
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 29
C: tipos compuestos, punteros, módulos
Gorka Guardiola Múzquiz
paurea@lsub.org
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 1
struct
Son como los registros de Pascal/Ada
Tipos de datos definidos por el usuario
Agregan otros tipos de datos
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 2
Ejemplo:
struct
int
int
};
struct
Point{
x;
y;
Point p;
void
mifuncion(void)
{
p.x = 3;
p.y = 4;
print("P is [%d. %d]\n", p.x, p.y);
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 3
Explicación del ejemplo:
Son 3 partes
Declaración del tipo (struct Point)
Declaración/definición de la variable (p)
Uso (p.x)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 4
Explicación del ejemplo:
Declaración del tipo (struct Point)
struct Point{
int x;
int y;
};
Esto declara un tipo de datos (como int)
El tipo de datos se llama struct Point
sizeof (struct Point) es la suma de sizeof de
los campos
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 5
Explicación del ejemplo:
Declaración/definición de la variable (p)
struct Point p;
Como cualquier otra variable, es un trozo de
memoria
La struct en sí no ocupa, es como si me
declarase cada uno de los tipos que contiene
sueltos.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 6
Explicación del ejemplo:
Si, por ejemplo me declaro estas dos globales:
struct Point p;
struct Point q;
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 7
Explicación del ejemplo: La memoria
Bss
p
q
x
0
y
0
x
0
y
0
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 8
Explicación del ejemplo: La memoria
sizeof(struct Point) =
= sizeof(int) + sizeof(int)
struct Point{
int x;
int y;
};
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 9
Explicación del ejemplo: Uso
p.x = 3;
Accedo a los campos desde la variable con .
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 10
Una struct dentro de otra
struct Rect{
struct Point ul;
struct Point dr;
};
struct Rect r;
void
otrafunc(void)
{
r.ul.x = 3;
r.dl.y = 4;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 11
typedef, malo
typedef es una forma de dar otros nombres
No define tipos, sólo les da nombres
En general, mala idea
Ë Especialmente mala idea esconder *
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 12
typedef, útil
struct Nombre ’ Nombre, más corto
Convenio para saber qué son structs
Ë En Plan 9, con mayúsculas Nombre
Se puede hacer typedef struct Nas Nas; sin
haber definido la struct Nas;
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 13
typedef: ejemplo
typedef struct Point Point;
struct Point{
int x;
int y;
};
Point p;
void
otrafunc(void)
{
p.x = 3;
print("sz Pnt %d", sizeof (Point));
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 14
Constantes, enum
La forma en C es usar enum
enum {
Total = 23,
Nlitros = 42,
};
Define valores enteros
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 15
Constantes, enum
Se le puede dar nombre al tipo, pero no se usa
mucho, es similar a typedef
enum Colors {
White = 0x0,
Blue = 0x00ff00,
};
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 16
Constantes, enum
Si no se le da valor, toma el anterior+1;
El primero tiene valor 0
enum {
Twrite, //vale 0
Tread, //vale 1
Topen = 28,
Tclose, //vale 29
};
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 17
punteros, introducción
Un puntero en C se declara con un *.
char *c;
Un puntero no es más que un entero "especial"
El tipo del puntero es (en el ejemplo) char *
Otro ejemplo:
int *i;
Su tipo es int *
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 18
punteros, introducción
Un puntero es una dirección de memoria que
"apunta a otra"
El puntero p apunta a la posición marcada
como x
p
x
0x0000600c
a
n
t
e
© Gorka Guardiola Múzquiz C Introducción
0x6000
0x6004
0x6008
0x600c
0x6010
Mar 4, 2009
Pg. 19
punteros
Un puntero es un entero
Apunta a otra variable, contiene su dirección
Se pueden sumar y restar, con unas reglas
especiales (aritmética de punteros).
Hay un valor especial, nil (en realidad 0) que
significa no apuntar a nada.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 20
punteros, &, *
La dirección de una variable se obtiene con &
El contenido de la variable a la que apunta el
puntero es *
Por ejemplo:
char *p;
char c = ’a’;
Y dentro de una función:
p = &c;
*p vale ’a’
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 21
punteros, &, *
La dirección de una variable se obtiene con &
El contenido de donde apunta un puntero *
p
0x00006004
0x6000
c
a
0x6004
En el dibujo *p es ’a’
En el dibujo &c es 0x6004
p vale 0x6004
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 22
punteros, aritmética y tipo
Un puntero apunta a un tipo de dato
char * apunta a char
Esto tiene dos consecuencias:
Ë Si le sumo 1 al puntero, en realidad le sumo
sizeof(tipo al que apunta)
Ë El contenido del puntero es del tipo al que
apunta
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 23
punteros, −>
El operador p−>x para acceder a campos de
struct
Cuando tengo un puntero a la struct
Es una forma mejor de escribir (*p).x
Son completamente equivalentes
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 24
punteros, arrays
No hay arrays de verdad en C.
Hay una notación para declararse punteros
constantes
Y otra notación para indexar punteros
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 25
array, ejemplo
char c[4];
En realidad c es un puntero constante que
apunta a la primera posición del array, que son
4 posiciones de tamaño sizeof (char)
c en sí no ocupa nada, es un valor constante.
c 0x6000
0
0x6000
0
0x6004
0
0x6008
0
0x600c
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 26
array, ejemplo
char c[27];
Estas dos sentencias:
c[3] = ’t’;
*(c+3) = ’t’;
hacen lo mismo, c[3] es igual que *(c+3)
funciona sobre punteros y sobre arrays, igual
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 27
punteros, strings
No hay strings en C
Hay una notación para inicializar la memoria de
una forma especial "asassa"
Por convenio un puntero a char en el que la
memoria a la que apunta contiene carácteres y
acaba en \0 se llama string.
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 28
Ejemplos de punteros, arrays, strings
char gs[4] = "eco";
void
mifuncion(void)
{
char *s;
→s = gs;
s[2] = ’c’;
return;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 29
Texto
Datos
Pila
PC
mifuncion
s = gs;
s[2] = c;
return;
...
.............................................................................................................................................
gs 0x6040
e
0x6041
c
0x6042
o
0x6044
\0
...
...
.............................................................................................................................................
SP’
...
s: 0x587585
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 30
Ejemplos de punteros, arrays, strings
char gs[4] = "eco";
void
mifuncion(void)
{
char *s;
s = gs;
→s[2] = ’c’;
return;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 31
Texto
mifuncion
s = gs;
s[2] = c;
PC
return;
...
.............................................................................................................................................
Datos
gs 0x6040
e
0x6041
c
0x6042
o
0x6044
\0
...
...
.............................................................................................................................................
Pila
SP’
...
s: 0x6040
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 32
Ejemplos de punteros, arrays, strings
char gs[4] = "eco";
void
mifuncion(void)
{
char *s;
s = gs;
→s[2] = ’c’;
return;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 33
Texto
mifuncion
PC
s = gs;
s[2] = c;
return otro;
...
.............................................................................................................................................
Datos
gs 0x6040
e
0x6041
c
0x6042
c
0x6044
\0
...
...
.............................................................................................................................................
Pila
SP’
...
s: 0x6040
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 34
punteros, strings, funciones
strcmp, strncmp, strcpy, strlen, strncat
mirar página de manual
reciben char *
memoria reservada!!
al final del array un \0 (strings)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 35
int
strcmp(char *s1, char *s2)
{
unsigned c1, c2;
for(;;) {
c1 = *s1++;
c2 = *s2++;
if(c1 != c2) {
if(c1 > c2)
return 1;
return -1;
}
if(c1 == 0)
return 0;
}
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 36
Ejemplos de punteros, arrays, strings
long
strlen(char *s)
{
long n;
n = 0;
while(*s++)
n++;
return n;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 37
Ejemplos de punteros, arrays, strings
long
strlen(char *s)
{
long n;
for(n = 0; *s!= ’\0’; s++)
n++;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 38
Ejemplos de punteros, arrays, strings
long
strlen(char *s)
{
long n;
for(n = 0; s[n]!=’\0’; n++)
;
return n;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 39
Ejemplos de punteros, arrays, strings
long
strlen(char *s)
{
return strchr(s, 0) - s;
}
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 40
punteros, malloc, free, memset
malloc pide un trozo de memoria en el montón
(heap)
la memoria que da malloc se puede usar hasta
hacer free
free le dice al que lo reserva que se lo puede
asignar a otro (liberar)
memset escribe un carácter n veces en
memoria
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 41
Ejemplos de punteros, arrays, strings
int *p;
p = malloc(sizeof(int)*10);
if(p == nil)
... manejo el error
memset(p, 0, sizeof(int)*10);
p[3] = 28;
free(p);
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 42
Ejemplos de punteros, arrays, strings
Siempre que llame a una función de
librería/llamada al sistema
Ë ver qué devuelve cuando hay un error
Ë comprobar qué devuelve
Ë manejar el error
si no pone qué devuelve en caso de error
Ë caso por defecto mirar intro(2)
man 2 intro
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 43
punteros, broken, stack
si intento acceder a una zona de memoria que
no tengo permiso, el programa casca
la primera página de memoria está protegida
(de 0 a 4k) contra lectura y escritura.
cualquier intento de atravesar * un puntero a
nil, por ejemplo, casca
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 44
punteros, broken, stack
$ ./hello
hello 601: suicide: sys: trap: fault read
addr=0x0 pc=0x00001261
$ ps|grep Broken
paurea
601
0:00
0:00
24K Broken
b
Puedo ver su pila para ver dónde se quedó y a
qué ha llamado con: $ stack hello
• O también con el pid
$ stack 601
No hace falta que esté roto
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 45
cast
cast es convertir un tipo a otro
los enteros promocionan unos a otros en C
para el resto se puede hacer explícitamente (tú
sabes lo que haces) poniendo el tipo entre
paréntesis
Por ejemplo: char *cp;
int *ip;
ip = (int *)cp;
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 46
void *
sirve para apuntar a "cualquier cosa"
es simplemente una dirección de memoria
hay que hacer cast antes de usarlo
la promoción void * → asdfa * es automática
la promoción asdfa *→ void * requiere un cast
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 47
El preprocesador (cpp)
todo lo que empieza con #
hace sustituciones textuales antes de la
compilación
las sustituciones no rompen tokens
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 48
El preprocesador (cpp)
#include
Ë Mis .h, se buscan aquí
#include <bla.h>
Ë los .h del sistema, se buscan en
/sys/include
Ë es la forma estándar de usar librerías y
demás
Ë #include significa literalmente incluye ahí
ese fichero
No pongo includes en los .h!
No pongo código en los .h, sólo
declaraciones de tipos, constantes!
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 49
El preprocesador (cpp)
#define Nbytes 3
Ë mejor usar enum
#ifdef ... en general compilación condicional
Ë mejor evitar (qué es lo que de verdad se
compila?)
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 50
nm y el proceso de compilación
La tabla de símbolos
extern sólo declaración (necesito un símbolo)
Ë alguien se ha declarado la variable en otro
fichero extern int a;
static local al ámbito (no exportes el símbolo)
Ë nadie puede ver esta variable fuera de este
ámbito (un fichero, por ejemplo)
Ë variable en el segmento de datos (como una
global, pero no se puede usar fuera) static
int a;
Ë para funciones y variables
nm sobre objetos y ejecutables para imprimir la
tabla de símbolos
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 51
Inicialización
char *s = "hola";
es muy diferente de:
char s[5] = "hola";
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 52
Inicialización
char *s = hola";
declara un puntero
en la zona de datos reserva 5 caracteres
consecutivos
los rellena con con h o l a \0
mete en s la dirección del primer carácter.
se puede hacer en dos pasos:
Ë char *s;
Ë s = "hola";
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 53
Inicialización
char s[5] = "hola";
no es una asignación (no se puede hacer en dos
pasos)
declara un array con su memoria "aquí"
Ë si la variable es global ’ datos
Ë si la variable es local ’ pila
rellena la memoria con h o l a \0
el puntero no se puede modificar
© Gorka Guardiola Múzquiz C Introducción
Mar 4, 2009
Pg. 54
Descargar