Ir ao conteúdo

Posts recomendados

Postado

Bom dia, Clube! 🙋‍♂️ Tudo bem com vocês? 😁

Já começo pedindo desculpas caso meu tópico esteja duplicado ou por faltar algum detalhe inicialmente... Sou novo nesse mundo e tô aqui pra aprender.

 

Utilizando o gancho da aprendizagem, agradeceria grandemente se alguém pudesse me responder esses problemas que esbarrei no primeiro dia de codificação C :

 

  1. O retorno da função printf da variável float nomeada Decimal tem o valor menor do que o definido manualmente pelo scanf;
  2. O retorno da função printf da variável char nomeada Caractere após o scanf neste código fica vazio por algum motivo.

 

Aqui o código:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//Incluindo bibliotecas pre-definidas

void main(){
    int Inteiro;
    float Decimal;
    char Caractere;
    bool Booleano;
//Definindo variáveis e seus tipos

    Inteiro = 4;
    Decimal = 1.5;
    Caractere = 'C';
    Booleano = false;
//Definindo valores das variáveis

    printf("\nO valor da variavel Inteiro atualmente = %d!", Inteiro);
    printf("\nQual o novo valor para Inteiro? ", Inteiro);
//Imprimindo na tela
    scanf("%d", &Inteiro);
//Pedindo usuário para inserir novo valor

    printf("\nO valor da variavel Decimal atualmente = %f!", Decimal);
    printf("\nQual o novo valor para Decimal? ", Decimal);
//Imprimindo na tela
    scanf("%f", &Decimal);
//Pedindo usuário para inserir novo valor

    printf("\nO valor da variavel Caractere atualmente = %c!", Caractere);
    printf("\nQual o novo valor para Caractere? ", Caractere);
//Imprimindo na tela
    scanf(" %c", &Caractere);
//Pedindo usuário para inserir novo valor

    printf("\nO valor da variavel Booleano atualmente = %d!", Booleano);
    printf("\nQual o novo valor para Booleano? ", Booleano);
//Imprimindo na tela
    scanf("%d", &Booleano);
//Pedindo usuário para inserir novo valor

    printf("\nO novo valor de A = %d", Inteiro);
    printf("\nO novo valor de B = %f", Decimal);
    printf("\nO novo valor de C = %c", Caractere);
    printf("\nO novo valor de D = %d\n\n", Booleano);
//Imprimindo valores após a modificação

    system("pause");
//Pausando após execução
    }

 

Sei que é um código simples e a ideia é essa mesmo! Comecei literalmente ontem e estou testando os tipos de variáveis.
Só que aí encontrei esses detalhes que não consegui encontrar a falha...

Aguardo respostas e sou grato antecipadamente pelo tempo e disposição de vocês.

 

Abraços,

Chris

erro 1.png

  • Amei 1
Postado
    printf("\nQual o novo valor para Inteiro? ", Inteiro);
    printf("\nQual o novo valor para Decimal? ", Decimal);
    printf("\nQual o novo valor para Caractere? ", Caractere);
    printf("\nQual o novo valor para Booleano? ", Booleano);

 

Eu não entendi o porque de colocar as variáveis nesses printf? Não precisa colocar a váriavel nessas linhas aí.

 

E uma outra coisa.

 

    scanf(" %c", &Caractere);

 

Viu que tem um espaço em branco antes do "%c"?

  • Curtir 1
  • Obrigado 1
Postado

Bom dia, @De Los Santos!

 

    printf("\nQual o novo valor para Inteiro? ", Inteiro);
    printf("\nQual o novo valor para Decimal? ", Decimal);
    printf("\nQual o novo valor para Caractere? ", Caractere);
    printf("\nQual o novo valor para Booleano? ", Booleano);


Obrigado pelo feedback. Corrigi o detalhe das variáveis no printf citado. Realmente não fazia sentido, erro de iniciante.
 

    scanf(" %c", &Caractere);

 

Quanto a esse scanf, em um momento anterior tive um problema ao tentar obter o input para essa função funcionar, o código não funcionava, saltando para a linha seguinte sem perguntar qual o novo valor para essa variável.

Vi num vídeo que o scanf em variáveis char precisavam deste espaço antes do %c para funcionar, senão ela é ignorada. Coloquei e funcionou por alguns testes. Mas após inserir o Booleano no código tive esse problema que não consegui resolver ainda...

 

