我想根据C语言代码的类型添加另一种类型

问题描述 投票:0回答:1
#include "stdio.h"

#define TYPE_DATA_DEFINE(name) \
    name; \
    unsigned char name##valid;\

#define TYPE_DATA_SET(name, value) \
    name##valid = 1; \
    name = value;    \

#define TYPE_DATA_GET(name, value) \
    (name##valid == 1 ? (value = name, 1) : 0)

#define TYPE_DATA_CLEAR(name) \
    name = 0;    \
    name##valid = 0; \

struct hh {
    unsigned char TYPE_DATA_DEFINE(max);
    unsigned char TYPE_DATA_DEFINE(min);
};

int main(void)
{
    struct hh hhs = { 0 };
    unsigned char tmp;

    if (SSWL_TYPE_DATA_GET(hhs.max, tmp)) {
        printf("info, tmp:(%u)", tmp);
    } else {
        printf("info, tmp:(%u)", tmp);
    }

    return 0;
}

我想根据C语言代码的类型添加另一种类型。该类型保留了原来的任意类型,但在此基础上增加了一个unsigned char类型的有效字段。

  1. 获取当前数据之前,首先判断数据是否有效。如果有效,则返回数据。如果无效,返回0。
  2. 设置数据时,将有效字段设置为有效,同时分配数据。

但是我遇到了两个问题。不知道有没有人有好的解决办法:

  1. 使用 GET 和 SET 时,如果类型不匹配,编译器不会发出警告。然而,这对于编写安全的 C 代码是不允许的。如何在具有参数类型检查功能的同时,保持上述功能。
  2. 我的宏不支持数组定义。有没有好的方法来实现数组定义?

我考虑了 C11 的 _Static_assert 语法和 GNU 的 #define static_assert(condition)
形式为 typedef char static_assert_failed[(condition) ? 1 : -1],还有更好的办法吗?

c
1个回答
0
投票
  1. 使用 GET 和 SET 时,如果类型不匹配,编译器不会发出警告。然而,这对于编写安全的 C 代码是不允许的。如何 我们可以在保留参数类型的同时保持上述功能吗 检查功能。
  1. 宏不是函数。所提供的代码中唯一的函数是

    main()

  2. 宏调用扩展到 C 源代码。如果您想要有关类型不完全匹配的赋值的警告,那么这与您对宏的使用没有特别关系,因为此类警告将基于生成的扩展代码。

  3. 你的编译器可能会发出什么诊断信息是你和它之间的事。任何特定的人可能有也可能没有诊断您所询问的情况的设施。

    如果您碰巧正在使用 GCC,那么打开

    -Wconversion
    可能会得到您想要的诊断(我含糊其辞,因为我不确定我是否完全理解您想要的东西)。其他模拟 GCC 命令行选项(Clang、icc 等)的编译器也可能支持该选项。不模拟 gcc 选项的编译器可能有自己的版本。

  1. 我的宏不支持数组定义。有没有好的方法来实现数组定义?

我不认为你的宏堆栈有什么特别好的地方。但是,您可以通过添加维度/索引参数来使其支持数组。请注意,宏参数可以根本不包含任何标记,这就是您将与标量一起使用的内容。示例:

#define TYPE_DATA_DEFINE(name, dim) \
    name dim; \
    unsigned char name##valid;\

#define TYPE_DATA_SET(name, index, value) \
    name##valid = 1; \
    name index = value;    \

#define TYPE_DATA_GET(name, index, value) \
    (name##valid == 1 ? (value = name index, 1) : 0)

#define TYPE_DATA_CLEAR(name, index) \
    name index = 0;    \
    name##valid = 0; \

struct hh {
    unsigned char TYPE_DATA_DEFINE(scalar,);
    unsigned char TYPE_DATA_DEFINE(array, [3]);
};

int main(void)
{
    struct hh hhs = { 0 };
    unsigned char tmp = 42;

    if (TYPE_DATA_GET(hhs.scalar,, tmp)) {
        printf("info, tmp:(%u)", tmp);
    } else {
        printf("info, tmp:(%u)", tmp);
    }

    if (TYPE_DATA_GET(hhs.array, [1], tmp)) {
        printf("info, tmp:(%u)", tmp);
    } else {
        printf("info, tmp:(%u)", tmp);
    }

    return 0;
}

如果您希望数组成员具有有效性标志数组,那么您可以修改上面的内容来实现。

但是不要。不要做任何这样的事情。这太糟糕了,而且没有办法让它变得更好。我不仅不喜欢它的实现,也不喜欢每个成员有效性标签的整个基本概念。

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