# 2. Estruturas Condicionais e Repeticao

## Introdução

As estruturas de controle em C e C++ determinam o fluxo de execução do programa. Diferente do PHP, que possui tipagem dinâmica e conversões automáticas, C/C++ exige que as condições sejam expressões que resultem em um valor **booleano** (em C, qualquer valor diferente de zero é considerado verdadeiro). O controle rigoroso de tipos e a ausência de "type juggling" tornam o comportamento mais previsível, mas exigem atenção redobrada em operações com ponteiros e inteiros.

## Estruturas Condicionais

{% stepper %}
{% step %}

### if, else if e else

A estrutura condicional mais básica avalia uma expressão e executa blocos de código conforme o resultado.

```c
int status = 403;

if (status == 200) {
    printf("Sucesso\n");
} else if (status == 403) {
    printf("Proibido\n");
} else {
    printf("Erro inesperado\n");
}
```

**Comportamento do Computador:**

* O compilador gera código que avalia a expressão dentro dos parênteses.
* Se o resultado for diferente de zero (verdadeiro em C), executa o bloco correspondente.
* Em C++, a expressão deve ser booleana ou conversível para bool.
* O bloco `else` é opcional e executa quando nenhuma condição anterior foi verdadeira.

#### Valores Verdadeiros em C

Em C, qualquer valor diferente de zero é considerado verdadeiro.

```c
int condicao = 1;
if (condicao) {           // Verdadeiro (1)
    printf("Executa\n");
}

if (10) {                 // Verdadeiro (qualquer != 0)
    printf("Sempre executa\n");
}

if (0) {                  // Falso
    printf("Nunca executa\n");
}
```

#### Operadores Relacionais e Lógicos

| Operador | Descrição        | Exemplo           |
| -------- | ---------------- | ----------------- |
| `==`     | Igual a          | `a == b`          |
| `!=`     | Diferente de     | `a != b`          |
| `>`      | Maior que        | `a > b`           |
| `<`      | Menor que        | `a < b`           |
| `>=`     | Maior ou igual   | `a >= b`          |
| `<=`     | Menor ou igual   | `a <= b`          |
| `&&`     | E lógico (AND)   | `a > 0 && a < 10` |
| \`       |                  | \`                |
| `!`      | NÃO lógico (NOT) | `!flag`           |

```c
int idade = 20;
int tem_carteira = 1;

if (idade >= 18 && tem_carteira) {
    printf("Pode dirigir\n");
}

if (!tem_carteira) {
    printf("Não pode dirigir\n");
}
```

{% endstep %}

{% step %}

### Operador Ternário (`? :`)

Forma compacta de if-else para atribuições simples.

```c
int idade = 20;
char *status = (idade >= 18) ? "Maior" : "Menor";
printf("%s\n", status);  // Maior
```

**Comportamento do Computador:**

* Avalia a expressão antes do `?`.
* Se verdadeira, retorna o valor entre `?` e `:`.
* Se falsa, retorna o valor após `:`.
* Ambos os valores devem ser do mesmo tipo (ou conversíveis).
  {% endstep %}

{% step %}

### Switch Case

Útil para múltiplas comparações com uma única variável.

```c
int servico = 80;

switch (servico) {
    case 22:
        printf("SSH\n");
        break;
    case 80:
        printf("HTTP\n");
        break;
    case 443:
        printf("HTTPS\n");
        break;
    default:
        printf("Desconhecido\n");
}
```

**Comportamento do Computador:**

* Avalia a expressão do `switch` uma única vez.
* Compara com cada `case` usando igualdade (`==`).
* Executa o bloco do `case` correspondente.
* **`break`** é essencial para sair do switch; sem ele, ocorre **fall-through** (execução dos cases seguintes).
* `default` é opcional e executa se nenhum case corresponder.

#### Fall-through (Comportamento Sem Break)

```c
int valor = 2;

switch (valor) {
    case 1:
        printf("Um\n");
    case 2:
        printf("Dois\n");  // Executa este
    case 3:
        printf("Três\n");  // E este também (fall-through)
        break;
    default:
        printf("Default\n");
}
// Saída:
// Dois
// Três
```

{% endstep %}
{% endstepper %}

## Estruturas de Repetição (Loops)

{% stepper %}
{% step %}

### for

Usado quando se conhece o número de iterações.

```c
for (int i = 0; i < 5; i++) {
    printf("Iteração %d\n", i);
}
```

**Comportamento do Computador:**

1. **Inicialização**: Executa `int i = 0` uma vez.
2. **Condição**: Avalia `i < 5`. Se verdadeira, entra no loop.
3. **Corpo**: Executa o bloco de código.
4. **Incremento**: Executa `i++`.
5. Repete passos 2-4 até a condição ser falsa.

#### for com Múltiplas Variáveis

```c
for (int i = 0, j = 10; i < j; i++, j--) {
    printf("i=%d, j=%d\n", i, j);
}
```

{% endstep %}

{% step %}

### while

Executa enquanto a condição for verdadeira.

```c
int conectado = 0;
int tentativas = 0;