Aguardo novas orientações,

 

Chris

  • Curtir 2
Postado

@De Los Santos

1 hora atrás, De Los Santos disse:

Viu que tem um espaço em branco antes do "%c"?

Isso faz com que caracteres de espaço em branco sejam lidos e ignorados, é uma boa prática se a ideia é evitar com que o usuário tecle Enter logo de cara (caso não haja interesse em ler esses caracteres).

 

@Chr15

1 hora atrás, Chr15 disse:

o código não funcionava, saltando para a linha seguinte sem perguntar qual o novo valor para essa variável

Qual tecla é pressionada ao finalizar a leitura? Enter!

Essa tecla interessa na leitura de um inteiro? de um ponto flutuante? A resposta é não, mas veja, vai interessar na leitura de um caractere.

\n é um caractere de espaço em branco, e você pode ignorá-lo colocando um espaço como primeiro caractere na string de formato na scanf():

1 hora atrás, Chr15 disse:
scanf(" %c", &Caractere);

Assim como fez sem saber o motivo, mas agora você sabe 🙂

 

1 hora atrás, Chr15 disse:
bool Booleano;

Sugiro esquecer bool em C, vai alocar 8 bits em vez de 1 como deveria (true ou false), acaba falhando no próprio conceito da variável. Pode usar um inteiro no lugar.

 

1 hora atrás, Chr15 disse:

Já começo pedindo desculpas caso meu tópico esteja duplicado ou por faltar algum detalhe inicialmente...

Aqui não é stackoverflow... Duplicado ou não, se for uma questão válida, você será respondido 😄

  • Curtir 2
Postado

Isso! Uma boa porção do mistério foi revelado, só não sei dizer se ficou evidente para todos da mesma maneira que para mim, assim explanarei mais um pouco o que acontece entre Booleano e Caractere.

 

1# Interpretando está cascata de declarações na forma de um vetor de bytes.

8 horas atrás, Chr15 disse:
    int Inteiro;
    float Decimal;
    char Caractere;
    bool Booleano;

 

Sendo que começa em Booleano e termina em Inteiro, por exemplo, se eu desejo trocar o valor da variável 'Inteiro' posso fazer também por qualquer endereço a partir da 'Booleano'.

 

Veja só:

#include"stdio.h"
#include"stdlib.h"
#include"stdbool.h"
int
main (void) {
  int Inteiro;
  float Decimal;
  char Caractere;
  bool Booleano;
//Definindo variáveis e seus tipos

  Inteiro = 4;
  Decimal = 1.5;
  Caractere = 'C';
  Booleano = 0;   
//Definindo valores das variáveis


*(int *) (&Booleano + 6) = 40;
//Com exceção gravar na 'Inteiro'

   printf("\nO novo valor de A = %d", Inteiro);
   printf("\nO novo valor de B = %f", Decimal);
   printf("\nO novo valor de C = %c", Caractere);
   printf("\nO novo valor de D = %d\n\n", Booleano);
//Imprimindo valores após a modificação

  system("pause");
//Pausando após execução
  return 0;
}

[SAÍDA]

127874380_Semttulo1.png.c67657ef000c94adffb1042293bbfcae.png

*Prova a si mesmo que a memória dessas declarações é contígua ao tentar outros valores.

 

É dito que um tipo bool tem 8 bits (1 byte), char tem 8 bits (1 byte), float tem 32 bits (4 bytes) que somados é: 6 bytes, daí o motivo de adicionar 6 ao endereço da 'Booleano'  para conduzir até o endereço do 'byte' menos significativo da 'Inteiro' que nos permiti acessa-lo.

 

#2

8 horas atrás, Chr15 disse:
//Imprimindo na tela
    scanf("%d", &Booleano);

O especificador na função Insinua que o parâmetro tem um decimal inteiro (ou seja, tipo int (32 bits (4 bytes))), entretanto sabemos ser falso, pois um tipo _Bool (ou bool — sendo seu apelido) tem 1 byte tal qual o tipo char.

 

Então, pergunta-se... a scanf grava em cima de quem, já que bool tem 1 byte, mas 'scanf' precisa de 4 bytes?

— DA 'Caractere' e DA 'Decimal' e com isso altera suas estruturas e seus valores.

 

