Porque diminuir aqui parece errado? [RESOLVIDO]

1. Porque diminuir aqui parece errado? [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 04/12/2021 - 00:44h

Bom dia a Todos!

Fazendo testes com strchr percebi um estranho comportamento!
O valor de Letra é 5
O valor de Text é 12
Logo 5 - 12 deveria dar -7 e não 7

Alguém sabe explicar?
#include <stdio.h>
#include <string.h>

int main(void) {
char Text[] = "Viva O Linux", // 12 Caracteres
*Letra = strchr(Text, 'L'); // 5 Caracteres

// Porque não dá negativo aqui?
printf("%ld\n", Letra - Text); // RESULT: 7

// Resultado OK
printf("%ld\n", strlen(Letra) - strlen(Text)); // RESULT: -7
}
Minha dúvida consiste em entender pq a matemática neste caso específico não funciona! Obrigado!


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 04/12/2021 - 07:06h

ApprenticeX escreveu:

Bom dia a Todos!

Fazendo testes com strchr percebi um estranho comportamento!
O valor de Letra é 5
O valor de Text é 12


Não.

O valor de Letra é um endereço na memória do caráter que fica 7 posições após o caráter que reside no endereço de memória produzido quando Text é usado numa expressão.

Em outras palavras, se Text corresponde a um endereço X (que, a princípio, é desconhecido, pois vai depender de como seu programa foi compilado e como foi carregado na memória no momento de ser executado), Letra corresponde ao endereço X+7. Daí, Letra-Text valerá X+7-X, que dá 7.

O tipo de dados do valor resultante da subtração de dois ponteiros é ptrdiff_t (definido em <stddef.h>). A conversão a ser usada com printf() quando o argumento é do tipo ptrdiff_t é "%td", não "%ld", como você fez. Possivelmente na sua máquina os tipos ptrdiff_t e long int têm a mesma representação interna, e por isso o compilador não alarmou incompatibilidade entre a conversão e o tipo do argumento, mas não se acostume a contar com essa coincidência, pois outra implementação pode usar representações diferentes, e o seu programa pode quebrar.


Outro problema com seu programa está na diferença strlen(Letra)-strlen(Text) e na impressão do resultado. O tipo de retorno de strlen() é size_t, que é um inteiro sem sinal (provavelmente, na sua máquina, equivalente a unsigned long int). Como tanto o minuendo quanto o subtraendo são do mesmo tipo sem sinal (size_t), o resultado também é do mesmo tipo e, portanto, é falso concluir que esse resultado é -7, já porque esse valor não é representável como size_t. A conversão correta a ser usada com printf() quando o argumento é do tipo size_t é "%zu". O valor impresso como -7 é resultado da conversão realizada dentro de printf() porque você disse que o argumento seria de um tipo com sinal quando usou a conversão "%ld". Possivelmente o compilador não alarmou porque na sua máquina size_t e long int têm o mesmo tamanho, e porque C aceita sem reclamar conversões implícitas entre inteiros com sinal e sem sinal quando eles têm o mesmo tamanho.

Se você quiser confirmar que o resultado não é negativo, você pode colocar as seguintes linhas no programa, e ver que a mensagem nunca será impressa.
if(strlen(Letra)-strlen(Text)<0))
puts("negativo");

Se estiver usando o GCC e compilar com a opção -Wextra, vai ver a explicação para o comportamento dessas linhas, que confirma o que eu afirmei acima.
gcc -Wextra -Werror -O2 -pedantic-errors y.cc
y.cc: In function ‘int main()’:
y.cc:14:36: error: comparison of unsigned expression < 0 is always false [-Werror=type-limits]
if(strlen(Letra) - strlen(Text) < 0L)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
cc1plus: all warnings being treated as errors

Se quiser que essa subtração produza um valor negativo, você deve converter os operandos para um valor inteiro com sinal (ou então converter o resultado, que foi o que você acabou fazendo sem querer quando usou a conversão incorreta com printf()).


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)

3. Re: Porque diminuir aqui parece errado? [RESOLVIDO]

Apprentice X
ApprenticeX

(usa Slackware)

Enviado em 04/12/2021 - 22:30h

paulo1205 escreveu:
Se quiser que essa subtração produza um valor negativo, você deve converter os operandos para um valor inteiro com sinal (ou então converter o resultado, que foi o que você acabou fazendo sem querer quando usou a conversão incorreta com printf()).

O que eu queria era mesmo entender o que estava acontecendo e o porque! E mais uma vez a sua resposta é uma grande aula! tenho que ver como vou armazenar essa informação aqui pra estar atento a isso! Obrigado!








Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts