LINUX.ORG.RU

Приведение типа аргумента функции в С

 ,


1

2

В С аргументы функции приводятся к типу указанному при объявлении т.е. если функция ожидает в качестве аргумента int, а передали, к примеру char, то произойдет неявное приведение char -> int

В С++ такой вариант уже не пройдет и компилятор выдаст ошибку.

Вопрос в следующем - существуют ли какие-то «стандартные» инструменты для С, запретить приведение, как в С++?


В С++ такой вариант уже не пройдет и компилятор выдаст ошибку.

Произойдёт и не выдаст.

существуют ли какие-то «стандартные» инструменты для С, запретить приведение, как в С++?

Есть - struct int_t { int v; }; - никуда ничего приводить не будет. В C++ можно это реализовать полноценно(правда оно там не особо нужно, поскольку есть (auto)). Но никто писать на таком не захочет.

anonymous
()
Ответ на: комментарий от pavel_l

Вызов функции тут ни при чём, ты мог бы etype b=0; написать с тем же результатом.

Не знал, что в С++ сейчас это выдаёт ошибку, но это именно свойство enum-а, а не приведения типов вообще. В Си такое скорее всего не предусмотрено. А ещё ни там ни там не выдаёт ошибку int a=ONE;. На мой взгляд неявную конвертацию int <-> enum в обе стороны надо запретить и в Си тоже, но от этого сломается много старого кода.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)

MISRA C. Сущесвуют компиляторы, которые делают более строгие проверки во время компиляции. Например, там не скомпилируется

uint32_t i=0;

vromanov ★★★
()
Ответ на: комментарий от pavel_l

То есть я тебе показал решение, далее пришёл персонаж с «решения нет»(а также пропагандой «неявные касты плохо») и ты родил на это «спасибо»? Ну такими темпами мир познаешь на отличненько, инфа сотка.

anonymous
()
Ответ на: комментарий от pavel_l

Я не про то, что ты там мне не сказал что-то - это ничего не значит. Но ты же учиться вроде пытаешься, и ответ «решения нет» - это последнее, что должно тебя устроить. Ты мог бы попытаться хотя бы чем-то таким решить:

enum x {
    zero,
#define zero ((enum x)zero)
    one,
#define one ((enum x)one)
    two
#define two ((enum x)two)
};
int _f(enum x v) { return v; }
#define f(v) _Generic(v, enum x: _f(v))
int main() { return f(zero); }

Оно конечно не особо работает, но толку было бы куда больше, чем просто принять «решения не существует».

anonymous
()
Ответ на: комментарий от anonymous

но толку было бы куда больше, чем просто принять «решения не существует».

Додумывать за других – плохая привычка. Меня не устроил ответ «решения нет», особенно после предложенного тобой варианта. Честно скажу для меня он не очевидный и мне потребовалось какое-то время, чтобы понять, как его можно применить.

Более развернутый ответ мне добавил понимания, еще раз спасибо.

pavel_l
() автор топика
Ответ на: комментарий от anonymous

Нет ли у вас решения на вот этот случай?

https://godbolt.org/z/Ebz41sqcz

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

void FreePtr(void **Ptr) {
    if (Ptr)
        if (*Ptr) {
            free(*Ptr);
            *Ptr = NULL;
        };
}

int main(void) {
    void *NullPtr = NULL;
    char *StringPtr = NULL;
    int *IntPtr = NULL;
    int Int = 0;

    StringPtr = strdup("StringPtr");
    IntPtr = malloc(sizeof(int));
    *IntPtr = 123;

    // Хочется написать так, чтобы не было ошибок и предупреждений:
    // FreePtr(&NullPtr);
    // FreePtr(&StringPtr);
    // FreePtr(&IntPtr);

    // А здесь наоборот, чтобы давало ошибку или предупреждение при компиляции.
    // FreePtr(&Int);

    // Приходится писать так:
    FreePtr(&NullPtr);
    FreePtr((void**)&StringPtr);
    FreePtr((void**)&IntPtr);

    // Однако, из-за (void**) можно легко выстрелить себе в ногу.
    // Поэтому, есть желание уйти от (void**), но вот как, не понятно.
    FreePtr((void**)&Int);

    return 0;
}
Vic
()

Плюсы приводят примитивы так же хорошо, как и си. А ещё они могут неявно приводить структуры и классы за счёт не-explicit конструкторов с одним аргументом или перегрузки оператора приведения типов.

Если нужно от этого защититься, то в си только оборачивать примитивы в структуры. В плюсах ещё можно строже ограничивать аргументы шаблонной функции за счёт концептов, но распространять такое на всю кодовую базу для больших любителей странного.

Ещё можно не писать ни на си, ни на плюсах. Тогда, возможно, автоприведение примитивов не будет происходить в зависимости от выбора языка.

KivApple ★★★★★
()