while (conectado == 0 && tentativas < 3) {
    printf("Tentando conectar...\n");
    tentativas++;
    // Simula conexão bem-sucedida na terceira tentativa
    if (tentativas == 3) {
        conectado = 1;
    }
}
```

**Comportamento do Computador:**

* Avalia a condição **antes** de cada iteração.
* Se a condição for falsa na primeira vez, o corpo nunca é executado.
* Útil quando o número de iterações é desconhecido.
  {% endstep %}

{% step %}

### do-while

Executa o corpo pelo menos uma vez antes de verificar a condição.

```c
int opcao;

do {
    printf("Digite 1 para continuar: ");
    scanf("%d", &opcao);
} while (opcao != 1);
```

**Comportamento do Computador:**

* Executa o bloco **antes** de verificar a condição.
* Garante pelo menos uma execução.
* Útil para menus e validação de entrada.
  {% endstep %}
  {% endstepper %}

## Controle de Fluxo: break e continue

### break

Sai imediatamente do loop mais interno.

```c
for (int i = 0; i < 10; i++) {
    if (i == 5) {
        break;  // Sai do loop quando i == 5
    }
    printf("%d ", i);
}
// Saída: 0 1 2 3 4
```

### continue

Pula para a próxima iteração do loop.

```c
for (int i = 0; i < 5; i++) {
    if (i == 2) {
        continue;  // Pula a iteração quando i == 2
    }
    printf("%d ", i);
}
// Saída: 0 1 3 4
```

## Estruturas Condicionais com Ponteiros

Ponteiros podem ser usados em condicionais para verificar nulidade e comparação.

```c
int *ptr = malloc(sizeof(int));

if (ptr == NULL) {
    printf("Erro: memória insuficiente\n");
    exit(1);
}

*ptr = 42;

if (ptr != NULL) {
    printf("Valor: %d\n", *ptr);
    free(ptr);
}
```

### Comparação de Ponteiros

```c
int a = 10, b = 20;
int *p1 = &a;
int *p2 = &b;
int *p3 = &a;

if (p1 == p3) {
    printf("Apontam para o mesmo endereço\n");  // Executa
}

if (p1 != p2) {
    printf("Apontam para endereços diferentes\n");  // Executa
}
```

## Operador sizeof em Condicionais

`sizeof` é avaliado em tempo de compilação e retorna o tamanho em bytes.

```c
int arr[10];

if (sizeof(arr) > 40) {
    printf("Array grande\n");
} else {
    printf("Array pequeno\n");
}
```

## Expressões Aritméticas como Condições

Em C, qualquer expressão que resulte em zero é falsa, diferente de zero é verdadeira.

```c
int x = 10;
int y = 0;

if (x) {           // Verdadeiro (10 != 0)
    printf("x não é zero\n");
}

if (!y) {          // Verdadeiro (y == 0)
    printf("y é zero\n");
}

// Comum em programação C
if (ptr) {         // Equivalente a if (ptr != NULL)
    *ptr = 42;
}
```

> Em C++, expressões que não são booleanas em condicionais ainda são permitidas, mas geram warnings. Use `bool` ou comparações explícitas para código mais seguro.

## C++ Específico: Inicialização Condicional (if/switch com inicializador)

C++17 introduziu inicializadores em `if` e `switch`, limitando o escopo da variável.

```cpp
#include <iostream>
#include <string>

std::string obter_nome() {
    return "Alice";
}

int main() {
    // Variável 'nome' existe apenas dentro do if
    if (std::string nome = obter_nome(); !nome.empty()) {
        std::cout << "Nome: " << nome << std::endl;
    } else {
        std::cout << "Nome vazio" << std::endl;
    }
    // nome não é acessível aqui
}
```

## C++ Específico: Range-based for (C++11)

Simplifica iteração sobre containers e arrays.

```cpp
#include <iostream>
#include <vector>

