_枚举器(Enum)的通用语句?

问题描述 投票:0回答:1

我经常需要处理 C 中

enum
的功能。然而,似乎没有一种简单且同样有效的方法来根据预定义的
enum
值提供不同的结果——至少,不适合我的情况。采取以下代码:

/**
 * @brief An enumerator to represent all the various numerical types that
 * can be stored in the @ref dynamic_array_number_t. This is simply a list
 * of the various integer types that can fit into a signed 64-bit integer.
 */
typedef enum
{
    /**
     * @brief Unsigned 8-bit integer.
     */
    unsigned8,
    /**
     * @brief Unsigned 16-bit integer.
     */
    unsigned16,
    /**
     * @brief Unsigned 32-bit integer.
     */
    unsigned32,
    /**
     * @brief Signed 8-bit integer.
     */
    signed8,
    /**
     * @brief Signed 16-bit integer.
     */
    signed16,
    /**
     * @brief Signed 32-bit integer.
     */
    signed32
} dynamic_array_number_type_t;

/**
 * @brief A dynamic array for integers. Can store an infinite amount of
 * members, if your computer's got the memory. All functions having to do
 * with this type are suffixed with "-N".
 */
typedef struct
{
    /**
     * @brief The list of the array's members. Stored in 8 bytes (64 bits)
     * since it provides integer safety, along with being a sort of generic
     * for all the possible integer types. Do not mess with this value
     * yourself, use helper functions. Do not retrieve values within this
     * array yourself, use helper functions.
     */
    int64_t* members;
    /**
     * @brief The type of integer we're storing in the array. This cannot
     * change, and is therefore marked with const. See @ref
     * dynamic_array_number_type_t for more information.
     */
    const dynamic_array_number_type_t type;
    /**
     * @brief The size of the array (in 64-bit blocks of memory). This is
     * simply a counter of how many numbers it @b can store, not @b is
     * storing. That is stored in the @ref occupied value. Do not increment
     * this value yourself, use helper functions.
     */
    size_t size;
    /**
     * @brief The count of members within the array. Do not mess with this
     * value, the program will very nearly always crash. Use helper
     * functions.
     */
    uint32_t occupied;
} dynamic_array_number_t;

/**
 * @brief Allocate a block of memory of @param size bytes long. This is
 * legitimately just @ref xmalloc but with a name that fits my scheme.
 * @param size The size--in bytes--of the block to allocate.
 * @return A pointer to to newly allocated block.
 */
void* AllocateBlock(size_t size);

/**
 * @brief Create a new dynamic array for integer types. You must free the
 * object returned by this function with @ref DestroyDynamicArrayN.
 * @param type The integer type this array should contain when converted
 * from the default int64_t.
 * @param size The size the array should be off the bat; this can be
 * changed via helper functions like @ref GrowDynamicArrayN or @ref
 * ShrinkDynamicArrayN.
 * @return A brand-spanking-new integer dynamic array.
 */
inline static dynamic_array_number_t
CreateArrayN(dynamic_array_number_type_t type, size_t size)
{
    return (dynamic_array_number_t){AllocateBlock(sizeof(int64_t) * size),
                                    type, size, 0};
}

/**
 * @brief Destroy the given integer array. The array passed into this
 * function, upon the completion of it, shall have none of its prior data
 * beyond the value of its @ref type member, and all deleted data shall
 * have been destroyed irretrievably.
 * @param array The array to destroy.
 */
void DestroyArrayN(dynamic_array_number_t* array);

// This is in a separate C file.
void* AllocateBlock(length_t size)
{
    void* ptr = malloc(size);
    if (ptr == NULL) LogError(failed_allocation);
    return ptr;
}

void DestroyArrayN(dynamic_array_number_t* array)
{
    assert(array != NULL && array->members != NULL);
    free(array->members);
    
    array->members = NULL;
    array->size = 0;
    array->occupied = 0;
}

以及数组创建的示例:

int main(void) {
    dynamic_array_number_t test_array = CreateArrayN(unsigned8, 3);
    // ... do stuff with array
    DestroyArrayN(&test_array);

    return 0;
}

我需要将结构中的

int64_t
转换为用户在创建数组时提供给数组的任何整数类型,
uint8_t
int32_t
,等等。当然,这很容易,使用像
(int8_t)array.members[0]
这样的简单转换。然而,我想提供一个辅助函数来使这种访问更容易,但我不想只返回一个
int64_t
就到此为止;这似乎毫无意义。

相反,有没有一种方法(类似于类型的 _Generic 语句)可以为传入数组的

type
值的任何可能值提供不同的函数?

c enums switch-statement
1个回答
0
投票

有没有一种方法(类似于类型的 _Generic 语句)可以为传入数组的类型值的任何可能值提供不同的函数?

不。类似于 unsigned8

unsigned16
的枚举
value
是运行时可用的信息,但 type 是编译时可用的信息。您无法进行时间旅行 - 一旦您使用在运行时具有值的value,它就不会影响编译时的类型。

如果您想要在编译时获得类型信息,则必须在编译时提供该信息。通常,人们会在编译时使用不同的 types 来表示该信息,例如

struct dynamic_array_signed8
struct dynamic_array_unsigned8
等。您可能对 STC 库感兴趣。

总的来说,使用 enum 值来表示不同的 types 是一个坏主意,这会导致超长的切换:https://github.com/Gurux/GuruxDLMS.c/blob/master/development/src /gxobjects.c#L1323 。您可能对虚拟方法 https://en.wikipedia.org/wiki/Virtual_method_table 非常感兴趣,以在运行时实现对象特定的动态调度

© www.soinside.com 2019 - 2024. All rights reserved.