我讨厌问这样的语法问题,但是我无法通过搜索找到答案。我不确定每个变量声明的含义。我对第3个问题的最佳猜测是,它采用标签检查点的逻辑和地址以及页面大小的倒数,将其作为无符号长整型,然后将其重新设置为void指针。代码来自此处:http://nmav.gnutls.org/2011/12/self-modifying-code-using-gcc.html
int (*my_printf) (const char *format, ...);
void (*my_exit) (int);
void *page =
(void *) ((unsigned long) (&&checkpoint) &
~(getpagesize() - 1));
谢谢!
答案 0 :(得分:5)
my_printf
是一个返回int的函数的指针,它接受一个char指针参数和一个其他的变量列表。
my_exit
是指向没有返回值的函数的指针,带有一个int参数。
page
是指向某些未指定类型的指针。它被分配了一个不应该编译的表达式的值,因为&&
是一个二元运算符并且没有左操作数,并且一元地址是没有意义的。 & ~(getpagesize() - 1)
位掩盖了可能意味着地址的低位,然后指向页面的开头。
一元&&
是GNU C扩展,它接受(goto)标签的地址,因此这种结构基本上获取包含该标签的代码页的起始地址。这是特定于编译器和操作系统的东西,而不是C语言的真正部分。
答案 1 :(得分:0)
前两个是分别与printf
和exit
兼容的函数指针。例如。你可以这样做:
my_exit = exit;
my_exit(3);
,这相当于调用exit(3)
。
你对第三个问题的猜测是正确的。它取决于页面大小始终为2的幂的事实。因此,pagesize-1
将具有二进制模式,该模式在低位中全部为1,高位中的所有0都是0。反转它会反转这些位。这可以用作带有地址的位掩码,以返回地址所指向的页面开头的地址。然后,它会将page
设置为包含checkpoint
的页面的开头。
答案 2 :(得分:0)
int (*my_printf) (const char *format, ...);
声明一个返回int的函数指针,并将一个c样式字符串作为第一个参数,在format参数后面有一个可变数量的参数。
void (*my_exit) (int);
声明一个不返回任何内容的函数指针,但是接受一个int。
void *page = (void *) ((unsigned long) (&&checkpoint) & ~(getpagesize() - 1));
声明一个通用指针,该指针等同于指向页面大小减去1的checkpoint
指针的地址。