int main() {
    int numeros[] = {1, 2, 3, 4, 5};
    
    // Range-based for
    for (int n : numeros) {
        std::cout << n << " ";
    }
    // Saída: 1 2 3 4 5
    
    std::vector<std::string> nomes = {"Alice", "Bob", "Charlie"};
    
    // Com referência para evitar cópia
    for (const auto& nome : nomes) {
        std::cout << nome << std::endl;
    }
}
```

## Boas Práticas

{% stepper %}
{% step %}

### Use chaves `{}` mesmo para blocos de uma linha

```c
// Ruim
if (condicao)
    printf("Executa\n");

// Bom
if (condicao) {
    printf("Executa\n");
}
```

{% endstep %}

{% step %}

### Evite comparações desnecessárias com booleanos

```c
// Ruim
if (flag == true) { ... }

// Bom
if (flag) { ... }
```

{% endstep %}

{% step %}

### Use `const` para valores que não mudam

```c
const int MAX_TENTATIVAS = 3;
for (int i = 0; i < MAX_TENTATIVAS; i++) { ... }
```

{% endstep %}

{% step %}

### Prefira `switch` para múltiplas condições de uma variável

```c
// Ruim - muitos if-else
if (opcao == 1) { ... }
else if (opcao == 2) { ... }
else if (opcao == 3) { ... }

// Bom - switch
switch (opcao) {
    case 1: ... break;
    case 2: ... break;
    case 3: ... break;
}
```

{% endstep %}

{% step %}

### Evite loops infinitos acidentais

```c
// Ruim
while (1) {  // Sem break, loop infinito
    // ...
}

// Bom - com condição de saída
int contador = 0;
while (contador < 10) {
    // ...
    contador++;
}
```

{% endstep %}

{% step %}

### Use `size_t` para índices de arrays

```c
size_t tamanho = 10;
for (size_t i = 0; i < tamanho; i++) {
    printf("%zu\n", i);
}
```

{% endstep %}
{% endstepper %}

## Vulnerabilidades Comuns em Estruturas de Controle

| Vulnerabilidade          | Descrição                             | Exemplo                                                 |
| ------------------------ | ------------------------------------- | ------------------------------------------------------- |
| Off-by-one               | Erro nos limites do loop              | `for (int i = 0; i <= 10; i++)` (acessa 11 elementos)   |
| Loop infinito            | Condição nunca se torna falsa         | `while (1) { /* sem break */ }`                         |
| Fall-through             | Esquecer `break` no switch            | Execução inesperada de cases subsequentes               |
| Comparação de atribuição | `=` em vez de `==`                    | `if (x = 5)` (atribui, não compara)                     |
| Uso de `else` ambíguo    | `else` associado ao `if` mais próximo | `if (a) if (b) x(); else y();` (y() associado ao if(b)) |

### Comparação de Atribuição (Erro Comum)

```c
int x = 5;

// Erro: = em vez de ==
if (x = 10) {  // Atribui 10 a x, condição sempre verdadeira
    printf("x agora é 10\n");
}

// Correto
if (x == 10) {
    printf("x é 10\n");
}
```

### Else Ambíguo

```c
// Qual if o else pertence?
if (a)
    if (b)
        x();
else
    y();

// Na verdade, else pertence ao if(b) mais interno
// Para corrigir, use chaves:
if (a) {
    if (b) {
        x();
    }
} else {
    y();
}
```

## Depuração de Estruturas de Controle

### Usando `printf` para rastrear fluxo

```c
int valor = 10;

if (valor > 5) {
    printf("Entrou no if\n");
    // ...
} else {
    printf("Entrou no else\n");
    // ...
}
```

### Usando GDB

```bash
gcc -g programa.c -o programa
gdb ./programa

# No GDB:
break main
run
step   # Executa linha a linha
print variavel  # Verifica valores
continue
```

## Resumo para Segurança

| Prática                    | Risco                   | Mitigação                       |
| -------------------------- | ----------------------- | ------------------------------- |
| `==` vs `=`                | Atribuição acidental    | Use `-Wall` para warnings       |
| Falta de `break` em switch | Fall-through inesperado | Sempre incluir `break`          |
| Loop sem limite            | DoS por loop infinito   | Garantir condição de saída      |
| Comparação de ponteiros    | Acesso inválido         | Verificar `NULL` antes de usar  |
| Índices de array           | Buffer overflow         | Usar `size_t` e validar limites |

## Recursos Adicionais

* Manual: `man gcc`, `man gdb`
* Documentação: [cppreference.com - Statements](https://en.cppreference.com/w/cpp/language/statements)
* OWASP: [Buffer Overflow](https://owasp.org/www-community/vulnerabilities/Buffer_Overflow)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/programacao-e-linguagens/c-and-c++/2.-estruturas-condicionais-e-repeticao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
