Нужны некоторые разъяснения относительно литья в C - PullRequest
2 голосов
/ 21 декабря 2009

Я только что читал о плохой практике приведения возвращаемого значения malloc. Если я правильно понял, то абсолютно законно оставлять актерский состав, как это делается неявно (и его следует оставить из-за других проблем, которые он может вызвать). Ну, мой вопрос, когда я должен затем бросить свои ценности? Есть какое-то общее правило или что-то? Например, этот код компилируется без ошибок с gcc -W -Wall (за исключением неиспользованного bar, но это не главное):

float foo(void) {
    double bar = 4.2;
    return bar;
}

int main(void) {
    double bar = foo();
    return 0;
}

Я сейчас в замешательстве. Каковы хорошие практики и правила о кастинге?

Спасибо.

Ответы [ 13 ]

0 голосов
/ 21 декабря 2009

Предупреждение о приведении результата к malloc() является особым случаем из-за того, что C неявно присваивает результат ранее необъявленным функциям int (который IINM запрещен с C99).

Как правило, вы хотите максимально ограничить использование явных приведений; единственный раз, когда нужно , чтобы использовать его, это если вы пытаетесь присвоить значение одного типа переменной несовместимого типа (например, назначить значение указателя для переменной int или наоборот). Поскольку void * совместим с любым другим типом указателя, явное приведение не требуется. Однако, если вы пытаетесь присвоить значение типа int * переменной типа struct foo *, явное приведение является обязательным . Если вы обнаружите, что присваиваете значения несовместимых типов lot , то вы можете пересмотреть свой дизайн.

0 голосов
/ 21 декабря 2009

По сути, вам нужно для приведения аргументов к функциям, которые ожидают параметр, отличный от утверждений их прототипа.

Например, isalpha() имеет прототип с аргументом int, но на самом деле ожидает unsigned char.

char *p;
if ((*p != EOF) && isalpha((unsigned char)*p) /* cast needed */
{
    /* ... */
}

И вы должны быть особенно осторожны с функциями, которые принимают переменное число аргументов, например:

long big;
printf("%d\n", (int)big);

Редактировать

Компилятор не может преобразовать аргументы переменных функций в правильный тип, поскольку в самом прототипе нет информации о типе. Рассмотрим функцию, похожую на printf ()

int my_printf(const char *fmt, ...);

Насколько известно компилятору, вы можете передавать значения всех типов в аргументе "...", и вы должны убедиться, что аргументы соответствуют ожидаемой функции. Например, скажем, функция my_printf() принимает значение типа time_t с соответствующим спецификатором "% t" в строке формата.

my_printf("UNIX Epoch: %t.\n", 0);         /* here, 0 is an int value */
my_printf("UNIX Epoch: %t.\n", (time_t)0); /* and here it is a time_t */

Мой компилятор не хочет, чтобы этот сбой! Очевидно, он ( и тот, что на кодовой панели тоже ) передает 8 байтов для каждого аргумента в "..."

Используя прототип без "..." (int my_printf(const char *fmt, time_t data);), компилятор автоматически преобразует первый 0 в правильный тип.

Примечание: некоторые компиляторы (включая gcc) будут проверять аргументы против строки формата для printf(), если строка формата является литеральной строкой

0 голосов
/ 21 декабря 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...