struct identificador-nombre {
tipo1 componente1;
tipo2 componente2;
...
tipoN componenteN;
} lista_variables;
struct point {
int x;
int y;
};
struct point punto;
/* var tipo point */
struct point puntoMax = {640, 480};
punto.x = 300; /* acceso al elemento con */
punto.y = 200; /* sintaxis operador punto */
punto.x = 300;
struct point A = {640, 480}, B;
struct point *pA,*pB;
pA = &A; pB = &B;
pB -> x = pA -> x;
pB -> y = 200; // B = {640,200}
struct point sumaPuntos (struct point p1,
struct point p2);
struct point sumaPuntos (struct point p1,
struct point p2) {
p1.x += p2.x;
p1.y += p2.y;
return p1;
}
a2.nota1 = 7.5;
a2 = a1;
La copia es como un memcpy(), byte a byte. Pero existe el problema de "shallow copy" si tenemos punteros dentro de la estructura (Articulo (EN), presentacion (EN), y resumen (HTML).
struct Alumnos a = {"Celeste Carballo",
"7654321",
6.0, 5.5, 5.0, 5.5};
struct Alumnos nuevoAlumno(char nombre[ ]) { ...
void calculaNota(struct Alumnos a1) { ...
struct fecha {
int dia, mes, anio;
};
struct persona {
char nombre[20];
char apellido[20];
struct fecha nacimiento;
unsigned long telefono;
};
struct persona amigo[30]; /* array */
amigo[15].nacimiento.anio = 1982;
struct point {
int x;
int y;
};
typedef struct point punto;
punto A,B;
A.x =1;
Uso de typedef para independizarse del compilador
Dependiendo del compilador elijo que definicion usar
/* Si tengo el tipo de dato bit disponible */
typedef bit bool;
/* Si no lo tengo disponible */
typedef char bool;
/* Si mi compilador soporta C99 */
typedef _BOOL bool;
Es importante en estructuras (así como con tipos de datos simples) utilizar el operador sizeof para averiguar su tamaño.
Esto es así por que queremos escribir programas portables, y para que sean portables debemos averiguar el tamaño de cada dato en tiempo de compilación.
Un detalle de color en intel 64bits es que dependiendo del orden puede ocupar distinto tamaño los mismos datos, dependiendo del orden. El mínimo a reservar en un campo será 4bytes. La única excepción será si puede "empacarlos" (ver en el ejemplo "estructuras.c" el tipo de datos_t4).
Articulos (EN): "Data structure alignment (Wikipedia)" & "Coding for Performance (Intel)".
union equivalencia {
short i;
char b[2];
};
union equivalencia x;
x.i = 0x4892;
printf("%x",x.b[0]);
printf("%x",x.b[1]);
typedef unsigned char uchar;
struct hexa {
uchar nl:4;
uchar nh:4;
};
union byte {
uchar b;
struct hexa h;
};
union byte A;
char str[3];
A.b=0x48;
printf("%d",A.h.nh); /* Muestra 4 */
printf("%d",A.h.nl); /* Muestra 8 */
/* Convirtiendo en string */
str[0] = '0' + A.h.nh; // Version simplificada
str[1] = '0' + A.h.nl; // Falta 'A', ver union_ej2.c
str[2] = NULL;
Recordemos las operaciones lógicas (vistas previamente)
&& : AND logico
& : AND binario (bit a bit)
A B R
0 0 0 --> Como A esta en 0 vale 0
0 1 0 --> Como A esta en 0 vale 0
1 0 0 --> Como A esta en 1 vale B
1 1 1 --> Como A esta en 1 vale B
=> Para poner en 0 usamos una AND
|| : OR logico
| : OR binario (bit a bit)
A B R
0 0 0 --> Como A esta en 0 vale B
0 1 1 --> Como A esta en 0 vale B
1 0 1 --> Como A esta en 1 vale 1
1 1 1 --> Como A esta en 1 vale 1
=> Para poner en 1 usamos una OR
Acceder a los bits de un byte utilizando una mascara:
bits-de-un-byte-mascara.c
Recordemos los Operadores (vistos previamente)
masc_b0 = 0x01; // 0000'0001
masc_b1 = 0x02; // 0000'0010
masc_b2 = 0x04; // 0000'0100
masc_b3 = 0x08; // 0000'1000
byte = 0xFF; // 1111'1111
res0 = byte & masc_b0; // 0000'0001
res = res0 >> 0; // 0000'0001
res1 = byte & masc_b1; // 0000'0010
res = res1 >> 1; // 0000'0001
res2 = byte & masc_b2; // 0000'0100
res = res2 >> 2; // 0000'0001
Si bien esto no está soportado directamente por C, usando desplazamiento y mascaras se puede lograr también rotar. Y ciertos compiladores con GCC pueden detectar este código y traducirlo correctamente a una operación de assembler de rotación.
unsigned int data=0x0F;
data= data>> (unsigned) 1 | data<< (unsigned)31;
compiles to ASM:
ror %eax
Rotando (además de desplazando) bits: bit_rotate.c
Ejemplos de desplazamiento y rotación bit a bit: operadores_bits_y_rotacion.txt
enum {lista_de_identificadores};
typedef enum {FALSE = 0, TRUE = 1} boolean;
#include <stdlib.h>
int *p;
p = (int *) malloc( sizeof(int) );
Por ejemplo, puedo crear un string en forma dinámica:
#include <stdlib.h>
#include <stdio.h>
void main(void) {
char *str, tam;
printf("Ingrese el tamaño de cadena deseado: ");
scanf("%d",&tam);
str = (char *) malloc ( sizeof(char) * tam );
printf("Ingrese su cadena: ");
scanf("%s",str);
printf("\nSu cadena es: %s",str);
}
Pero no solo de chars...
De cualquier tipo de dato puedo pedir...
¡Incluso estructuras!
struct vendedor {
char nom[40];
float com,acum;
int vent;
} *vec;
/* Creo un vector de 10 posiciones dinamicamente */
vec = (struct vendedor *) malloc( sizeof( struct vendedor ) * 10);
#define FIL 5
#define COL 5
void main(void) {
int **v, i, j;
v = malloc(sizeof(*int)*FIL);
for(i=0;i<FIL;i++) {
v[i] = malloc(sizeof(int)*COL);
srandom(15);
for(i=0;i<FIL;i++) {
for(j=0;j<COL;j++) {
...
void *p = NULL;
struct vendedor *q, *r;
q = (struct vendedor *) malloc ( sizeof(struct vendedor) );
r = (struct vendedor *) malloc ( sizeof(struct vendedor) * 10 );
struct vendedor **vp[100];
struct nodo {
struct vendedor dato;
struct nodo *sig;
};
struct nodo *p1;
Realizar un programa que maneje el ingreso de vendedores.
Debe poder agregarse un vendedor y luego agregar ventas de ese vendedor.
Se debera poder listar las ventas durante el mes, y al final del mes se debe generar un cierre del mes informando el monto total de las ventas y comisiones a pagar.
Las comisiones son 10% del monto vendido por vendedor.