A linguagem C é amplamente reconhecida por sua flexibilidade e proximidade com o hardware, características proporcionadas por um conjunto robusto de operadores e palavras-chave. Este artigo explora elementos essenciais para a construção de programas eficiantes e bem estruturados.
- Operadores em C
1.1 Operadores Aritméticos
Os operadores básicos incluem soma (+), subtração (-), multiplicação (*), divisão (/) e módulo (%).
#include <stdio.h>
int main() {
int res_int = 10 / 3; // Resultado: 3 (divisão inteira)
float res_float = 10 / 3.0; // Resultado: 3.333... (divisão de ponto flutuante)
int resto = 10 % 3; // Resultado: 1 (resto da divisão)
printf("Inteiro: %d\n", res_int);
printf("Float: %.2f\n", res_float);
printf("Resto: %d\n", resto);
return 0;
}
1.2 Atribuição Composta
C permite simplificar operações matemáticas seguidas de atribuição através de operadores como +=, -=, *=, entre outros.
int x = 5;
x += 10; // Equivalente a x = x + 10 (x agora é 15)
x *= 2; // Equivalente a x = x * 2 (x agora é 30)
1.3 Operadores Unários
Operadores unários atuam sobre um único operando. Exemplos comuns são o incremento (++) e decremento (--).
int valor = 10;
int pos = valor++; // 'pos' recebe 10, depois 'valor' torna-se 11 (pós-incremento)
int pre = ++valor; // 'valor' torna-se 12, depois 'pre' recebe 12 (pré-incremento)
size_t tamanho = sizeof(int); // Retorna o tamanho do tipo em bytes
1.4 Operador Condicional (Ternário)
Uma forma compacta de representar uma estrutura if-else.
int a = 50, b = 100;
int maior = (a > b) ? a : b; // Se a > b, retorna a; caso contrário, retorna b.
- Palavras-chave de Controle e Escopo
2.1 typedef
Utilizado para criar apelidos (aliases) para tipos de dados existentes, melhorando a legibilidade do código.
typedef unsigned long ulong;
int main() {
ulong contador = 1000;
return 0;
}
2.2 static
A palavra-chave static altera o tempo de vida e a visibilidade de variáveis e funções:
- Variáveis Locais Estáticas: Mantêm seu valor entre chamadas de função e são armazenadas no segmento de dados, não na pilha.
- Variáveis/Funções Globais Estáticas: Limitam o escopo ao arquivo onde foram declaradas (linkage interna).
void contador_chamadas() {
static int cont = 0; // Inicializada apenas uma vez
cont++;
printf("Execução número: %d\n", cont);
}
2.3 register
Sugere ao compilador que a variável seja armazenada em um registrador da CPU para acesso mais rápido, embora o compilador possa ignorar essa sugestão.
- Pré-processamento: #define
O #define é usado para criar constantes simbólicas ou macros.
#define PI 3.14159
#define QUADRADO(x) ((x) * (x))
int main() {
float area = PI * QUADRADO(5); // Substituído antes da compilação
return 0;
}
- Ponteiros e Endereçamento de Memória
A memória do computador é organizada em unidades chamadas bytes, cada uma com um endereço único. Um ponteiro é uma variável que armazena esse endereço.
int main() {
int n = 42;
int *ptr = &n; // 'ptr' armazena o endereço de 'n'
printf("Endereço: %p\n", (void*)ptr);
printf("Valor via ponteiro: %d\n", *ptr); // Desreferenciação
*ptr = 100; // Altera o valor de 'n' através do ponteiro
return 0;
}
O tamanho de um ponteiro depende da arquitetura do sistema: 4 bytes em sistemas de 32 bits (x86) e 8 bytes em sistemas de 64 bits (x64).
- Estruturas (struct)
As estruturas permitem agrupar diferentes tipos de dados sob um único nome, facilitando a representação de objetos complexos.
struct Produto {
char nome[50];
float preco;
int estoque;
};
void exibir(struct Produto *p) {
// Acesso via operador seta para ponteiros
printf("Produto: %s - Preço: %.2f\n", p->nome, p->preco);
}
int main() {
struct Produto p1 = {"Teclado", 150.00, 10};
exibir(&p1);
return 0;
}