Resultado do concurso do livro uC/OS-III The Real-Time Kernel

- por Sergio Prado

Categorias: Promoção, RTOS Tags: , , ,

Muito bem pessoal, chegou a hora de conhecer os 3 vencedores da promoção para ganhar o livro de RTOS da Micrium!

Primeiramente, gostaria de agradecer à todos pela participação. Recebi 85 respostas, e deu um pouco de trabalho corrigir tudo! :)

A maioria acertou pelo menos 3 dos 4 desafios, e 38 acertaram tudo. Dentre estas 38 pessoas, fiz o sorteio lá no http://www.random.org/.

Mas antes de dizer quem são os 3 felizardos, que tal darmos uma olhada novamente nos desafios?

DESAFIO 1

O desafio 1 dizia o seguinte:

O código abaixo tem um erro. Qual é este erro?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdlib.h>
#include <stdio.h>
 
#define SIZE 15 
 
int main()
{
    int *a, i;
 
    a = malloc(SIZE*sizeof(int));
 
    for (i = 0; i < SIZE; i++)
        *(a + i) = i * i;
 
    for (i = 0; i < SIZE; i++)
        printf("%dn", *a++);
 
    free(a);
 
    return 0;
}

A maioria acertou este desafio. Na linha 10 alocamos uma região de memória e armazenamos o endereço no ponteiro “a”. Na linha 16 este ponteiro é alterado, e quando tentamos desalocá-lo na linha 18 teremos problemas na certa, já que o ponteiro “a” não armazena mais o endereço inicial retornado por malloc(). A solução aqui seria não alterar este ponteiro. O código abaixo resolve o problema:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdlib.h>
#include <stdio.h>
 
#define SIZE 15 
 
int main()
{
    int *a, i;
 
    a = malloc(SIZE*sizeof(int));
 
    for (i = 0; i < SIZE; i++)
        *(a + i) = i * i;
 
    for (i = 0; i < SIZE; i++)
        printf("%dn", *(a + i));  // CORREÇÃO
 
    free(a);
 
    return 0;
}

Algumas pessoas apontaram ainda que faltou checar o retorno da função malloc() e fazer o cast para (int *). É verdade! O cast é necessário principalmente se você tentar compilar em C++. Mas não considerei estes fatores para validar a resposta como certa.

DESAFIO 2

O desafio 2 dizia o seguinte:

O código abaixo tam­bém tem um erro. Qual?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
    int* ptr1, ptr2;
 
    ptr1 = malloc(sizeof(int));
 
    ptr2 = ptr1;
 
    *ptr2 = 10;
 
    return 0;
}

A maioria também acertou este exercício. Uma coisa que aprendi deste quando comecei a estudar C é que devemos colocar o “*” sempre do lado do nome do ponteiro, e não do lado do tipo. No código acima, ptr2 é um inteiro, e não um ponteiro para inteiro como pretendiamos, causando erro na linha 11. Para corrigir este código, basta declarar ptr2 como ponteiro:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
    int *ptr1, *ptr2;  // CORREÇÃO
 
    ptr1 = malloc(sizeof(int));
 
    ptr2 = ptr1;
 
    *ptr2 = 10;
 
    return 0;
}

Assim como no primeiro exercício, algumas pessoas também apontaram a ausência da checagem do retorno da função malloc() e do cast para (int *). Mas também não considerei estes fatores para validar a resposta como certa.

Outros falaram da ausência do free(). Sim, é sempre uma boa prática usar o free(), mas sua ausência nem sempre significa erro. No nosso caso, como a aplicação aloca e depois encerra, não teremos problema com memory leak pela ausência do free().

DESAFIO 3

O desafio 3 dizia o seguinte:

A função abaixo recebe um vetor de números inteiros e tem o obje­tivo de retornar o menor número inteiro deste vetor. Imple­mente esta função sem usar nen­hum oper­ador de com­para­ção! Ou seja, você não pode usar nen­hum destes oper­adores: “==”, “!=”, “>”, “<”, “>=”, “<=”.

1
2
3
4
unsigned int menor(unsigned int buf[], size_t size)
{
 
}

Aqui o bicho pegou! Este é o típico “exercício bombril”, que pode ser resolvido de 1001 maneiras. Recebi implementações de 5 linhas e outras de 50 linhas! :)

