C 可以用变量体定义类似宏的函数吗?

C 可以用变量体定义类似宏的函数吗?,c,macros,mutex,C,Macros,Mutex,我一直在寻找定义宏的方法,看起来我想要的是不可能的,但我想如果是的话,这里的人会知道的 我要做的是定义此宏: synchronized(x) { do_thing(); } 扩展至: { pthread_mutex_lock(&x); do_thing(); pthread_mutex_unlock(&x); } 在C++中,我可以在构造函数中获取锁的同步块< /代码>对象,并在析构函数中解锁,但是我不知道如何在C. < /P>中实现它。 我意识到

我一直在寻找定义宏的方法,看起来我想要的是不可能的,但我想如果是的话,这里的人会知道的

我要做的是定义此宏:

synchronized(x) {
  do_thing();
}
扩展至:

{
    pthread_mutex_lock(&x);
    do_thing();
    pthread_mutex_unlock(&x);
}
<>在C++中,我可以在构造函数中获取锁的<代码>同步块< /代码>对象,并在析构函数中解锁,但是我不知道如何在C. < /P>中实现它。
我意识到我可以使用
synchronized(x,&myfunction)形式的函数指针,但我的目标是使一些C代码看起来尽可能像Java。是的,我知道这是邪恶的。

这是一个开始,但你可能需要调整它:

#define synchronized(lock, func, args...) do { \
    pthread_mutex_lock(&(lock)); \
    func(##args); \
    pthread_mutex_unlock(&(lock)); \
} while (0)
这样使用(不幸的是,不是您想要的类似Java的语法):


编辑:更改为Nategose的版本

#define synchronized(lock) \
for (pthread_mutex_t * i_#lock = &lock; i_#lock; \
     i_#lock = NULL, pthread_mutex_unlock(i_#lock)) \
    for (pthread_mutex_lock(i_#lock); i_#lock; i_#lock = NULL)
您可以这样使用它:

synchronized(x) {
    do_thing(x);
}
甚至没有支架

synchronized(x)
    do_thing();

这是我想到的最好的:

#define synchronized(x, things) \
      do { \
           pthread_mutex_t * _lp = &(x); \
           pthread_mutex_lock(_lp);      \
           (things);                     \
           pthread_mutex_unlock(_lp);    \
      } while (0)

...

        synchronized(x,(
                          printf("hey buddy\n"),
                          a += b,
                          printf("bye buddy\n")
                        ));

请注意,您必须使用很少使用的逗号运算符,并且对同步代码列表(不太像java)中的代码有限制。

非常有趣的问题

我看了其他答案,喜欢使用
for
的答案。如果可以的话,我有一个进步!GCC 4.3引入了计数器宏,我们可以使用它生成唯一的变量名

#define CONCAT(X, Y) X##__##Y
#define CONCATWRAP(X, Y) CONCAT(X, Y)
#define UNIQUE_COUNTER(prefix) CONCATWRAP(prefix, __COUNTER__)

#define DO_MUTEX(m, counter) char counter; \
for (counter = 1, lock(m); counter == 1; --counter, unlock(m))

#define mutex(m) DO_MUTEX(m, UNIQUE_COUNTER(m))
使用这些宏,这段代码

mutex(my_mutex) {
    foo();
}
。。。将扩展到

char my_mutex__0;
for (my_mutex__0 = 1, lock(my_mutex); my_mutex__0 == 1; --my_mutex__0, unlock(m)) {
    foo();
}

我的互斥从0开始,每次使用时都会生成一个新名称!您可以使用相同的技术创建类似监视器的代码体,并为互斥体指定一个唯一但未知的名称。

在尝试使一种语言看起来像另一种语言之前,您确实应该三思而后行。如果一个宏看起来像你要的语法,读它的人会非常困惑,因为C.R.是正确的,这可能会使阅读变得困难,因为这是一个宏,不容易看到。我认为最好是坚持宏应该是大写的惯例,并且名称应该是真正有用的。我会选择像“相互排除”这样的东西。^
是的,我知道这是邪恶的。
看起来像是
做的。。。虽然(0)
不是必需的,但是
{..}
单独工作(至少对于gcc是这样)。这仍然需要像
synchronized(x,function)
这样的块,而不是
synchronized(x){/*function*/}
,这既令人惊讶又令人恐惧。我从来没有想过。这应该可以解决这两个问题:
\define synchronized(lock)
\
for(pthread\u mutex\u t*I=&lock;I\u;I=NULL)
\`for(pthread\u mutex\u lock(I);I\u;` pthread\u mutex\u unlock(I),I\u=NULL)`或者,用一个
for()
并检查是否已获得锁:
定义同步(MUTEX)\for(pthread\u MUTEX\u t*synchronized\u MUTEX\u=&MUTEX;\synchronized\u MUTEX\u&&!pthread\u MUTEX\u lock(synchronized\u MUTEX);\pthread\u MUTEX\u unlock(synchronized\u MUTEX),synchronized\u MUTEX\u=0)
此外,这在流控制方面存在一些缺陷<代码>中断
继续
转到
返回
的操作可能与程序员预期的不同:前两个操作只会在宏内部终止的
,而不是封闭结构。后两个将跳过
pthread\u mutex\u unlock
,因此不会释放锁。此版本不允许嵌套同步块。为了修复这一问题,我将
I_u
更改为
I_35;#锁
(因此
synchronized(some_lock)
扩展为
for(pthread_mutex*I_some_lock=&some_lock;…
。另外,
synchronized(some_lock)synchronized(some_lock){}
将导致编译器错误。我喜欢这种方法,但如果我传递一个结构成员,它就不起作用。
同步(对象->锁){/*stuff*/}
扩展到
char object->lock\uu 0;/*etc*/
,这会导致问题,因为lock\uu 0不是结构成员。啊,没错=(不管怎样,上面修改过的答案看起来更好,而且不需要计数器。干杯!只需命名变量
\u lock\u35;_35;u COUNTER\uuuu
,似乎就行了(并解决了另一个实现中的问题)。
char my_mutex__0;
for (my_mutex__0 = 1, lock(my_mutex); my_mutex__0 == 1; --my_mutex__0, unlock(m)) {
    foo();
}