C语言:声明指向函数的volatile指针

14

如何在C语言中声明一个函数指针,使得指针本身是volatile。

static void volatile (* f_pointer)(void*);

static void (volatile * f_pointer)(void*);

static void (* volatile f_pointer)(void*);

为什么我会问这个问题呢?因为我在http://wiki.answers.com/Q/Volatile_example_code_sample_coding_of_volatile_pointer上读到了有关volatile指针的内容。

使用volatile指针和指向volatile的指针时有时会出现问题:

现在,事实证明指向volatile变量的指针非常常见。这两个声明都将foo声明为指向volatile整数的指针:

volatile int * foo; 
int volatile * foo; 

指向非volatile变量的volatile指针非常罕见(我想我只用过一次),但我最好还是给你语法:

int * volatile foo;

因此,我想获取指向函数的易失性指针,而不是指向“易失性”函数的指针。

谢谢


4
你为什么需要一个指向函数的易失性指针?谁将更改这个指针?你知道“volatile”是什么意思吗? - James McNellis
@James McNellis,是的,我想要。这个指针被线程0更改,并被线程1..7用于启动函数。之间有一个屏障,但我希望编译器在进入屏障之前将此指针刷新到内存中的线程0。此外,我希望线程1..7重新读取此指针(有一个循环{barrier,pointer read,calling function})。我使用了一个具有大量可用寄存器的系统,因此编译器可以缓存许多变量。我是对的吗? - osgx
如果屏障写得正确,编译器就不应该在屏障之间缓存值 - volatile 应该是不必要的。 - caf
1
@caf,很高兴见到你。关于这段代码 a=1; pthread_barrier(); b=a;,pthread_barrier是一个错误的写法吗?编译器对该函数内部一无所知。编译器是否可以在该函数调用周围缓存变量a的值(在其看来,这是普通的函数调用)?编译器可以缓存任何非volatile变量。 - osgx
3
在正确的pthread实现中,pthread_barrier_wait()必须充当编译器屏障(防止其它值被缓存越过该屏障)。实际上,并不需要特定的编译器支持,因为pthread_barrier_wait()是一个外部函数,所以编译器必须假设它可能会修改任何全局变量或任何地址被取出的变量(换言之,从编译器的角度看,可能是pthread_barrier_wait()修改了a,而不是另一个线程)。 - caf
3个回答

20

把星号看作是一个“障碍”。比变量名更靠近星号的限定符(如constvolatile)会修改指针本身。比星号更远离变量名的限定符会修改指针所指向的内容。因此,在这种情况下,您将会有:

static void * volatile f_pointer(void *);

当然,如果你要定义一个指向函数的指针,你需要使用括号而不是声明一个返回指针的函数:

static void (*volatile f_pointer)(void *);

static是一种存储类而不是限定符,因此对于它的情况,不能这样说。您只能为变量本身指定存储类,而不能为它所指向的内容指定存储类。不存在"指向extern int"或"指向static int"的概念,只有"指向int"的概念。如果您指定了存储类(staticextern),它总是出现在首位

其他线程讨论了线程和volatile之间的关系,因此我不会在此重复讨论,只是提醒这可能没有用。


10

cdecl在这类问题中非常有用:

$ cdecl
Type `help' or `?' for help
cdecl> declare f_pointer as static volatile pointer to function(pointer to void) returning void
static void (* volatile f_pointer)(void *)
cdecl>

cdecl的源码:http://cdecl.org/files/cdecl-blocks-2.5.tar.gz


@osgx,它已经包含在许多开发环境中了。我记得我的是从源代码构建的,但我不记得我从哪里得到它了。你可以在http://cdecl.org/上在线使用它。 - Carl Norum
谢谢!你能说出一些包含cdecl的IDE吗?(我认为任何包含cdecl的IDE都必须非常用户友好) - osgx
@osgx,抱歉 - 我不知道有这样的东西。我只是将其用作命令行程序。 - Carl Norum

9
static void (* volatile f_pointer)(void*);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接