[🙂] — espero que ajude! 

 

 

 

  • Curtir 3
Postado

Boa noite,@Lucca Rodrigues🙋‍♂️
Primeiramente muito obrigado pela resposta. 🤝

 

8 horas atrás, Lucca Rodrigues disse:

Isso faz com que caracteres de espaço em branco sejam lidos e ignorados, é uma boa prática se a ideia é evitar com que o usuário tecle Enter logo de cara (caso não haja interesse em ler esses caracteres).

 

No vídeo que vi, não foi dito o motivo, só que funcionava quando fosse colocado esse espaço...

 

8 horas atrás, Lucca Rodrigues disse:

Qual tecla é pressionada ao finalizar a leitura? Enter!

Essa tecla interessa na leitura de um inteiro? de um ponto flutuante? A resposta é não, mas veja, vai interessar na leitura de um caractere.

\n é um caractere de espaço em branco, e você pode ignorá-lo colocando um espaço como primeiro caractere na string de formato na scanf():

Assim como fez sem saber o motivo, mas agora você sabe 🙂

 

Mas agora eu sei o porquê e vários outros saberão também quando encontrarem esse tópico quando surgir alguma dúvida relacionada. Obrigado!

 

8 horas atrás, Lucca Rodrigues disse:

Sugiro esquecer bool em C, vai alocar 8 bits em vez de 1 como deveria (true ou false), acaba falhando no próprio conceito da variável. Pode usar um inteiro no lugar.

 

Aqui não é stackoverflow... Duplicado ou não, se for uma questão válida, você será respondido 😄

 

E sim, eu fui informado que bool em C é quase inútil, mas começando agora preciso testar e saber os reais motivos para tal.
Acabo de descobrir!

Obrigado mais uma vez pela disposição, @Lucca Rodrigues!


------------------------------------------------------------------------------------------------

Boa noite,@mauro_b!

 

1 hora atrás, mauro_b disse:

#2

O especificador na função Insinua que o parâmetro tem um decimal inteiro (ou seja, tipo int (32 bits (4 bytes))), entretanto sabemos ser falso, pois um tipo _Bool (ou bool — sendo seu apelido) tem 1 byte tal qual o tipo char.

 

Então, pergunta-se... a scanf grava em cima de quem, já que bool tem 1 byte, mas 'scanf' precisa de 4 bytes?

— DA 'Caractere' e DA 'Decimal' e com isso altera suas estruturas e seus valores.

 

[🙂] — espero que ajude! 

 

Antes de mais nada: obrigado pelos esclarecimentos! Confesso que fiquei 2 minutos refletindo o que você tinha dito mas agora entendo o que significa (ou pelo menos acho que entendo).

Se eu declaro que o scanf precisa de um inteiro ("%d" e peço desculpas se eu te corrigir errado mas creio que o mesmo tem 2 bytes) e bool tem somente 1 byte, ele sobrescreve a variável char para que se torne inteiro (2 bytes) e isso altera a característica da variável, tornando o printf nulo pois não condiz com seus parâmetros.

 

É isso, não? Por favor, me corrija se eu estiver errado.

 

Detalhe: a variável float agora funciona normalmente, só precisei removê-las do printf em que perguntava quais seriam os novos valores das variáveis. Antes mesmo de remover a bool.

 

 

 

Te agradeço grandemente pela disposição em repassar os conhecimentos adquiridos com tanta paciência e boa vontade! 👏

Um ótimo início de semana para vocês! 😁

Aguardo mais informações.

Chris

  • Curtir 2
Postado

. sizeof(variavel);       exemplo --> sizeof(Inteiro);

             ou
sizeof (tipo_de_variavel);   exemplo --> sizeof(Int);

  • Curtir 2
Postado

Isso, a resposta do usuário acima (@Izera XD) é a maneira C de pegar a capacidade (em “bytes”) dos tipos. Então, usarei a sugestão dele e anteciparei o experimento com um programa demostrativo que ilustra a capacidade das variáveis do teu programa e seus respectivos tipos, @Chr15.

 

Ilustração

