c用于设置位的宏

时间:2012-03-26 23:53:09

标签: c macros

我有一个程序比较两个结构的变量,并相应地为位图变量设置一个位。我必须比较结构的每个变量。实际变量的数量对于每个结构更多但是为了简单起见,我花了3.我想知道我是否可以创建一个宏来比较变量并相应地设置位图中的位。

#include<stdio.h>


struct num 
{
   int a;
   int b;
   int c;
};

struct num1
{
   int d;
   int e;
   int f;
};

enum type
{
   val1 = 0,
   val2 = 1,
   val3 = 2,
};
int main()
{
  struct num obj1;
  struct num1 obj2;
  int bitmap = 0;

  if( obj1.a != obj2.d)
  {
      bitmap  = bitmap | val1;
  }
  if (obj1.b != obj2.e)
     bitmap = bitmap | val2;

  printf("bitmap - %d",bitmap);
  return 1;


}

我可以声明一个宏......

#define CHECK(cond)
  if (!(cond))
    printf(" failed check at %x: %s",__LINE__, #cond);
    //set the bit accordingly

#undef CHECK

4 个答案:

答案 0 :(得分:0)

除了需要对多行宏使用反斜杠

之外,您应该可以这样做
#ifndef CHECK
    #define CHECK(cond) \
    if (!(cond)) { \
      printf(" failed check at %x: %s",__LINE__, #cond); \
      //set the bit accordingly
    }
#endif /* CHECK */

答案 1 :(得分:0)

通过一点点护理,您可以相当轻松地完成。您只需要仔细确定要比较和设置的内容,并将它们作为宏参数传递。用法示例:

CHECK(obj1.a, obj2.d, bitmap, val1);
CHECK(obj1.b, obj2.e, bitmap, val2);

这假定CHECK的定义类似于:

#define STRINGIFY(expr) #expr

#define CHECK(v1, v2, bitmap, bit) do \
    { if ((v1) != (v2)) \
         {   printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
             (bitmap) |= (1 << (bit)); \
         } \
    } while (0)

当然,你可以随心所欲地放置宏;我对此并不十分满意,但这并不太可怕。

演示代码

编译和测试运行:

$ gcc -Wall -Wextra -g -O3 -std=c99 xx.c -o xx && ./xx
failed check at 40: obj1.a != obj2.d
failed check at 42: obj1.c != obj2.f
bitmap - 5
$

实际代码:

#include <stdio.h>

struct num 
{
   int a;
   int b;
   int c;
};

struct num1
{
   int d;
   int e;
   int f;
};

enum type
{
   val1 = 0,
   val2 = 1,
   val3 = 2,
};

#define STRINGIFY(expr) #expr

#define CHECK(v1, v2, bitmap, bit) do \
    { if ((v1) != (v2)) \
      {   printf("failed check at %d: %s\n", __LINE__, STRINGIFY(v1 != v2)); \
      (bitmap) |= (1 << (bit)); \
      } \
    } while (0)


int main(void)
{
    struct num  obj1 = { 1, 2, 3 };
    struct num1 obj2 = { 2, 2, 4 };
    int bitmap = 0;

    CHECK(obj1.a, obj2.d, bitmap, val1);
    CHECK(obj1.b, obj2.e, bitmap, val2);
    CHECK(obj1.c, obj2.f, bitmap, val3);

    printf("bitmap - %X\n", bitmap);
    return 0;
}

显然,此代码依赖于您在CHECK宏的调用中匹配正确的元素和位数。

可以使用offsetof()等设计更复杂的方案,并使用描述数据结构的初始化数组等,但最终会得到一个更复杂的系统并且收效甚微。特别是,调用不能大大减少参数计数。你可以假设'bitmap'是变量。您需要识别这两个对象,因此您将指定'obj1'和'obj2'。在该行的某处,您需要确定要比较的字段和要设置的位。这可能是一些单一的值(也许是位数),但你仍然有3个参数(CHECK(obj1, obj2, valN)和假设bitmap)或4个参数(CHECK(obj1, obj2, bitmap, valN)而没有假设bitmap),但很多背景复杂性,可能更容易出错。如果您可以修改代码以便您只有一种类型而不是两种类型等,那么您可以使用假设的系统使生活更轻松,但是我认为处理工作代码中显示的方式仍然更简单

我同意gbulmer我可能不会这样做,但你确实声明你已经大大减少了结构的大小(为此,谢谢!)它会变得更加诱人字段数增加(但我只在一个函数中写出一对结构类型的比较)。

您还可以将宏修改为:

#define CHECK(cond, bitmap, bit) do \
    { if (cond) \
      {   printf("failed check at %d: %s\n", __LINE__, STRINGIFY(cond)); \
          (bitmap) |= (1 << (bit)); \
      } \
    } while (0)

CHECK(obj1.a != obj2.d, bitmap, val1);
...
CHECK((strcmp(obj3.str1, obj4.str) != 0), bitmap, val6);

最后一行显示这将允许您选择任意比较,即使它们包含逗号。请注意围绕strcmp()

调用的额外括号

答案 2 :(得分:0)

如果你想得到真正的花哨(和简洁),你可以使用连接运算符。我还建议稍微更改你的结构以具有不同的命名约定,虽然不知道你正在尝试用它做什么,但很难说。我还注意到你的位字段中有一个值为0;当你试图查看那个位值时,这不会告诉你太多。如果您对任何东西进行OR 0,它将保持不变。无论如何,这是你的程序稍作重写:

struct num {
   int x1; // formerly a/d
   int x2; // formerly b/e
   int x3; // formerly c/f
};

enum type {
   val1 = 1, // formerly 0
   val2 = 2, // formerly 1
   val3 = 4, // formerly 2
};

// CHECK uses the catenation operator (##) to construct obj1.x1, obj1.x2, etc.
#define CHECK(__num) {\
   if( obj1.x##__num != obj2.x##__num )\
     bitmap |= val##__num;\
}

void main( int argc, char** argv ) {
  struct num obj1;
  struct num obj2;
  int bitmap = 0;

   CHECK(1);
   CHECK(2);
   CHECK(3);
}

答案 3 :(得分:0)

作为一个合理的经验法则,当尝试做位数组是C时,需要有一个可用于索引该位的数字。

您可以将该位数传递给宏,也可以尝试派生它。

在编译时或运行时,唯一可用的是字段的地址 所以你可以使用它。

如果可能有效,有几个问题需要了解。 对于你的结构:

  1. 所有字段的顺序是否相同?即你可以将c与f进行比较,而不是将c与e进行比较?
  2. 所有相应字段的类型是否相同
  3. 条件是否平等?每个宏都将连接条件,因此每个条件都需要一个新的宏。

    如果答案是肯定的,那么你可以使用地址:

    #define CHECK(s1, f1, s2, f2) do \
        { if ((&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2)) \
             || (s1.f1) != (s2.f2) \
             {   printf("failed check at %d: ", #s1 "." #f1 "!=" #s1 "." #f1 "\n", \
                                         __LINE__); \
                 (shared_bitmap) |= (1 << (&s1.f1-&s1)); // test failed \
             } \
        } while (0)
    

    我不太清楚它是否是所有比较的位图,或者每个结构对一个位图。我认为这是一个适合所有人的地图。

    有很多检查确保你没有违反“两条规则”:

    (&s1.f1-&s1 != &s2.f2-&s2) || (sizeof(s1.f1)!=sizeof(s2.f2))
    

    如果您确信测试是正确的,没有这些限制,只需将测试的那部分扔掉。

    警告我没有编译该代码。

    如果值是数组,则变得更加简单。

    我可能不会用它。对我来说似乎有点太棘手了: - )