Esta é a minha sugestão de implementação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
unsigned int menor(unsigned int buf[], size_t size)
{
    unsigned int m = 0;
    int i;
 
    while(1) {
 
        for (i = size; i; i--) {
            if (!buf[i - 1]) return m;
            buf[i - 1]--;
        }
 
        m++;
    }
}

Eu faço uma varredura do vetor em um loop e decremento, um a um, cada elemento deste vetor. A quantidade de decrementos realizados é armazenada na variável “m”. Quando um dos elementos do vetor atingir o valor 0, significa que descobri qual era o elemento de menor valor dentro do vetor, e retorno este valor, que é exatamente a quantidade de decrementos realizada, armazenada na variável “m”.

Recebi algumas implementações que usavam esta lógica, mas também recebi outras implementações bem interessantes.

Achei bem legal esta implementação do Paulo Daniel:

1
2
3
4
5
6
7
8
unsigned int menor(unsigned int buf[], size_t size)
{
   unsigned int min = UINT_MAX;
   while(size) 
      if(!(buf[--size]/min))
         min = buf[size];
   return min;
}

Ele conseguiu resolver em 5 linhas, usando apenas uma operação de divisão de inteiros!

Atualização: Como bem observado pelos leitores Fernando Barboza e Уθя¡ςκ, esta implementação tem uma falha, já que existe o risco de divisão por 0 na linha 5. Mas a forma como o problema foi resolvido não deixa de ser bem interessante.

Já o Douglas Drumond preferiu escovar alguns bits e trabalhar com complemento de 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
unsigned int menor(unsigned int buf[], size_t size)
{
    unsigned int shamt =  (sizeof(unsigned int) * 8 - 1);
    unsigned int mask = 0x01;
 
    size_t i = size - 1;
 
    unsigned int menor_item = buf[i];
    while (i--) {
        if(((buf[i] - menor_item) >> shamt) && mask) menor_item = buf[i];
    }
 
    return menor_item;
}

DESAFIO 4

Este desafio dizia o seguinte:

Escreva um pro­grama em C que imprima “Quero o meu livro!”, mas sem usar nen­hum ponto-e-vírgula no arquivo “.c”! Obs: o pro­grama deve com­pi­lar e fun­cionar nor­mal­mente.

A solução é bem simples:

1
2
3
4
5
6
#include <stdio.h>
 
void main()
{
    if (printf("Quero o livro!n")) {}
}

Você pode trocar o “if” pelo “while” também.

Teve gente que queria tanto o livro que colocou em um loop infinito! :)

1
2
3
4
void main()
{
    while(printf("Quero o meu livro!n")){}
}

Mas aqui o pessoal resolveu usar a criatividade. Como falei apenas que não podia usar “;” no arquivo “.c”, e não mencionei nada sobre o uso de arquivo “.h”, recebi respostas do tipo:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Author: Celso
// imprime.c
#include <stdio.h>
#include <stdlib.h>
 
#include "imprime.h"
void main()
{
  IMPRIME
}
 
// imprime.h
#define IMPRIME   printf("Quero o meu livro!n");

Ou então trocando o “;” por um define passado pelo compilador:

1
2
3
4
5
6
7
8
9
10
11
/* Author: Fernando Martines
 *
 * Compilacao: gcc -DSPECIAL=";" desafio4.c -o desafio4
 */
#include <stdio.h>
 
int main()
{
    printf("Quero o meu livro!n") SPECIAL
    return 0 SPECIAL
}

Bom, gostei muito do resultado destes desafios. Aprendi bastante e espero que vocês tenham aprendido também. Afinal, o que importa é participar. Ganhar é só um detalhe, não é verdade? O quê? Não!? :)

OK, chega de enrolação, estes são os três participantes que acertaram os 4 desafios e foram sorteados para receber o livro:

  • Rodrigo (a.k.a. Skhaz)
  • Eduardo Vieira
  • Rodolfo Pereira Araujo

Para aqueles que não ganharam, não desanimem! Vocês podem baixar gratuitamente o PDF do livro no site da Micrium aqui.

Ou então vocês podem esperar o próximo concurso. Eu havia falado que tinha 3 livros, não é verdade? Então… eu estava escondendo o jogo! :)

Na verdade, alem destes 3, tenho mais 1! E logo mais teremos um novo desafio por aqui. Mas desta vez não será tão fácil assim! :)

Um abraço!

Sergio Prado

Faça um Comentário

Navegue
Creative Commons Este trabalho de Sergio Prado é licenciado pelo
Creative Commons BY-NC-SA 3.0.