#include"stdio.h"
#include"stdlib.h"
#include"stdbool.h"
//Incluindo bibliotecas pre-definidas
int
main (void) {
  int Inteiro;
  float Decimal;
  char Caractere;
  bool Booleano;

  unsigned long
  capacidade_Inteiro = sizeof(Inteiro),
  capacidade_Decimal = sizeof(Decimal),
  capacidade_Caractere = sizeof(Caractere),
  capacidade_Booleano  = sizeof(Booleano),

  capacidade_int = sizeof(int),
  capacidade_float = sizeof(float),
  capacidade_char = sizeof(char),
  capacidade_bool = sizeof(bool);

  puts ("capacidade . . . = bytes");
  puts ("VARIAVEIS:");
  printf ("%s%lu\n%s%lu\n%s%lu\n%s%lu\n",

         "capacidade_Inteiro = ", capacidade_Inteiro,
         "capacidade_Decimal = ", capacidade_Decimal,
         "capacidade_Caractere = ", capacidade_Caractere,
         "capacidade_Booleano  = ", capacidade_Booleano

  );
  puts ("TIPOS:");
  printf ("%s%lu\n%s%lu\n%s%lu\n%s%lu\n",

         "capacidade_int = ", capacidade_int,
         "capacidade_float = ", capacidade_float,
         "capacidade_char = ", capacidade_char,
         "capacidade_bool  = ", capacidade_bool

  );
  system ("pause");
//Pausando após execução
  return 0;
}

[SAÍDA]

763972942_Semttulo1.png.daa399feda5bf6f75774e96bcf1e1933.png

* Há 4s e 1s!

 

Agora que ilustrei o operador, usarei a mesma sugestão também numa versão do exemplo comprobatório da estrutura contígua na definição de variáveis do 'post' anterior.

#include"stdio.h"
#include"stdlib.h"
#include"stdbool.h"
int
main (void) {
  int Inteiro;
  float Decimal;
  char Caractere;
  bool Booleano;
//Definindo variáveis e seus tipos

  Inteiro = 4;
  Decimal = 1.5;
  Caractere = 'C';
  Booleano = 0;   
//Definindo valores das variáveis


*(int *) (&Booleano + (sizeof(bool) + sizeof(char) + sizeof(float))) = 1010111;
//Com exceção gravar na 'Inteiro' -- tudo isso equivale a referencia dela >'<

   printf("\nO novo valor de A = %d", Inteiro);
   printf("\nO novo valor de B = %f", Decimal);
   printf("\nO novo valor de C = %c", Caractere);
   printf("\nO novo valor de D = %d\n\n", Booleano);
//Imprimindo valores após a modificação

  system("pause");
//Pausando após execução
  return 0;
}

[SAÍDA]

591528780_Semttulo1.png.008ffd2e1f65a3286545fb6de4d6776d.png

*Comprova (pela 2th vez) que as variáveis são vizinhas!

 

[🙂] — espero que ajude! 

 

  • Curtir 2
  • Obrigado 1
Postado

Acabei lendo às pressas e não vi uma passagem importante de sua resposta, @Chr15

 

[!] esta passagem 

9 horas atrás, Chr15 disse:

só precisei removê-las do printf em que perguntava quais seriam os novos valores das variáveis.

Em tese, só isso não basta!

 

RESUMIDAMENTE, as variáveis na função main são vizinhas e o especificador no formato da 'scanf' ("%d") exige um parâmetro do tipo int * (na arquitetura 32 bits aponta para um início da sequência de 4 ‘bytes’). E os compiladores atuais tem (porém, não perfeita) regras para verificação da sintaxe, logo "os comados" abaixo são uma "falha gramatical"

 

19 horas atrás, Chr15 disse:
    scanf("%d", &Booleano);
//Pedindo usuário para inserir novo valor

[ALERTA DURANTE COMPILAÇÃO]

413972862_Semttulo1.png.da0958a80943407eb5627e1dbc3b61ba.png

 

Ignoraremos e continuamos… com esta versão reduzida do programa de maneira que sobrou só a bendita 'scanf' (ou seja, sem as tais 'printf')

