Problemas ao compilar com gcc

Recentemente voltei a usar o linux (Linux Mint 19.3 Tricia 64-bit) e me deparei com a necessidade de escrever um programa simples em C para testar um software de engenharia reversa (meu conhecimento sobre a linguagem está entre o básico e o mediano). Porém estou tendo erros ao compilar o arquivo com o gcc, versão (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0. Acabei criando duas versões do código baseado em informações encontradas em fóruns, por tanto vou anexar um print do código e seu erro de compilação respectivamente , para caso alguém possa me ajudar com isso:

Código 1:


Erro:

Código 2:


Erro:
Erro 2

Primeiramente, isso não é um problema relacionado ao Linux, e sim à sintaxe da linguagem C. Mas vamos lá, são alguns erros:

O primeiro, da primeira versão, é que o parâmetro “%c” exige que o segundo parâmetro seja um “char” e não um ponteiro de char (char*). Para ler uma string (ponteiro de char, char*) você deve usar a opção “%s”. Além disso, você apenas declarou o ponteiro, mas não o inicializou com o malloc. Isso vai causar uma falha de segmentação ao executar o programa, pois o ponteiro não está apontando para nada e nem tem um espaço reservado para armazenar o que foi lido.

No segundo exemplo, os erros são parecidos, só que invertidos. Você declarou as variáveis “user_input” e “aux” como “char” (apenas um caractere), e por isso o compilador não reclama durante a compilaçã do “%c”, porém, o programa vai ler apenas um caractere e não a string completa. O erro de compilação é justamente esse, você está comparando um caractere com uma string.

3 curtidas

Uma versão funcional do programa (uma parte dele):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char const *argv[]) {
  char *user_input;

  user_input = (char*)malloc(sizeof(char)*64);
  scanf("%s", user_input);
  printf("Leu: %s\n", user_input);

  if (strcmp(user_input,"r10") == 0){
    printf("RRRRrrrrrronaldinho!!!!!\n");
  }
  return 0;
}

A saída:

bruno@ubuntu-Lenovo:~$ gcc t.c && ./a.out 
r10
Leu: r10
RRRRrrrrrronaldinho!!!!!
bruno@ubuntu-Lenovo:~$ gcc t.c && ./a.out 
r9
Leu: r9
1 curtida

Olá!
Notável que você está começando com a linguagem c, então tentarei lhe explicar de forma simples:

Você está lidando com a string “Ronaldinho”, logo, se você quiser comparar strings, não irá ser como linguagens de alto nivel, você precisará incluir a lib, string.h, ou criar a sua própria que lide com comparação de strings.

Você está utilizando a função scanf(), não é recomendado, mas ignorando isso… troque o “%c” por “%s”, e defina a variável que levará o valor de stdin, desta forma: char user_input[x] troque o x pelo valor do array que levará os characteres passados.

Outra ponto, você está criando um “menu” com while, para receber um string ao invéz de do-while e está criando muitas variáveis que não são necessárias.

Segue exemplo em código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  char input[56];
  do {
    printf("Please insert the key: ");
    scanf("%s", &input);
  } while ((strcmp("Ronaldinho", input)) != 0);

  if ((strcmp("Ronaldinho", input)) == 0) {
     printf("Access granted!\n");
     return 0;
  } else {
     printf("Access denied!\n");
     return 1;
   }
}

Uma ideia para você, tente limitar o numero de tentativas do menu utilizando size_t. Ou tente também separar o menu em uma função diferente de main(). A e digite “ola Ronaldinho” nesse menu, irá validar, mesmo o usuário não ter digitado apenas, “Ronaldinho”, solução? Pesquise como utilizar a função fgets().

Mais informações:

  1. C strcmp()
  2. C Input and Output
  3. C strings

Espero ter lhe ajudado, até mais!

1 curtida

Muito obrigado pela resposta. Me ajudou muito.

Bruno muito obrigado pela resposta. Eu poderia ao invés de declarar o tamanho da string com o malloc declarar um vetor? Por exemplo:
char user_input[64];
Se sim qual a diferença usando o malloc?

