Algumas considerações: 1: O operador sizeof retorna o tipo size_t, definido em stdlib.h. Esse tipo tem o tamnho de um ponteiro (na arquitetura i386 têm 4 bytes de tamanho, na arquitetura x86-64, 8 bytes); 2: Existe uma extensão para os especificadores de coversão do printf (as substrings começadas com %) que pode ser usada para quando queremos imprimir o valor expresso no tipo size_t. Ao invés de usar %lu, podemos usar %zu - garantindo a compatibilidade com a arquitetura vigente... Isso existe porque o tipo "long" no Windows, por exemplo, tem 4 bytes de tamanho (32 bits), mas no "Linux" e outros UNIXes, ela tem 8 bytes... 3: O tipo bool é um "apelido" para o tipo _Bool, definido na especificação C99. Se não quiser incluir o header stdbool.h, basta substituir "bool" por "_Bool" (com underscore). Uma dúvida que vi expressa aqui nos comentários foi justamente sobre o fato de que 0 é false e 1 é true... Fernando deverá falar sobre isso mais adiante, mas o fato é que 0 é sempre falso e qualquer coisa diferente de 0 é "true". No entando, a especificação da linguagem C nos diz que uma EXPRESSÃO BOOLEANA sempre resulta em 0 ou 1, MAS a avaliação de um valor booleano sempre é feito contra o ZERO. Ou seja, se o valor booleano for -10, por exemplo, ele será TRUE. O tipo '_Bool', nesse sentido, é especial porque apenas o bit 0 é considerado... modifique o exemplo final, mostrado pelo Fernando, para: bool b = -10; E você verá que o valor impresso, final, será 1 (true). []s Fred
Não sei se conhece o Termux. Simulador de terminal bash do Linux para Android. Eu tenho PC, mas estou fazendo essa aula pelo termux pra testar. Quando fui compilar deu um erro que, traduzindo, pediu pra trocar o parâmetro %lu por %u, uma vez que a função 'main' retorna um valor "inteiro sem sinal" e eu estou com argumento de "long sem sinal" . Na mensgem de erro, sugeriu-se usar o %u, que funcionou. Daí, coloquei esse %zu e funcionou também. Eu queria saber porque no Linux Mint não dá erro algum. Deve ser alguma coisa referente a arquitetura ARM, Sistema Android ou coisas do tipo. Que eu saiba, mesmo sendo no termux, o compilador é gcc.
Só um aviso: Um caracter literal, como 'A', por exemplo, tem o tamanho de um int, não de um char. Isso é fácil demonstrar usando o operador sizeof('A'), por exemplo (e você obterá 4!)... Quando fazemos: char c = 'A'; O inteiro 'A' é convertido para char, mantendo apenas os 8 bits inferiores. Isso é diferente da "string" literal, onde cada item tem 1 byte de tamanho, exceto se usamos prefixos como L, u, U ou u8 (no caso do C11).
aqui deu 4 para sizeof('A') como explicado pelo Frederico... mas também deu 2 para sizeof("A") Não está errado! como explicado pelo Frederico em uma string cada caractere conta como 1... "A" possui 2 caracteres A e \0 :-) Se fizermos sizeof "AA" será exibido 3 (A A \0) e se fizermos sizeof "" (string vazia) será impresso 1 :-)
Outra dica sobre os conversores d e u de printf é que, assim como o modificador 'l' pode ser usado como prefixo para a conversão (como no caso de %lu para 'long unsigned int'), os prefixos 'hh' e 'h' são definidos na especificação C99 (não tenho certeza sobre 'h')... O conversor %hhd espera o arqgumento do tipo 'char' e um '%hd', um do tipo 'short'. O conversor '%i', usado nos exemplos, espera um argumento do tipo 'int' - que funciona, neste caso... Os prefixos 'hh', 'h', 'l' e 'll' não são "extensões", mas fazem parte do padrão (de novo, não estou certo sobre 'h', mas estou sobre os outros).
Boa Noite Fernando! Curti de mais, e já vou compartilhar.... kkkk Pegando o bonde sobre tamanho de variáveis, penso que seria legal em momentos futuros dar exemplos de boas práticas para tratanto de BoF... abs!
Bom dia Mercês. Queria dar uma ideia para o curso. Quando estudei Clipper e COBOL há muitos anos atrás, o que mais me ajudou à entender, foi colocando a mão na massa. Eu era estagiário. rsrsrs Seria interessante tipo à partir de algum momento do curso pegarmos um software livre que você tenha desenvolvido, destrinchar ele e usá-lo como aplicação dos conceitos aprendidos. Como por exemplo o pev ou outro que achar interessante. Obrigado por dar esse treinamento!
O meu está dando erro aula2.c: In function ‘main’: aula2.c:6:10: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘unsigned int’ [-Wformat=] printf("O tamanho é %lu ", sizeof c); Alguém pode me ajudar ?
quando tenta por 256 em um char, meu compilador clang não avisa overflow, mas avisa que usuário tentou armazenar um int em um char. também não aceita valor maior que 128, só de -128 a 127 em um signed char. isso são apenas variações dos compiladores em si né?
Prezado Fernando, primeiramente parabens pelos videos deste curso. Estou assistindo a todos. Tenho uma duvida sobre o tipo boolean e acredito que nao seja facil de se resolver pois a propria lib que define este tipo já foi codificada com o char. No intuito de economizar alocacao de memoria, seria possivel utilizar 1 bit para alocar um boolean ao inves de um char que ocupa 8 bits? Ou o minimo que se consegue alocar em C eh 1 byte? Desde ja, agradeco.
Fabiano Furtado Eu já me perguntei sobre essa questão de campos de bits. Se você reparar, por mais que o compilador permitisse armazenamento de 1 bit, você ganharia em espaço de memória, mas perderia em desempenho. Imagina a complicação que seria pra acessar essas coisas...:)
12:40 : dúvida: o tamanho da variável 'c' é de um byte!? Byte é *maior* que bit. E você ainda *multiplicou* por oito!? Eu creio que o tamanho da variável 'c' é de um *bit* (bit, não byte). Depois você multiplicou um *bit* por oito, resultando em oito *bits* (bits, não bytes). Oito *bits*, isso sim, é igual a um *byte*. Começando a estudar e a aprender a linguagem C. Daqui de Jaboatão dos Guararapes, Pernambuco, Brasil, quarta-feira, 17 de julho de 2024.
Entendi sua lógica, mas tá certa a multiplicação mesmo. O sizeof dá o tamanho em bytes. Se quiser saber em bits, multiplica-se por 8 justamente porque 1 byte são 8 bits nessa arquitetura. Assim: 1 byte == 8 bits (1*8) 4 bytes == 32 bits (4*8) 8 bytes == 64 bits (8*8) 16 bytes == 128 bits (16*8) Ou seja: bits = bytes * 8 e bytes = bits / 8 Abraço!
Estou com a seguinte DÚVIDA! Fernando Mercês: Resolvi ir um pouco além da aula que versa sobre char e boolean, e apliquei os conceitos em Int, float e double. Se o tamanho de char é 1 byte, int seria 2 bytes, float 4 e double 8. Porém após a execução o int apresenta o mesmo tamanho do float que são 4 bytes, PORQUE??
eber barbosa Na realidade, o tamanho de um int depende do compilador (que decide ou não seguir os padrões da arquitetura). Talvez seja 2 bytes em arquiteturas de 16 bits ou sistemas embarcados...talvez o seu livro seja antigo demais também, hehehehehe.
Muito bom! :-) Assistindo o vídeo, lembrei de um challenge que explora um conceito que foi discutido. Fica aí pra quem quiser se aprofundar: w3challs.com/challenges/challenge60 Abs!!
Como um booleano só recebe 1 ou 0, porque seu tamanho é de 1 byte? Não seria mais inteligente ele ter sido definido como apenas 1 bit? Não entendi porque a biblioteca C definiu ele como sendo 8 bits. Me parece haver um desperdício de bits. Estou certo?
Bruno Saldanha Acho que a questão do booleano ser 0 ou 1 está na representação em decimal, por isso do byte. Ao ponto que o bit é a linguagem de máquina.
Eu ainda não assisti o vídeo , mas vou ver logo breve... Mas aproveitando a sua pergunta, vou responder sem saber se já foi respondido no vídeo. Seguinte... Numa resposta muito rápida: "A CPU NÃO consegue acessar endereços menores que 8-bits (1 byte)!" Tentando explicar: Sei que Wikipédia não é uma das melhores referencias, mas, diz o seguinte: "Historically, the byte was the number of bits used to encode a single character of text in a computer and for this reason it is the smallest addressable unit of memory in many computer architectures." Isso quer dizer que: Endereçamentos são inteiros, a CPU endereça pequenos valores, o menor é 8-bits... Ou seja, é o menor valor que pode ser endereçado (note: endereçado! e não "acessado"). Caso, você queira acessar 1-bit... Você terá de acessar esses 8-bits, e ignorar os outros bits extras. Isso evita certa confusão de acessos de "bits" arbitrários. Por exemplo: você não pode criar um ponteiro direto para um valor menor que 1-byte.
Entendi o seguinte. Como estamos trabalhando com variáveis e variáveis são valores que armazenamos na memória, o menor valor que podemos armazenar na memória seria de 1 byte. Por isso tanto o tipo char quanto o bool ocupam o espaço de 1 byte.
Trata-se do padrão de avaliação de expressões boleanas de C... Antes do tipo _Bool (ou de seu "apelido" 'bool'), uma expressão booleana pode ser feita com qualquer tipo... Se o valor da expressão der ZERO isso quer dizer FALSO, se der diferente de zero, quer dizer VERDADEIRO. No entanto, operadores booleanos zeram todos os bits superiores, deixando apenas o bit 0 intacto e, no C++, o tipo 'bool' foi criado para conter esse tipo de resultado. Ele foi, depois, incorporado à especificação C99. Substitua, no último exemplo do Fernando, o valor de 'b' por, por exemplo, -10 e verá que o printf continuará imprimindo 1.
Algumas considerações:
1: O operador sizeof retorna o tipo size_t, definido em stdlib.h. Esse tipo tem o tamnho de um ponteiro (na arquitetura i386 têm 4 bytes de tamanho, na arquitetura x86-64, 8 bytes);
2: Existe uma extensão para os especificadores de coversão do printf (as substrings começadas com %) que pode ser usada para quando queremos imprimir o valor expresso no tipo size_t. Ao invés de usar %lu, podemos usar %zu - garantindo a compatibilidade com a arquitetura vigente... Isso existe porque o tipo "long" no Windows, por exemplo, tem 4 bytes de tamanho (32 bits), mas no "Linux" e outros UNIXes, ela tem 8 bytes...
3: O tipo bool é um "apelido" para o tipo _Bool, definido na especificação C99. Se não quiser incluir o header stdbool.h, basta substituir "bool" por "_Bool" (com underscore).
Uma dúvida que vi expressa aqui nos comentários foi justamente sobre o fato de que 0 é false e 1 é true... Fernando deverá falar sobre isso mais adiante, mas o fato é que 0 é sempre falso e qualquer coisa diferente de 0 é "true". No entando, a especificação da linguagem C nos diz que uma EXPRESSÃO BOOLEANA sempre resulta em 0 ou 1, MAS a avaliação de um valor booleano sempre é feito contra o ZERO. Ou seja, se o valor booleano for -10, por exemplo, ele será TRUE.
O tipo '_Bool', nesse sentido, é especial porque apenas o bit 0 é considerado... modifique o exemplo final, mostrado pelo Fernando, para:
bool b = -10;
E você verá que o valor impresso, final, será 1 (true).
[]s
Fred
PS: A extensão z para conversores do printf só vale para o GCC e para a GLIBC. Que eu sabia, não funciona no Visual Studio, por exemplo...
Já funciona no VS 2015, apesar da documentação de size specification ainda dizer que não (msdn.microsoft.com/en-us/library/tcxf1dw6.aspx)
Não sei se conhece o Termux. Simulador de terminal bash do Linux para Android. Eu tenho PC, mas estou fazendo essa aula pelo termux pra testar.
Quando fui compilar deu um erro que, traduzindo, pediu pra trocar o parâmetro %lu por %u, uma vez que a função 'main' retorna um valor "inteiro sem sinal" e eu estou com argumento de "long sem sinal" . Na mensgem de erro, sugeriu-se usar o %u, que funcionou. Daí, coloquei esse %zu e funcionou também.
Eu queria saber porque no Linux Mint não dá erro algum. Deve ser alguma coisa referente a arquitetura ARM, Sistema Android ou coisas do tipo. Que eu saiba, mesmo sendo no termux, o compilador é gcc.
Sem dúvidas o melhor curso de C, os outros só ensina a syntax da linguagem e mais nada.
Só um aviso: Um caracter literal, como 'A', por exemplo, tem o tamanho de um int, não de um char. Isso é fácil demonstrar usando o operador sizeof('A'), por exemplo (e você obterá 4!)...
Quando fazemos:
char c = 'A';
O inteiro 'A' é convertido para char, mantendo apenas os 8 bits inferiores.
Isso é diferente da "string" literal, onde cada item tem 1 byte de tamanho, exceto se usamos prefixos como L, u, U ou u8 (no caso do C11).
@Vitor Gusmao, é o contrário... o literal "A" (com aspas duplas) é um PONTEIRO (por isso 4 ou 8 bytes - em 32 e 64 bits, respectivamente).
@@FredericoPissarra te amo cara que massa essa info obgad heheheh tmj família
aqui deu 4 para sizeof('A') como explicado pelo Frederico... mas também deu 2 para sizeof("A")
Não está errado! como explicado pelo Frederico em uma string cada caractere conta como 1... "A" possui 2 caracteres A e \0 :-)
Se fizermos sizeof "AA" será exibido 3 (A A \0) e se fizermos sizeof "" (string vazia) será impresso 1 :-)
Vamos que vamos :) agora acho que aprendo C definitivamente.
Cara, sua didática é muito foda! parabens! curso nota MIL!
Parabéns! O curso está ótimo! O canal é sensacional!!!!
Outra dica sobre os conversores d e u de printf é que, assim como o modificador 'l' pode ser usado como prefixo para a conversão (como no caso de %lu para 'long unsigned int'), os prefixos 'hh' e 'h' são definidos na especificação C99 (não tenho certeza sobre 'h')...
O conversor %hhd espera o arqgumento do tipo 'char' e um '%hd', um do tipo 'short'.
O conversor '%i', usado nos exemplos, espera um argumento do tipo 'int' - que funciona, neste caso...
Os prefixos 'hh', 'h', 'l' e 'll' não são "extensões", mas fazem parte do padrão (de novo, não estou certo sobre 'h', mas estou sobre os outros).
Como mnemônico, se 'l' é 'long', 'h' é 'half', ou "metade"... Da mesma forma, 'hh' é "metade da metade".
Metade de quê? De um 'int'.
Boa Noite Fernando!
Curti de mais, e já vou compartilhar.... kkkk
Pegando o bonde sobre tamanho de variáveis, penso que seria legal em momentos futuros dar exemplos de boas práticas para tratanto de BoF...
abs!
Bom dia Mercês. Queria dar uma ideia para o curso. Quando estudei Clipper e COBOL há muitos anos atrás, o que mais me ajudou à entender, foi colocando a mão na massa. Eu era estagiário. rsrsrs Seria interessante tipo à partir de algum momento do curso pegarmos um software livre que você tenha desenvolvido, destrinchar ele e usá-lo como aplicação dos conceitos aprendidos. Como por exemplo o pev ou outro que achar interessante. Obrigado por dar esse treinamento!
Nem sabia que operador possuía argumentos KKKK, vivendo e aprendendo
Legal né? 🙂
Ótima aula, Mercês!
Excelente aula !!!!
Obrigado ☺️
muito bom o curso de C!!!!!
vamos que vamos! que venha a terceira aula. :-)
Boa essa aula
Muito Bom!
Show!
O meu está dando erro
aula2.c: In function ‘main’:
aula2.c:6:10: warning: format ‘%lu’ expects argument of type ‘long unsigned int’,
but argument 2 has type ‘unsigned int’ [-Wformat=]
printf("O tamanho é %lu
", sizeof c);
Alguém pode me ajudar ?
Apenas para informar que o link para o vídeo sobre ASCII está direcionando para o Studio!
Valeu, Henrique! Já tá corrigido lá, mas segue aqui também: th-cam.com/video/IN9ElO90uLc/w-d-xo.html
:)
quando tenta por 256 em um char, meu compilador clang não avisa overflow, mas avisa que usuário tentou armazenar um int em um char.
também não aceita valor maior que 128, só de -128 a 127 em um signed char.
isso são apenas variações dos compiladores em si né?
Olha, possivelmente são só jeitos diferentes de tratar isso de cada compilador. Legal saber. 🙂
Prezado Fernando, primeiramente parabens pelos videos deste curso. Estou assistindo a todos.
Tenho uma duvida sobre o tipo boolean e acredito que nao seja facil de se resolver pois a propria lib que define este tipo já foi codificada com o char.
No intuito de economizar alocacao de memoria, seria possivel utilizar 1 bit para alocar um boolean ao inves de um char que ocupa 8 bits? Ou o minimo que se consegue alocar em C eh 1 byte?
Desde ja, agradeco.
Pessoal... acho que isso esclarece a minha dúvida: C Bit Fields
Detalhes em www.tutorialspoint.com/cprogramming/c_bit_fields.htm
Fabiano Furtado Eu já me perguntei sobre essa questão de campos de bits. Se você reparar, por mais que o compilador permitisse armazenamento de 1 bit, você ganharia em espaço de memória, mas perderia em desempenho. Imagina a complicação que seria pra acessar essas coisas...:)
12:40 : dúvida: o tamanho da variável 'c' é de um byte!? Byte é *maior* que bit. E você ainda *multiplicou* por oito!? Eu creio que o tamanho da variável 'c' é de um *bit* (bit, não byte). Depois você multiplicou um *bit* por oito, resultando em oito *bits* (bits, não bytes). Oito *bits*, isso sim, é igual a um *byte*. Começando a estudar e a aprender a linguagem C. Daqui de Jaboatão dos Guararapes, Pernambuco, Brasil, quarta-feira, 17 de julho de 2024.
Entendi sua lógica, mas tá certa a multiplicação mesmo. O sizeof dá o tamanho em bytes. Se quiser saber em bits, multiplica-se por 8 justamente porque 1 byte são 8 bits nessa arquitetura. Assim:
1 byte == 8 bits (1*8)
4 bytes == 32 bits (4*8)
8 bytes == 64 bits (8*8)
16 bytes == 128 bits (16*8)
Ou seja: bits = bytes * 8
e
bytes = bits / 8
Abraço!
Estou com a seguinte DÚVIDA! Fernando Mercês:
Resolvi ir um pouco além da aula que versa sobre char e boolean, e apliquei os conceitos em Int, float e double. Se o tamanho de char é 1 byte, int seria 2 bytes, float 4 e double 8. Porém após a execução o int apresenta o mesmo tamanho do float que são 4 bytes, PORQUE??
eber barbosa Não, parceiro, você está confundindo um pouco. Um int possui o tamanho de 4 bytes e um short possui o tamanho de 2 bytes. :)
Entendi!!, porque li em um livro o valor de um int = 16 bits 2 bytes e escala -32768 a 32767 . Vlw e obrigado pela resposta.
eber barbosa Na realidade, o tamanho de um int depende do compilador (que decide ou não seguir os padrões da arquitetura). Talvez seja 2 bytes em arquiteturas de 16 bits ou sistemas embarcados...talvez o seu livro seja antigo demais também, hehehehehe.
Olá!!! Pq 'sizeof c * 8 = 8' e 'sizeof (c * 8) = 4' ?
Bj. no coração!
Em qual momento do vídeo? Tem tempo que gravei hehe
Estou obtendo erro na linha de comando:
bash-4.3$ make char
make: *** No rule to make target 'char'. Pare.
Do jeito que você está fazendo o nome do arquivo fonte deveria ser char.c - é esse?
@@mentebinaria eu coloquei como aula2.c o nome do arquivo, deve ter sido isso entao
@@mentebinaria resolvi colocando make aula2.c, entendi o que fiz de errado a partir do seu comentario. obrigado
Muito bom! :-)
Assistindo o vídeo, lembrei de um challenge que explora um conceito que foi discutido. Fica aí pra quem quiser se aprofundar: w3challs.com/challenges/challenge60
Abs!!
Como um booleano só recebe 1 ou 0, porque seu tamanho é de 1 byte? Não seria mais inteligente ele ter sido definido como apenas 1 bit? Não entendi porque a biblioteca C definiu ele como sendo 8 bits. Me parece haver um desperdício de bits. Estou certo?
Boa observação. Também fiquei com essa curiosidade. Porque só precisaria de 1 bit sendo 0 ou 1 como em binário.
Bruno Saldanha Acho que a questão do booleano ser 0 ou 1 está na representação em decimal, por isso do byte. Ao ponto que o bit é a linguagem de máquina.
Eu ainda não assisti o vídeo , mas vou ver logo breve... Mas aproveitando a sua pergunta, vou responder sem saber se já foi respondido no vídeo.
Seguinte... Numa resposta muito rápida: "A CPU NÃO consegue acessar endereços menores que 8-bits (1 byte)!"
Tentando explicar:
Sei que Wikipédia não é uma das melhores referencias, mas, diz o seguinte:
"Historically, the byte was the number of bits used to encode a single character of text in a computer and for this reason it is the smallest addressable unit of memory in many computer architectures."
Isso quer dizer que: Endereçamentos são inteiros, a CPU endereça pequenos valores, o menor é 8-bits... Ou seja, é o menor valor que pode ser endereçado (note: endereçado! e não "acessado"). Caso, você queira acessar 1-bit... Você terá de acessar esses 8-bits, e ignorar os outros bits extras. Isso evita certa confusão de acessos de "bits" arbitrários. Por exemplo: você não pode criar um ponteiro direto para um valor menor que 1-byte.
Entendi o seguinte. Como estamos trabalhando com variáveis e variáveis são valores que armazenamos na memória, o menor valor que podemos armazenar na memória seria de 1 byte. Por isso tanto o tipo char quanto o bool ocupam o espaço de 1 byte.
Trata-se do padrão de avaliação de expressões boleanas de C... Antes do tipo _Bool (ou de seu "apelido" 'bool'), uma expressão booleana pode ser feita com qualquer tipo... Se o valor da expressão der ZERO isso quer dizer FALSO, se der diferente de zero, quer dizer VERDADEIRO.
No entanto, operadores booleanos zeram todos os bits superiores, deixando apenas o bit 0 intacto e, no C++, o tipo 'bool' foi criado para conter esse tipo de resultado. Ele foi, depois, incorporado à especificação C99.
Substitua, no último exemplo do Fernando, o valor de 'b' por, por exemplo, -10 e verá que o printf continuará imprimindo 1.