#include"stdio.h"
#include"stdlib.h"
#include"stdbool.h"
//Incluindo bibliotecas pre-definidas
int
main (void) {
  int Inteiro;
  float Decimal;
  char Caractere;
  bool Booleano;
//Definindo variáveis e seus tipos

  Inteiro = 4;
  Decimal = 1.4;
  Caractere = 'C';
  Booleano = false;
//Definindo valores das variáveis

  printf("\nO valor da variavel Decimal atualmente = %f!\n", Decimal);
//Imprimindo na tela

  scanf("%d", &Booleano);
//Pedindo usuário para inserir novo valor

  printf("\nO novo valor de A = %d", Inteiro);
  printf("\nO novo valor de B = %f", Decimal);
  printf("\nO novo valor de C = %c", Caractere);
  printf("\nO novo valor de D = %d\n\n", Booleano);
//Imprimindo valores após a modificação

  system("pause");
//Pausando após execução
  return 0;
}

[SAÍDA]

450997554_Semttulo1.png.891275ae1a6012a7a0c0e05328cae15b.png

*O valor zero, abaixo da saída do valor atual na 'Decimal', é a entrada para scanf.

 

Observe a igualdade de B C.

19 horas atrás, Chr15 disse:

Chris

erro 1.png

 

[🙂] — espero que ajude.

  • Obrigado 2
Postado

@Chr15      sobre o titulo desse seu post  ,  o printf nso mostra o valor de scanf , por que voce colocou o printf antes do scanf ,  assim o compilador  ainda nem não leu o que voce digitou no teclado  ,   e assim ele escreve o valor wue as variaveus tem nesse momento , e nesse caso os valores delas sao aleatirios , pois voce não fez a inicializacao das variaveis la no inicio do codigo

