1
resposta

Warning: comparison of integer expressions of different signedness: 'int' and 'size_t'

Olá!

Gostaria de saber sobre o aviso que está aparecendo quando compilo o código. Estou usando o VS code.

Warning "Ex2.c: In function 'desenhaforca': Ex2.c:37:17: warning: comparison of integer expressions of different signedness: 'int' and 'size_t' {aka 'unsigned int'} [-Wsign-compare] 37 | for (i=0; i < strlen (palavraSecreta); i++){"

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

//variáveis globais
char chutes [26];
int tentativas = 0;
char palavraSecreta [20];

void abertura(){
    printf("*******************\n");
    printf("*  Jogo de forca  *\n");
    printf("*******************\n\n");
} 

void chuta(){
    char chute;
    scanf(" %c",&chute);
    chutes[tentativas] = chute;
    (tentativas)++;

}

int jaChutou(char letraPalavraSecreta){
    int j;  
    int achou = 0;
    for (j = 0; j < tentativas; j++){
        if (chutes[j] == letraPalavraSecreta){
            achou = 1;
            break;
        }
   }
   return achou;
}

void desenhaforca(){

    int i;
    for (i=0; i < strlen (palavraSecreta); i++){

        int achou = jaChutou(palavraSecreta[i]); //a letra já foi chutada? 

        if (achou){
            printf ("%c ", palavraSecreta[i]);
        } else{
            printf("_ ");
        }

    }
    printf("\n");
}

void escolhePalavra (){
    sprintf(palavraSecreta, "MELANCIA");
}

int main(){


    escolhePalavra();

    int acertou = 0;
    int enforcou = 0;

    abertura();

    do {

        //imprime a palavra secreta

        desenhaforca();

        chuta();

    } while (!acertou && !enforcou); //se usassemos == seria 0


}
1 resposta

Esse aviso é bem simples de entender quando se entende um pouco de numeração binária. Você provavelmente deve saber que cada tipo possui um tamanho (em bytes), e que este tamanho depende da sua plataforma. Execute o código abaixo para saber qual o tamanho de cada um dos tipos primitivos em sua arquitetura.

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf(
        "char: %lu\n"
        "short: %lu\n"
        "int: %lu\n"
        "long: %lu\n"
        "float: %lu\n"
        "double: %lu\n",
        sizeof(char),
        sizeof(short),
        sizeof(int),
        sizeof(long),
        sizeof(float),
        sizeof(double)
    );

    return 0;
}

Existem dois tipos de representação binária: a representação inteira, e a representação em ponto flutuante. Dizemos que os tipos char, short, int e long são tipos inteiros, ao passo que float e double são números em ponto flutuante que aderem ao padrão IEEE 754 de precisão simples e dupla respectivamente.

A representação inteira, por sua vez, possui 2 variantes: com ou sem sinal. Fazemos uso dos modificadores de tipo signed e unsigned, respectivamente, para marcar o tipo; por padrão o modificador signed é adotado implicitamente caso omitido.

O tipo size_t, retornado por strlen, é um alias para unsigned long, ao passo que sua variável é do tipo signed int. Execute o programa abaixo para verificar os parâmetros de representação de cada tipo em sua máquina.

#include <math.h>
#include <stdio.h>
#include <stddef.h>

static const struct {
    const char *const str;
    const size_t size;
} types[] = { 
    {"char", sizeof(char)}, 
    {"short", sizeof(short)}, 
    {"int", sizeof(int)}, 
    {"long", sizeof(long)} 
};

int main(int argc, char *argv[]) {
    printf("Total de representações por tipo\n\n");
    for (int i = 0; i < 4; i++)
        printf("\t%s: %.0f representações\n", types[i].str, pow(2.0, types[i].size * 8));
    printf("\n\n\n");

    printf("Intervalo de representação com sinal\n\n");
    for (int i = 0; i < 4; i++) {
        double value = pow(2.0, (types[i].size * 8) - 1);

        printf("\tsigned %s: de -%.0f a %.0f\n", types[i].str, value, value - 1);
    }

    printf("\n\n\n");

    printf("Intervalo de representação sem sinal\n\n");
    for (int i = 0; i < 4; i++)
        printf("\tunsigned %s: de 0 a %.0f\n", types[i].str, pow(2.0, types[i].size * 8) - 1);

    return 0;
}

A razão desta diferença de representação se dá pela quantidade de bits disponíveis para armazenar informação. Ainda que ambos os tipos, com ou sem sinal, possuam o mesmo tamanho em memória, tipos sem sinal fazem uso de todos os bits disponíveis, ao passo que os tipos com sinal usam o bit mais significativo como marcador do sinal (0 se for positivo, 1 se for negativo).

O meu compilador não emite esse aviso, pois não estou usando a flag -Wsign-compare, como é o seu caso. Essa flag faz com que o compilador avise quando inteiros com modificadores de tipo de sinal diferentes estão sendo comparados, pois, ainda que o compilador possa fazer conversões implicitamente para realizar as operações aritméticas, essa comparação em certas circunstâncias pode estar associado a erros de lógica. Para silenciar o aviso, faça uma coerção explícita, mude o tipo da variável ou remova a flag do compilador.