(É como criar um tipo no Haskell)

struct s {
	int sp;
	int valores [Max];
};

struct s a ;
// Array de structs
struct s b [40]; 

// a componente sp de a passa a 5
a.sp = 5;
a.valores[3] = 42;
v[2].sp = 3;
b[3].valores[5] = 44;
// Agora Student pode estocar 4 diferentes elementos
struct Student {
	char name [50] ;
	char major [50] ;
	int age ;
	double gpa ;
}

int main () {

	struct Student student1 // Student é a caixa aonde os estudantes fão ficar guardados
                          // student1 é o nome do elemento que estamos a por nessa caixa
	student1.age = 22 ;     // desta maneira mudamos a variável age que está no student1
  student1.gpa = 3.2 ;
//student1.name = "Pedro" - NãO funciona em uma struct
	strcpy ( student1.name, "Jim") ;      // desta maneira podemos guardar uma string
  strpcy ( student1.name, "Business") ; // dentro de uma variável

   // Podemos criar quantos quisermos (student neste caso, por exemplo student2)

printf (%f, student1.age) // desta maneira podemos usar qualquer elemento guardado
                          // dentro da struct 
struct s {
	int sp;
	int valores [Max];
};

	int x[10] , y[10];

	struct s a, b;

	--> Difenças entre struct e array :

	1)
	x = y --> ERRADO
	a = b --> CORRETO (complexo em tempo de cpu)

	2)
	passagem como argumento :
	int f (int v[], int N); --> esta função recebe um endereço
	int g (struct s a);

int main () {

	int x [400];
	f (x, 400); --> O endereço de onde começa o array é enviado pela função
		1 : Não é feita uma cópia do array
		2 : Quaisquer alterações feitas no array pela função são guardadas

	struct s xxxx;
	g (xxxx);
		1 : É feita uma cópia do argumento (cada chamada da função -> uma cópia da struct : computacionalmente relevante)
		2 : Quaisquer alterações feitas à struct pela função não são visiveis do exterior
}	

--> É possível returnar uma struct embora computacionalmente seja demorado.

---------------------- stack ----------------------
| push  : acrescentar um elemento                 |
| pop   : retirar um elemento                     |
| top   : qual o proximo elemento a ser retirado  |
| empty : Saber se a stack está vazia             |
--------------------------------------------------|

int A; --> A é uma variável do tipo int
typedef int B; --> B é um tipo equivalente a int // typedef basicamente cria uma abreviatura de tipo
B x; --> X é uma variável do tipo B. i.e., int 

-------- Exemplo : implementaçāo de stack de inteiros --------------------------------------------------------------------------

typedef struct stack {
	int valores [100];
	int quantos;
} STACK;

// os valores são inseri“dos da esquerda para a direita

STACK push (int x, STACK s) {
	s.valores [s.quantos++] = x;
	return s;
}

STACK pop (STACK s) {
	s.quantos--;
}

int top (STACK s) {
	return (s.valores [s.quantos - 1]);
}

int empty (STACK s) {
	return (s.quantos == 0);
}

Usar endereços de memória em structs :

void push (int x, STACK *s) {
	(*s).valores [(*s).quantos++] = x;
}

void pop (STACK *s) {
	(*s).quantos--;
}

int top (STACK *s) {
	return ((*s).valores [(*s).quantos - 1]);
}

int empty (STACK *s) {
	return ((*s).quantos == 0);
}

int main () {
	STACK s1;
	int aaa;
	s1.quantos = 0;
	push (3,&s1);
	aaa = top (&s1);
	return 0;
}

Abreviatura para (*a).b : a é um endereço de uma struct que tem um campo b Em vez de escrever (*a).b —> a→b

void push (int x, STACK *s) {
	(s->valores [(s->quantos++] = x;
}

void pop (STACK *s) {
	s->quantos--;
}

int top (STACK *s) {
	return (s->valores [s->quantos - 1]);
}

int empty (STACK *s) {
	return (s->quantos == 0);
}

int main () {
	STACK s1;
	int aaa;
	s1.quantos = 0;
	push (3,&s1);
	aaa = top (&s1);
	return 0;
}

Neste caso, estou a definir 2 tipos : → STACK que é o mesmo que struct stack. → SStack que é o endereço de STACK

typedef struct stack {
	int valores [100];
	int quantos;
} STACK, *SStack;

void push (int x, SStack) {
	(s->valores [(s->quantos++] = x;
}

void pop (SStack) {
	s->quantos--;
}

int top (SStack) {
	return (s->valores [s->quantos - 1]);
}

int empty (SStack) {
	return (s->quantos == 0);
}

int main () {
	STACK s1;
	int aaa;
	s1.quantos = 0;
	push (3,&s1);
	aaa = top (&s1);
	return 0;
}

Link para Alocação de Memória