int main(){ int Inteiro; float Decimal; char Caractere; bool Booleano; //Definindo variáveis e seus tipos Inteiro = 4; Decimal = 1.5; Caractere = 'C'; Booleano = false; //Definindo valores das variáveis printf("\nO valor da variavel Inteiro atualmente = %d!", Inteiro); printf("\nQual o novo valor para Inteiro? ", Inteiro); //Imprimindo na tela scanf("%d", &Inteiro); //Pedindo usuário para inserir novo valor

printf("\nO valor da variavel Inteiro agora eh = %d!", Inteiro); 

 

printf("\nO valor da variavel Decimal atualmente = %f!", Decimal); printf("\nQual o novo valor para Decimal? ", Decimal); //Imprimindo na tela scanf("%f", &Decimal);

printf("\nO valor da variavel Decimal Agora eh = %d!", Decimal); 

//Pedindo usuário para inserir novo valor printf("\nO valor da variavel Caractere atualmente = %c!", Caractere); printf("\nQual o novo valor para Caractere? ", Caractere); //Imprimindo na tela

fflush(stdin);

scanf("%c", &Caractere);

printf("\nO valor da variavel csractere atualmente = %d!", caractere); 

//Pedindo usuário para inserir novo valor printf("\nO valor da variavel Booleano atualmente = %d!", Booleano); printf("\nQual o novo valor para Booleano? ", Booleano); //Imprimindo na tela

fflush(stdin);

scanf("%d", &Booleano);

printf("\nO valor da variavel booleano Agora eh = %d!", booleano); 

//Pedindo usuário para inserir novo valor printf("\nO novo valor de A = %d", Inteiro); printf("\nO novo valor de B = %f", Decimal); printf("\nO novo valor de C = %c", Caractere); printf("\nO novo valor de D = %d\n\n", Booleano); //Imprimindo valores após a modificação system("pause"); //Pausando após execução }

Postado
Em 20/02/2022 às 09:33, Chr15 disse:

O retorno da função printf da variável float nomeada Decimal tem o valor menor do que o definido manualmente pelo scanf;

No computador nem todo número real tem representação exata, é o caso do 1.4. Internamente a máquina usa a base binária, então quando você entra com um número real ele é convertido para essa base. E quando não dá para formar o número de forma exata nessa base ele é arredondamento e isso fica mais evidente quando você mostra mais casas após a vírgula, p.ex,

printf("%.20f\n", 1.4f);

 

  • Curtir 2
Postado
36 minutos atrás, Midori disse:

Internamente a máquina usa a base binária, então quando você entra com um número real ele é convertido para essa base. E quando não dá para formar o número de forma exata nessa base acontece isso que fica mais evidente quando você mostra mais casas após a vírgula

 

Mudar a base não muda a precisão. Qualquer número inteiro tem representação precisa em qualquer base.

 

Números reais são armazenados no formato de mantissa e expoente, num formato chamado IEEE754. Há outros formatos mas hoje de longe esse é hoje o padrão. E é essa representação, que permite em geral 7 ou 15 dígitos de precisão para valores em 4 ou 8 bytes, que não representa exatamente números reais. Por isso cuidado ao comparar ou apresentar esses números. Em especial evite o uso de '==' e compare com intervalos. 2.1 pode ser 2.10000001 ... 

  • Curtir 2
Postado
29 minutos atrás, Midori disse:

Se colocar p.ex 1.4 como comentei poderá ver a representação e o erro após a conversão

 Talvez "erro" não seja uma boa definição. O comum é chamar de tolerância e considerar o número de dígitos significativos, usando isso na comparação. 

 

EXEMPLO na documentação da Microsoft

 

EPSILON é a tolerância no exemplo: 1/10.000

 

// Floating-point_number_precision.c
// Compile options needed: none. Value of c is printed with a decimal
// point precision of 10 and 6 (printf rounded value by default) to
// show the difference
#include <stdio.h>

#define EPSILON 0.0001   // Define your own tolerance
#define FLOAT_EQ(x,v) (((v - EPSILON) < x) && (x <( v + EPSILON)))

int main() {
   float a, b, c;

   a = 1.345f;
   b = 1.123f;
   c = a + b;
   // if (FLOAT_EQ(c, 2.468)) // Remove comment for correct result
   if (c == 2.468)            // Comment this line for correct result
      printf_s("They are equal.\n");
   else
      printf_s("They are not equal! The value of c is %13.10f "
                "or %f",c,c);
}

 

Mostra

 

They are not equal! The value of c is  2.4679999352 or 2.468000

 

  • Curtir 1
  • Obrigado 2
Postado
2 horas atrás, arfneto disse:

Talvez "erro" não seja uma boa definição. O comum é chamar de tolerância e considerar o número de dígitos significativos, usando isso na comparação.

Talvez a questão de termos não seja tão relevante, mas eu sempre vi o termo "erro". Isso quando o número não pode ser representado de forma exata. E a definição é como no link que postei, a diferença entre o valor real e o mostrado pela máquina com o arredondamento.

  • Curtir 2
  • Obrigado 1
Postado
6 horas atrás, Midori disse:

Talvez a questão de termos não seja tão relevante, mas eu sempre vi o termo "erro". Isso quando o número não pode ser representado de forma exata. E a definição é como no link que postei, a diferença entre o valor real e o mostrado pela máquina com o arredondamento.

 

Eu não vou julgar a relevância claro, mas nunca vi isso ser chamado de erro na literatura.  Talvez eu deva ler mais 😉 

 

O termo "erro" sempre aparece associado a erros de arredondamento causados por cálculos sucessivos. Isso eu já li muitas vezes. Um caso especial é o dinheiro, e essa foi a razão de COBOL ter tipo de dados BCD (no popular: Decimal Codificado em Binário, dois dígitos por byte) desde '59: somar dinheiro perfeitamente. Algo como o BigDecimal de java, só que em COBOL é mais limpo: apenas declara a variável como BCD e usa.

 

Por coincidência o exemplo que mostrei tem as duas expressões: tolerância e precisão. Mas não fala em erro. Se me lembro bem o que acontece é que na conversão para IEEE754 ou qualquer outro formato mantissa/expoente muitos números que tem formato decimal certinho acabam gerando uma dízima na conversão para IEEE754 e tem que parar em algum limite e há um truncamento.

  • Curtir 3
Postado

 

Acho que tem boas respostas de outros acima e já deve ter entendido o que acontece.

 

Vou somar mais uns palpites apenas

 

Em 20/02/2022 às 09:33, Chr15 disse:
  1. O retorno da função printf da variável float nomeada Decimal tem o valor menor do que o definido manualmente pelo scanf;
  2. O retorno da função printf da variável char nomeada Caractere após o scanf neste código fica vazio por algum motivo.

 

 

Isso está errado. 

 

O retorno da função printf() é um número, e você nem tratou em seu programa. 

scanf() não define manualmente nada. Apenas lê e converte valores da entrada usando os especificadores e endereços.

 

printf() retorna um int com o total de bytes mostrados. Você não tratou isso. scanf() retorna um int com o total de especificadores atendidos, ou um valor negativo em caso de erro. Especificadores são aquelas coisas de começam por % e não por %%, como o %d em seu programa. Você também não tratou isso em seu código.

 

Sobre seu código

 

void main(){

 

Está errado. main() retorna um int e o protótipo tem dois parâmetros: um int e um ponteiro para um vetor de strings. 

 

Algo assim é o comum:

 

int main( int argc, char** argv)

 

argc é o total de argumentos e argv é o vetor com os argumentos, fornecido pelo sistema para TODO programa C. O primeiro argumento, argv[0], é em geral o nome completo do programa executável, e o sistema prepara a lista pra você.

 

Se não vai usar os argumentos procure declarar

 

    int main(void)

 

Deixando claro que não vai usar nenhum.

 

Em geral em C ou qualquer linguagem coisas implícitas PODEM dar erro. Coisas explícitas mesmo que irrelevantes na aparência podem levar a programas mais seguros, então é um bom hábito evitar coisas implícitas.

 

Evite comentários com acentos e coisas pouco relevantes como

 

//Definindo valores das variáveis

 

Acentos podem não ser exibidos como se espera. E procure comentar o que está fazendo e o porque. Dá pra imaginar que uma declaração defina valores para as variáveis. E procure definir os valores na própria declaração: assim não vai esquecer algum valor que possa ser importante no futuro, não vai errar um nome na segunda vez, não vai ter que procurar pela definição...

 

    int Inteiro;
    float Decimal;
    char Caractere;
    bool Booleano;

//Definindo variáveis e seus tipos

   
    Inteiro = 4;
    Decimal = 1.5;
    Caractere = 'C';
    Booleano = false;

 

podia ser

 

    int Inteiro = 4;
    float Decimal = 1.5f;
    char Caractere = 'C';
    bool Booleano = false;

 

bool em C ou qualquer linguagem de pouco vale a menos que ocupe um único bit, e isso não acontece. Em C zero é falso, o resto é verdadeiro. E basta. Qualquer expressão que resolve em zero é falsa, e as outras verdadeiras.

 

sizeof é operador que define o tamanho de variáveis em C

 

Deixe a linguagem trabalhar para você. Estes printf:

 

    int n = printf(
        "Tamanhos em bytes:\n\tint=%lld\n\tfloat=%lld\n\tchar=%lld\n\t"
        "bool=%lld\n",
        sizeof(int),
        sizeof(float),
        sizeof(char),
        sizeof(Booleano));
    printf("\n\to printf() anterior retornou %d\n", n);

 

Ajudam a entender o que está tentando entender, e mostram

 

Tamanhos em bytes:
        int=4
        float=4
        char=1
        bool=1

        o printf() anterior retornou 51

 

E você já vê o espaço ocupado pelos tipos das variáveis, e pelo tal Booleano. 51 foi o total de bytes escritos por printf() na saída padrão, em C conhecida por stdout.

 

Seu exemplo, alterado:

 

Mudando um pouco seu programa para incluir algumas das coisas de que falei:
 

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

int main(int argc, char** argv)
{
    int   Inteiro   = 4;
    float Decimal   = 1.5f;
    char  Caractere = 'C';
    bool  Booleano  = false;

    int n = printf(
        "Tamanhos em bytes:\n\tint=%lld\n\tfloat=%lld\n\tchar=%lld\n\t"
        "bool=%lld\n",
        sizeof(int),
        sizeof(float),
        sizeof(char),
        sizeof(Booleano));
    printf("\n\to printf() anterior retornou %d\n", n);
    
    // testa o uso de argc/argv
    printf("\n\tO primeiro argumento do programa: \"%s\""
        "\n\tTotal de %d argumento(s)\n",
        argv[0], argc);

    printf(
        "\nValores atuais:\n\tint: %d\n\tfloat: %f"
        "\n\tchar '%c'\n\t"
        "bool %d\n",
        Inteiro,
        Decimal,
        Caractere,
        Booleano);

    printf("\nEntre com um novo valor"
        " para Decimal (atual = %f): ", Decimal);
    n = scanf("%f", &Decimal);
    printf("\n\to scanf() retornou %d.\n\tO valor"
        "lido foi %f, ou %.10f (10 decimais)\n",
        n, Decimal, Decimal);
}

 

Que mostra

 

C:\Clube> ./teste Clube do Hardware
Tamanhos em bytes:
        int=4
        float=4
        char=1
        bool=1

        o printf() anterior retornou 51

        O primeiro argumento do programa: "C:\Clube\teste.exe"
        Total de 4 argumento(s)

Valores atuais:
        int: 4
        float: 1.500000
        char 'C'
        bool 0

Entre com um novo valor para Decimal (atual = 1.500000): 1.4

        o scanf() retornou 1.
        O valor lido foi 1.400000, ou 1.3999999762 (10 decimais)

 

teste.exe era o nome do programa. Foi chamado com 3 argumentos como vê. Mas o primeiro o sistema fornece.

 

Note que o padrão para printf() nessa máquina é usar 6 decimais, como no exemplo que te mostrei antes, mas se usar 10 vai ver que o 1.4 não é o que parece...

 

E note que o ponto decimal nessa máquina é ponto. Em muitos casos é a vírgula e isso é um inferno. Um programa educado deveria consultar o sistema e ver qual é o ponto decimal em uso e avisar na mensagem antes da leitura, porque o usuário pode não saber e se digitar errado vai dar confusão, certo?

 

Sugiro que rode isso em sua máquina e compare.

 

Uma ú;tima nota: não use system() nunca. Para nada. Não estará fazendo nada nem aprendendo nada. Se precisa parar o programa porque roda no IDE e o IDE não tem a opção de parar apenas mude de IDE: por certo há melhores.

 

E se acostume a rodar seus programas no terminal, como no exemplo acima. O ambiente da telinha do IDE é diferente e nem sempre vai resolver: programas são escritos para rodar em outras máquinas. não para ficarem no interminável ciclo compila/roda em uma única máquina.

 

 

 

 

 

Sobre o erro e sua pergunta original

 

Se viu as respostas anteriores e a saída do exemplo que te mostrei sabe que um bool ocupa um byte em C.

 

A relação de  scanf() e os tipos dos argumentos

 

Não existe. scanf() não entende nada de tipos dos argumentos. scanf() só trata endereços. E essa função foi escrita para ler dados tabulares, as populares tabelas, aqueles arquivos com muitas linhas com campos de dados. como planilhas e arquivos do tipo csv. A ideia era você definir os tipos dos dados em cada linha e colocar os especificadores corretos, e a função rapidamente consome milhares de linhas e cria uma estrutura na memória, um registro no banco de dados, essas coisas. 

 

Por isso o nome scanf: scan formatted data. O teclado não é nada formatado. São mais de 100 teclas de liberdade e assim provavelmente não é a melhor opção usar scanf() para ler dados não formatados sabendo que ela foi escrita e nomeada para o contrário.

 

De todo modo eis uma tabela que mostra os possíveis especificadores para scanf().

 

image.png.a8187ac1cc49d03cf539bfef58c6d5a9.png

 

Se acostume a ler o manual ou ao menos o que o IDE diz sobre cada função. Se seu IDE nada diz use outro. No linux o manual faz parte do sistema: use man scanf por exemplo. Quando esse sistema foi escrito todo mundo era programador afinal 🙂 

 

Veja as primeiras linhas do resultado de um man scanf 😉 

 

image.png.a5e1d27ed5f946a99fb9beec3c432711.png

 

De volta à tabela

 

Pode ver na tabela que os tipos das variáveis vão todos na coluna do meio, que fala dos especificadores. Nos argumentos tudo tem asterisco: scanf() só trata endereços. Nada mais: char*, float* etc...

 

    scanf("%d", &Booleano);

 

Assim, ao usar %d pode ver na tabela
 

image.png.60ed44b68b35b991f0f2a228f34651a5.png

 

E como viu no exemplo que te mostrei um int ocupa 4 bytes. Isso quer dizer que o argumento deve apontar para uma área alocada em seu programa de pelo menos 4 bytes.

 

E você passou o endereço de Booleano usando o popular operador Address Of, o &. Só que essa variável só ocupa um byte. scanf() não vai dar a mínima para isso e vai gravar até 4 bytes a partir desse endereço e claro corromper algo na memória gravando no que tiver depois. É provável que cancele seu programa e é melhor assim, porque se não cancelar e seu programa for algo com mais de umas poucas linhas pode gastar horas pra achar um erro desses. Coisas assim custam tempo, notas e empregos.

 

 

  • Curtir 1
  • Obrigado 2

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...