如何获取 C/C++ 变量的属性
How to get a C/C++ variable's property
如何获取变量的属性?
示例:
int a = 5;
....
....
isConstant(a); //Prints "no!" if 'a' is not a constant at this time.
isRegister(a); //Prints "yes!" if 'a' is a register at this time.important.
isVolatile(a); //Prints "trusted" if 'a' is volatile.
isLocal(a); //If it is temporary.
isStatic(a); //Static?
我只读过关于改变一个变量的常数的文章,但没有读过其他的。
我确信您可以为const
和volatile
使用模板元编程。IDK关于register
,我敢肯定你不能用于static
或局部范围的变量。
在C++11中,例如:
#include <iostream>
#include <type_traits>
int main()
{
std::cout << boolalpha;
std::cout << std::is_const<int>::value << 'n';
std::cout << std::is_const<const int>::value << 'n';
}
打印
false
true
还有std::is_volatile<>
主要是因为我想知道我是否可以:你可以通过一点内联汇编来查看某个东西是否在寄存器中。它两次请求相同的输入,一次在寄存器中,一次是在存储器或寄存器的任何位置。如果更改一个会同时更改两个,那么您将获得与两个输入相同的寄存器。
以下操作使用gcc在x86和x86_64上运行:
#include <iostream>
#define isRegister(x)
{
bool result;
asm("notl %1; /* alter always register one */
cmpl %2, %1; /* has the other changed? */
sete %0; /* save to result */
notl %1; /* restore */"
:"=&q"(result) /* out */
:"r"(x), "g"(x) /* in */
: /* no clobber */
);
std::cout << (result ? "Yes" : "No") << "n";
}
int main() {
register int a=666;
int b=667;
register int c = 0;
int d = 0;
isRegister(a);
isRegister(b);
isRegister(c);
isRegister(d);
std::cout << a << ", " << b << ", " << c << ", " << d << "n";
}
在这里使用内联asm会立即使其不可移植,并且您可能希望在实际代码中使用gcc的expr语句扩展,这再次使它不可移植并且是一个脆弱的破解。你需要小心——激进的优化可能会打破这种局面。这是一个很好的提示,你应该把这件事留给编译器,而不是担心寄存器中有没有什么,实际使用这段代码可能会改变答案,因为它本身可能会占用寄存器!
实际上,您可以确定变量是否在堆中动态分配。为此,您需要跟踪malloc()
、new()
/new[]
等返回的地址。然后,您可以检查变量的地址是否属于当前分配的内存块的任何范围。
您还可以确定变量是否为全局/静态变量。为此,您需要让程序自行解析(=解析其可执行文件)以找出相关数据段的起始和结束位置,或者指示编译器/链接器在数据段的开始和结束处创建全局变量。然后您可以查看变量的地址是否在这些变量之间的范围内。
对于const
、volatile
和register
修饰符,您可以按照其他人的建议使用一些C++"魔术"。
有一种相当简单的方法可以确定变量是在堆栈上(本地)还是在堆上(全局/静态/已分配)-基本上检查变量地址是否在堆栈顶部的变量和堆栈底部的变量之间。我还添加了一些测试代码。
#include <iostream>
#include <algorithm>
// we want asserts to work in release as well
#undef NDEBUG
#include <cassert>
//! Address of the first variable on the stack
void* g_stackStart;
//! return true if the address of variable is between g_stackStart and an address of the variable on the top of the stack
template <class T>
bool isLocal(const T& var)
{
void* stackEnd;
__asm
{
mov stackEnd, ESP
}
// what's the direction of stack?
if ( g_stackStart > stackEnd )
{
return &var < g_stackStart && &var >= stackEnd;
}
else
{
return &var >= g_stackStart && &var < stackEnd;
}
}
// test for nested variables
void nested(int arg)
{
int local = int();
assert( isLocal(local) );
assert( isLocal(arg) );
}
// global variable used for testing
int global;
int main()
{
// global stack begin pointer must be set here
__asm
{
mov g_stackStart, EBP
}
int onStack = int();
int* onHeap = new int();
std::pair<int, int> pair(0, 0);
assert( isLocal(onStack) );
assert( !isLocal(*onHeap) );
assert( isLocal(onHeap) );
assert( !isLocal(global) );
assert( isLocal(pair) );
assert( isLocal(pair.first) );
assert( isLocal(pair.second) );
nested(0);
delete onHeap;
return 0;
}
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- Cpp-Tuple使用带有变量的get
- 将包含C样式数组的对象初始化为成员变量(C++)
- 当vector是tje全局变量时,c++中vector的内存管理
- 通过多个头文件使用常量变量
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 执行函数时导致崩溃的变量
- 变量没有改变?通过向量的函数调用