Как избавиться от следующего предупреждения о преобразовании знака? - PullRequest
1 голос
/ 08 февраля 2020

Я получаю следующее предупреждение всякий раз, когда вызывается функция initSetArray ():

error: conversion to ‘long unsigned int’ from ‘int’ may change the sign of the result [-Werror=sign-conversion]
  setarray = (set*)malloc(sizeof(set) * number_of_sets);   

Функция initSetArray просто инициализирует setarray.

void initSetArray(set *setarray, int number_of_sets, int number_of_blocks)
{
    setarray = (set*)malloc(sizeof(set) * number_of_sets);
}

Я определил две структуры, которые используются в описанной выше вспомогательной функции:

typedef struct{
    uint64_t tag;   // For identifying the block
    uint8_t valid;  // Valid bit for the block
    uint8_t dirty;  // Dirty bit for the block
} block;

typedef struct{
    uint64_t index; // For identifying the set
    block* way;
} set;

Я не могу точно определить, какая переменная имеет тип "long unsigned int". Что я могу сделать, чтобы решить эту проблему?

Ответы [ 3 ]

2 голосов
/ 08 февраля 2020

В этом операторе

setarray = (set*)malloc(sizeof(set) * number_of_sets);

переменная number_of_sets является целым числом (int), и поскольку она используется в выражении с sizeof (size_t), значение преобразуется в соответствие.

size_t обычно unsigned long. Если вам не нравится предупреждение, это исправит это:

setarray = (set*)malloc(sizeof(set) * (size_t) number_of_sets);
1 голос
/ 08 февраля 2020

Предупреждение выдается при очень строгих настройках предупреждения, поскольку значение number_of_sets неявно преобразуется из int в тип без знака unsigned long int, который может иметь противо-интуитивное значение для отрицательных значений number_of_sets.

Чтобы отключить это предупреждение, вы можете:

  • изменить прототип initSetArray, чтобы исправить тип аргументов: number_of_sets и numer_of_blocks, вероятно, должны быть значениями без знака с типом size_t в любом случае:

    void initSetArray(set *setarray, size_t number_of_sets, size_t number_of_blocks)
    
  • поочередно, вы можете добавить явное преобразование, используя оператор приведения:

    void initSetArray(set *setarray, int number_of_sets, int number_of_blocks) {
        setarray = (set*)malloc(sizeof(set) * (size_t)number_of_sets);
    }
    

Обратите внимание, что установка значения аргумента setarray не влияет на переменную вызывающего, которая используется в качестве аргумента для initSetArray. Вы должны либо вернуть указатель, либо взять указатель на аргумент указателя.

1 голос
/ 08 февраля 2020

Функция malloc принимает аргумент size_t, а size_t определяется для вашей сборки как unsigned long int (как это часто бывает). В вашем вызове:

setarray = (set*)malloc(sizeof(set) * number_of_sets);

вы умножаете такое значение size_t (оператор sizeof дает size_t) на (подписанную) int переменную - отсюда и предупреждение.

Чтобы избежать этого, либо явно приведите number_of_sets к size_t, например так:

setarray = (set*)malloc(sizeof(set) * (size_t)number_of_sets);

Или, лучше, измените тип этого аргумента на size_t:

void initSetArray(set *setarray, size_t number_of_sets, size_t number_of_blocks)
{
    setarray = (set*)malloc(sizeof(set) * number_of_sets);
}

Как правило, при использовании переменных, представляющих «количество» или «размер» объектов, предпочтительным является unsigned int (если вы не можете действительно имеют отрицательный счет или размер).

...