2013-07-04 71 views
2

我讨厌这样的语法问题,但我一直没能通过搜索找到答案。我不确定每个变量声明的含义。我对第三种猜测的最佳猜测是,它将逻辑和标签检查点的地址以及页面大小的倒数作为无符号长整型,然后将其重新命名为void指针。代码是从这里:http://nmav.gnutls.org/2011/12/self-modifying-code-using-gcc.html无法弄清楚这个c语法是什么

int (*my_printf) (const char *format, ...); 
void (*my_exit) (int); 
void *page = 
    (void *) ((unsigned long) (&&checkpoint) & 
    ~(getpagesize() - 1)); 

谢谢!

+1

前两个是函数指针 – FDinoff

+0

是的,这正是它所做的。不知道为什么你需要问这个。你所做的只是用言语表达这个表达。 –

+2

请注意,“标签地址”('&& checkpoint',here)是一个GNU C扩展,并且可能无法在其他编译器中使用。 – torek

回答

0

前两个函数指针分别与printfexit兼容。例如。你可以这样做:

my_exit = exit; 
my_exit(3); 

它就相当于叫exit(3)

你对第三点的猜测是正确的。这取决于页面大小始终是2的幂的事实。因此,pagesize-1将具有二进制模式,其全部位于低位,全0位于高位。反转它反转这些位。这可以用作带地址的位掩码,以返回地址指向的页面开始的地址。然后它将page设置为包含checkpoint的页面的开头。

+0

非常感谢。为什么他们使页面无效*虽然,而不是将其作为无符号长整型?另外,为什么该位掩码工作返回页面的开始?比如说,页面大小是8,检查点地址是00100000. pagesize-1的倒数是1111000。&将是00100000.为什么这一定是包含检查点的页面的开始?例如,它是否也可以从00011111开始,并且在包含检查点的情况下仍然保持8的页面大小? – user2142343

0

int (*my_printf) (const char *format, ...);声明一个函数指针,该指针返回一个int值,并将c样式字符串作为第一个参数,并在format参数之后具有可变数量的参数。

void (*my_exit) (int);声明一个函数指针,它不返回任何东西,但是接受一个int。

void *page = (void *) ((unsigned long) (&&checkpoint) & ~(getpagesize() - 1));声明了一个通用指针,该指针相当于指向checkpoint的指针的地址,页面大小减1。

5

my_printf是一个返回int的函数的指针,它接受一个char指针参数和其他变量列表。

my_exit是一个无返回值的函数指针,取一个int参数。

page是指向某种未指定类型的指针。它被分配了一个不应编译的表达式的值,因为&&是一个二元操作符,并且没有左操作数,并且一元地址的地址是没有意义的。 & ~(getpagesize() - 1)位掩盖了可能被认为是地址的低位,然后该地址将指向页面的开始。

一元&&是一个GNU C扩展,它接受一个(goto)标签的地址,所以这个构造基本上得到了包含该标签的代码页的起始地址。这是编译器和操作系统特定的东西,而不是真正的C语言的一部分。