Pode sim. Eu sempre prefiro usar o malloc, mas nesse caso, ainda mais por ser apenas uma espécie de buffer, pode usar o char[64] sem problemas. Internamente o funcionamento é um pouco diferente, mas o resultado é o mesmo.

E o aux pode ser apenas um caractere. Existem outras soluções melhores para esse caso, de apenas esperar por uma entrada qualquer, mas um simples caractere funciona.

Entendi. Muito obrigado pela ajuda!

1 curtida

Eduardo tentei usar seu código. Porém ele retorna o seguinte erro:
Erro forum
Após alguns testes cheguei a conclusão que ele vem do “&” antes do nome da varável (ao tirá-lo o programa é compilado e executado normalmente) o que é estranho pois eu tinha aprendido que quando você vai fazer referência ao endereço de memória da variável é necessário usar o carácter “&” antes do nome da variável. Enfim não sei porque isso acontece se souber puder me explicar agradeço, porém se futuramente alguém precisar do conteúdo desse tópico fique ciente disso.

Só para te deixar atualizado testei o seu código e ele rodou sem problemas fiz algumas molificações utilizando também o código do Matheus como base e cheguei ao código que precisava. Muito obrigado.

Estranho, abri o terminal pra testar e funcionou…

Vou pesquisar um pouco, testar outras versões do gcc e debugar o código para entender o que eu fiz ou oque pode ser.

Não havia testado o código antes, fui só pelo o que lembrava. Se houver um erro meu, eu não ia nem perceber. Obrigado, por me avisar! :+1:

1 curtida

Não sei se ajuda mas ta ai a versão do gcc que usei:

gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1 curtida

Erro meu havia esquecido sobre o uso de & para ponteiros e eu não havia definido nenhum ponteiro… e sim char user_input[56]; :sweat_smile: :+1:

O “&” indica o endereço da variável, e não o valor. Por isso é necessário usá-lo quando você quer ler um “int”, pois você quer que naquele endereço seja armazenado o “int” lido pelo scanf.
Porém, ao se usar ponteiros ou [], não se pode usar o “&” pois o valor da variável já é o endereço. Ou seja, ao declarar uma variável como tipo *x, *x vai se referir ao valor de x, que estará armazenado no endereço apontado por x, pois x é do tipo ponteiro de tipo (que é um endereço).

Então, como o scanf pede por um endereço, se x já for do tipo ponteiro de char ao se colocar o “&” vai dar erro. Por outro lado se y for do tipo char, é preciso usar o & para usar o endereço de y e não o valor da variável y.

Edit:
Esse código pode ajudar a entender:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char const *argv[]) {
    char x;
    char *y;

    y = (char*)malloc(sizeof(char));

    x = 'A';
    *y = 'B';

    printf("x = %c, *y = %c\n",x,*y);
    printf("end de x = %p, end de y = %p\n",&x,y);

    return 0;
}

A saída é:

x = A, *y = B
end de x = 0x7fff3930c5ff, end de y = 0x562bf07a62a0
1 curtida

Valeu @brunonzanette, estava misturando muita coisas, essa primeira linha já diz muito.

E desculpa @Skylong por passar instrução equivocada, para exemplo alterei o código deixei assim agora:

Para mostrar utilização do “&” com int x; e não com char input[56];. :+1:

2 curtidas

Tranquilo! Que bom que consegui ajudar.

E agora que eu lembrei que há um bom tempo atrás eu escrevi um código com vários exemplos de usos de ponteiros, para ser usado como material de estudo dos alunos do meu orientador. Acabou que nunca foi usado para esse fim, mas eu deixei o código salvo para quando precisasse. Então eu criei um “gist” no Github para pode compartilhar, e o link está a seguir. Pode ser útil para estudar e testar algumas coisas.

2 curtidas

Fica tranquilo Eduardo ajudou bastante

Vlw vou dar uma olhada depois.

E @Skylong, Só uma dica extra, para quem pretende aprender c/c++, caso queira ler algumas libraries da linguagem c/c++ recomendo o code.woboq.org, que usei para estudar a um tempo atrás:

Você pode achar os códigos de varias funções por exemplo de scanf() é bom para entender como a função funciona. você pode achar a scanf() neste link glibc/glibc/stdio-common/ Source Tree

1 curtida

Obrigado vou dar uma olhada também.