C 检查指针是否指向有效的结构
我有N个静态分配的结构C 检查指针是否指向有效的结构,c,pointers,struct,C,Pointers,Struct,我有N个静态分配的结构 struct exemple{ ... } struct exemple array[N]; struct exemple *test_ptr = 0x3; /* random address */ 我可以检查test_prt是否指向有效地址吗?i、 它指向分配的一个“结构示例”。您只能通过执行指针!=NULL因为除“NULL”之外的任何内容都由有效指针处理 在您的情况下,要检查指针是否指向任何数组项,只能执行以下操作: size_t i = 0; int
struct exemple{
...
}
struct exemple array[N];
struct exemple *test_ptr = 0x3; /* random address */
我可以检查test_prt是否指向有效地址吗?i、 它指向分配的一个“结构示例”。您只能通过执行
指针!=NULL
因为除“NULL”之外的任何内容都由有效指针处理
在您的情况下,要检查指针是否指向任何数组项,只能执行以下操作:
size_t i = 0;
int isValid = 0;
for (i = 0; i < N; i++) {
if (test_ptr == &array[i]) {
isValid = 1;
break;
}
}
if (isValid) {
//Pointer points to one of your array entry
}
你不能。你必须知道。如果正确管理指针,这不是问题。一个好习惯是在销毁指针指向的对象后,始终将指针设置为
0
/NULL
。然后您可以使用if(ptr)
或if(!ptr)
(或者更详细地说:if(ptr==NULL)
/if(ptr!=NULL)
)进行测试
请注意,您上次的作业
struct exemple *test_ptr = 0x3; /* random address */
无效。不能将整数指定给指针。但您可以将其转换为指针类型
struct exemple *test_ptr = (struct exemple *)0x3; /* random address */
结果将取决于您的实现/系统。没有语言方法,但在某些情况下,您可以尝试在结构的某些点上使用一些已知值。如果指向的内存位置具有这些值,您可以假定它是有效的,但您当然没有任何保证。但在创建结构和销毁结构时(在释放内存之前填充零),需要编写自己的函数。这是一个非常周密的解决方案,但是如果你使用其他的度量方法并接受开销,那么错误程序行为的概率就会降低 有时它被称为安全cookie
当然,这可能会使它变得更复杂——在某些位置,您只有对这些cookie的偏移量。内存中的随机位置不太可能有这样的数据链:)一般来说,不,您无法测试指针是否有效 但是,如果您想知道指针是否指向数组的元素,可以:
if(test_ptr >= &array[0] && test_ptr < &array[N]
&& ((intptr_t)test_ptr - (intptr_t)array)%((intptr_t)(&array[1]) - (intptr_t)array) == 0) {
// test_ptr points to an element of array
}
if(test_ptr>=&array[0]&&test_ptr<&array[N]
&&((intptr_t)test_ptr-(intptr_t)array)%((intptr_t)(&array[1])-(intptr_t)array)==0){
//test_ptr指向数组的一个元素
}
这是因为数组是连续分配的。我不知道我是否正确理解了您的问题 如果您想知道指针是否指向某种类型的结构(例如,将我的结构强制转换为
void*
,反之亦然),我将使用下一种方法:
#include <assert.h>
struct my_struct {
#ifndef NDEBUG
#define MY_STRUCT_MAGIC 0x1234abcd
uint64_t magic;
#endif
int my_data;
};
void init_struct(struct my_struct *s, int t_data) {
#ifdef MY_STRUCT_MAGIC
s->magic = MY_STRUCT_MAGIC;
#endif
s->my_data = t_data;
}
my_struct *my_struct_cast(void *vs) {
my_struct *s = vs;
#ifdef MY_STRUCT_MAGIC
assert(MY_STRUCT_MAGIC == s->magic);
#endif
return s;
}
#包括
结构我的结构{
#ifndef NDEBUG
#定义MY_STRUCT_MAGIC 0x1234abcd
uint64_t魔术;
#恩迪夫
int my_数据;
};
void init_struct(struct my_struct*s,int t_data){
#我的魔法
s->magic=MY_STRUCT_magic;
#恩迪夫
s->my_data=t_data;
}
我的结构*我的结构演员阵容(无效*vs){
我的结构*s=vs;
#我的魔法
断言(MY_STRUCT_MAGIC==s->MAGIC);
#恩迪夫
返回s;
}
因为包含了const casting,所以它的代码稍微多了一点,但我想你明白了
如果您想知道test_ptr是否指向一个aray成员,您必须这样检查:
test_ptr>=array&&test_ptr<&array[sizeof(array)/sizeof(array[0]))
。如果指针来自void、char或某种危险的ariyhmetic,您还可以检查test\u ptr%sizeof(数组[0])
如果您想知道指针是否指向程序“曾经分配”的有效内存,则必须截取allocs函数,保存返回的块指针和大小,并像前面的示例一样进行计算。我知道我可以进行数组检查,但我想知道是否有更直接的方法。thanks@alessiovolpe不幸的是,没有,这就是为什么C是控制语言:)对于大型数组来说,这是非常低效的。还有一种更直接的方法,@alessiovolpe@alain它效率很低,但除了检查指针是否为非空之外,根本没有其他方法来测试指针是否指向有效位置。即使指针是非空的,从它读取也是未定义的行为。@tilz0R通常是,但对于数组,请参阅我的答案;-)这在任何情况下都不行。如果你想要你的方法,你必须先减去:
((intptr\u t)test\u ptr-(intptr\u t)和array[0])%sizeof…
,最好是使用test\u ptr感谢你指出缺少的减法@tilz0R。但是不需要使用数组[N-1]
,因为可以指向超过数组末尾的一个,而不会导致UB。
#include <assert.h>
struct my_struct {
#ifndef NDEBUG
#define MY_STRUCT_MAGIC 0x1234abcd
uint64_t magic;
#endif
int my_data;
};
void init_struct(struct my_struct *s, int t_data) {
#ifdef MY_STRUCT_MAGIC
s->magic = MY_STRUCT_MAGIC;
#endif
s->my_data = t_data;
}
my_struct *my_struct_cast(void *vs) {
my_struct *s = vs;
#ifdef MY_STRUCT_MAGIC
assert(MY_STRUCT_MAGIC == s->magic);
#endif
return s;
}