C: 在编译时或 运行 时检查变量是否具有静态存储-class 说明符
C: check at compile time or at run time that variable has static storage-class specifier
是否有可能以某种方式在编译时或 运行 时检查变量是否具有 static
存储-class 说明符?
示例:
static int v1;
int v2;
bool r1 = is_static(v1); /* true */
bool r2 = is_static(v2); /* false */
免责声明:以下代码不符合标准、可移植,甚至不安全。请不要在生产中使用它。
我们可以通过检查变量是否在栈上来判断一个变量是否是静态的。 Out 函数 is_static()
有两个参数。第一个是指向我们要检查的变量的指针,第二个是指向堆栈开头的指针(这就是 a
的用途)。然后它使用 getrlimit() 来确定该堆栈末尾的位置并检查我们的变量是否在堆栈上。这应该适用于大多数类 unix 系统。
#include <stdio.h>
#include <sys/resource.h>
_Bool is_static(void* var, char* stack_start)
{
struct rlimit stack; // Use getrlimit to get the maximum stack size.
getrlimit(RLIMIT_STACK, &stack); // TODO only run this once.
char* stack_end = stack_start - stack.rlim_cur; // Work out where the end of the stack is.
return !((char*)var < stack_start && (char*)var > stack_end) // Return whether the variable is on the heap.
}
int main()
{
char a = 0;
int b = 42;
static int c = 42;
printf("is_static(b) returns %i\n", is_static(&b, &a));
printf("is_static(c) returns %i\n", is_static(&c, &a));
}
我们 运行 代码并得到这个:
is_static(b) returns 0
is_static(c) returns 1
编辑:如果您不想使用 getrlimit()
,那么您可以使用 __builtin_return_address()
来确定最高堆栈值。
好的,事实证明我之前的答案对静态全局变量不起作用,所以我设计了这个程序来检查全局变量是否声明为静态。它的工作方式是 dysym() 在符号 table 中找不到静态全局变量,所以我只检查它的输出。它还使用布尔值引用变量,以确保它确实存在。
#include <stdio.h>
#include <dlfcn.h>
char* a = "hello, world";
static char* b = "hello, world";
#define is_static(name) \
(is_sym_static(#name) && &name)
_Bool is_sym_static(const char* const name)
{
void* hdl = dlopen(NULL, 0); // TODO: optimise by only calling this once.
return dlsym(hdl, name) == NULL;
}
int main(int argc, char** argv)
{
printf("%i\n", is_static(a)); // prints 0
printf("%i\n", is_static(b)); // prints 1
}
这必须用 -ldl -Wl,--export-dynamic
编译,以确保所有变量都以符号 table 结尾。这不适用于局部变量,但我们可以将其与我之前的答案结合起来......
#include <stdio.h>
#include <dlfcn.h>
#include <sys/resource.h>
static char* stack_start;
#define is_static(name) \
(is_addr_static(&name) && is_sym_static(#name) && &name)
_Bool is_sym_static(const char* const name)
{
void* hdl = dlopen(NULL, 0); // TODO: optimise by only calling this once.
return dlsym(hdl, name) == NULL;
}
_Bool is_addr_static(void* var)
{
struct rlimit stack;
getrlimit(RLIMIT_STACK, &stack); // TODO: optimise by only calling this once.
char* stack_end = stack_start - stack.rlim_cur;
return !((char*)var < stack_start && (char*)var > stack_end);
}
char* a = "hello, world";
static char* b = "hello, world";
int main(int argc, char** argv)
{
char _;
stack_start = &_;
char* c = "hello, world";
static char* d = "hello, world";
printf("%i\n", is_static(a)); // prints 0
printf("%i\n", is_static(b)); // prints 1
printf("%i\n", is_static(c)); // prints 0
printf("%i\n", is_static(d)); // prints 1
}
现在可以检测全局和局部静态变量。然而,我认为没有理由需要这个,因为局部静态和全局静态是根本不同的东西。
是否有可能以某种方式在编译时或 运行 时检查变量是否具有 static
存储-class 说明符?
示例:
static int v1;
int v2;
bool r1 = is_static(v1); /* true */
bool r2 = is_static(v2); /* false */
免责声明:以下代码不符合标准、可移植,甚至不安全。请不要在生产中使用它。
我们可以通过检查变量是否在栈上来判断一个变量是否是静态的。 Out 函数 is_static()
有两个参数。第一个是指向我们要检查的变量的指针,第二个是指向堆栈开头的指针(这就是 a
的用途)。然后它使用 getrlimit() 来确定该堆栈末尾的位置并检查我们的变量是否在堆栈上。这应该适用于大多数类 unix 系统。
#include <stdio.h>
#include <sys/resource.h>
_Bool is_static(void* var, char* stack_start)
{
struct rlimit stack; // Use getrlimit to get the maximum stack size.
getrlimit(RLIMIT_STACK, &stack); // TODO only run this once.
char* stack_end = stack_start - stack.rlim_cur; // Work out where the end of the stack is.
return !((char*)var < stack_start && (char*)var > stack_end) // Return whether the variable is on the heap.
}
int main()
{
char a = 0;
int b = 42;
static int c = 42;
printf("is_static(b) returns %i\n", is_static(&b, &a));
printf("is_static(c) returns %i\n", is_static(&c, &a));
}
我们 运行 代码并得到这个:
is_static(b) returns 0
is_static(c) returns 1
编辑:如果您不想使用 getrlimit()
,那么您可以使用 __builtin_return_address()
来确定最高堆栈值。
好的,事实证明我之前的答案对静态全局变量不起作用,所以我设计了这个程序来检查全局变量是否声明为静态。它的工作方式是 dysym() 在符号 table 中找不到静态全局变量,所以我只检查它的输出。它还使用布尔值引用变量,以确保它确实存在。
#include <stdio.h>
#include <dlfcn.h>
char* a = "hello, world";
static char* b = "hello, world";
#define is_static(name) \
(is_sym_static(#name) && &name)
_Bool is_sym_static(const char* const name)
{
void* hdl = dlopen(NULL, 0); // TODO: optimise by only calling this once.
return dlsym(hdl, name) == NULL;
}
int main(int argc, char** argv)
{
printf("%i\n", is_static(a)); // prints 0
printf("%i\n", is_static(b)); // prints 1
}
这必须用 -ldl -Wl,--export-dynamic
编译,以确保所有变量都以符号 table 结尾。这不适用于局部变量,但我们可以将其与我之前的答案结合起来......
#include <stdio.h>
#include <dlfcn.h>
#include <sys/resource.h>
static char* stack_start;
#define is_static(name) \
(is_addr_static(&name) && is_sym_static(#name) && &name)
_Bool is_sym_static(const char* const name)
{
void* hdl = dlopen(NULL, 0); // TODO: optimise by only calling this once.
return dlsym(hdl, name) == NULL;
}
_Bool is_addr_static(void* var)
{
struct rlimit stack;
getrlimit(RLIMIT_STACK, &stack); // TODO: optimise by only calling this once.
char* stack_end = stack_start - stack.rlim_cur;
return !((char*)var < stack_start && (char*)var > stack_end);
}
char* a = "hello, world";
static char* b = "hello, world";
int main(int argc, char** argv)
{
char _;
stack_start = &_;
char* c = "hello, world";
static char* d = "hello, world";
printf("%i\n", is_static(a)); // prints 0
printf("%i\n", is_static(b)); // prints 1
printf("%i\n", is_static(c)); // prints 0
printf("%i\n", is_static(d)); // prints 1
}
现在可以检测全局和局部静态变量。然而,我认为没有理由需要这个,因为局部静态和全局静态是根本不同的东西。