Будет ли приведение к объединению совместимых типов возврата удовлетворять критериям совместимости для указателей на функции? - PullRequest
1 голос
/ 22 октября 2019

Чтобы объяснить, почему я пытаюсь это сделать, ограничения моей среды требуют от меня работы с автоматически сгенерированным кодом. Сгенерированный код очень похож, и я хотел бы вызвать пакет функций, которые в основном одинаковы. Мне нужно использовать решение, совместимое с C89 или C99.

Из чтения спецификаций ниже приведен правильный код, но я не уверен насчет приведения указателя функции для возврата типа объединения. Кто-нибудь может указать, если это законно или какую часть спецификации он нарушает?

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

/* Automagically generated types */

struct A_return_type {
    int index;
    unsigned int options;
};

struct A_return_type *A_function(int x) {
    struct A_return_type *A_return = malloc(sizeof(*A_return));
    A_return->index = x;
    A_return->options = 0xA;
    return A_return;
}

struct B_return_type {
    int index;
    unsigned int options;
};

struct B_return_type *B_function(int x) {
    struct B_return_type *B_return = malloc(sizeof(*B_return));
    B_return->index = x;
    B_return->options = 0xB;
    return B_return;
}

struct C_return_type {
    int index;
    unsigned int options;
};

struct C_return_type *C_function(int x) {
    struct C_return_type *C_return = malloc(sizeof(*C_return));
    C_return->index = x;
    C_return->options = 0xC;
    return C_return;
}

/* End generated types */

int main(int argc, char *argv[]) {
    /*--------------------------------------------------------------
    All of the generated methods take the same arguments and return
    structs with the same members in the same order. It is permitted
    to inspect the common initial part of any structs in a union,
    per C89 3.3.2.3 p5.
    --------------------------------------------------------------*/
    union return_types {
        struct {
            int index;
            unsigned int options;
        } common_return;
        struct A_return_type A_return;
        struct B_return_type B_return;
        struct C_return_type C_return;
    };

    /*----------------------------------------------------------
    Function pointers are compatible if their return types and
    parameter lists are compatible per C89 3.5.4.3 p9.
    ----------------------------------------------------------*/
    typedef union return_types *(*generated_function)(int);

    generated_function function_array[] = {
          (generated_function)A_function
        , (generated_function)B_function
        , (generated_function)C_function
    };

    for(int i = 0; i < sizeof(function_array)/sizeof(function_array[0]); ++i) {
        printf("%x\n", function_array[i](0)->common_return.options);
    }
}

1 Ответ

2 голосов
/ 23 октября 2019

Вы можете преобразовать указатели на функции в указатели других типов в функции, которые вам нужны (C 2018 6.3.2.3 8: «Указатель на функцию одного типа может быть преобразован в указатель на функцию другого типа…»), но если вы используете преобразованный указатель для вызова функции с несовместимым типом, стандарт C не определяет поведение ( ibid : «… если преобразованный указатель используется для вызова функциичей тип не совместим с ссылочным типом, поведение не определено. »).

Функция, которая возвращает struct A_return_type *, не совместима с функцией, которая возвращает union return_types *. Вы почти сохранены в 6.2.5 28, где говорится: «… Все указатели на типы структуры должны иметь те же требования к представлению и выравниванию, что и другие. Все указатели на типы объединений должны иметь те же требования к представлению и выравниванию, что и другие ... », а в сноске говорится:« Те же требования к представлению и выравниванию предназначены для обеспечения взаимозаменяемости в качестве аргументов функций, возвращаемых значений из функций и членов объединений ». . »Эта взаимозаменяемость означает, что функция, возвращающая struct foo *, совместима с функцией, возвращающей struct bar *. К сожалению, вы вызываете функцию, которая возвращает указатель на структуру с выражением для функции, которая возвращает указатель на объединение, и в стандарте не говорится, что они имеют одинаковые требования к представлению и выравниванию или что они взаимозаменяемы.

...