Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何检查C中的指针是否属于某种类型?_C_Gcc - Fatal编程技术网

如何检查C中的指针是否属于某种类型?

如何检查C中的指针是否属于某种类型?,c,gcc,C,Gcc,如何检查指针是否属于某种类型 使用sizeof是不够的 我试图避免将id号放入结构中以标识其类型。假设gcc可能会在流程中的某个位置放置一个结构定义,并将该定义映射到指针处分配的内存。如果这是真的,我想会有办法检查指针类型。你不能。 指针只存储地址,与地址内容无关。不,任何地方都没有运行时类型信息 您应该编写函数,以便函数签名携带类型信息,并让编译器静态检查类型。例如,void burp\u foo(struct foo*thefoo)告诉我们参数是指向struct foo的指针。由调用方提供一

如何检查指针是否属于某种类型

使用
sizeof
是不够的


我试图避免将id号放入结构中以标识其类型。假设gcc可能会在流程中的某个位置放置一个结构定义,并将该定义映射到指针处分配的内存。如果这是真的,我想会有办法检查指针类型。

你不能。


指针只存储地址,与地址内容无关。

不,任何地方都没有运行时类型信息


您应该编写函数,以便函数签名携带类型信息,并让编译器静态检查类型。例如,
void burp\u foo(struct foo*thefoo)
告诉我们参数是指向
struct foo
的指针。由调用方提供一个。当然,通过类型转换,可以提供任何指针指向“代码>结构FoO < /C>”,但这是调用方的问题,而不是您的问题。

< P>您不能在C中这样做。实际上,C++编译器执行了您想要的(将类的类型存储到分配的内存中的信息)。在C中没有类,只有结构,它不包含任何开销。

在C中没有类似的东西。指针要么是特定类型的,要么是void*。在C++中没有函数重载或内置运行时多态性。不过,您可以使用函数指针执行伪面向对象技巧,如:


typedef void (*cmd_func)( int );
struct command
{
    int      arg;
    cmd_func action;
};

指针是类型。更一般地说,C不提供内省功能。没有编程方法来确定变量的类型。

我试图避免将idnumbers放入结构中以识别其类型。不要避免这样做。如果您确实希望能够检查类型,请将typeID作为每个结构的第一个元素。您的冲动还不错。

Gcc不会将结构定义放在运行时的任何位置。这意味着您不能将其作为标准

它可能取决于您使用类型信息的目的。两个主要应用可能是:

  • 调试或类似的运行时检查
  • 数据结构的序列化和反序列化
  • 在第一种情况下,信息通常存储在编译器输出的符号中,并附加到可执行文件(在许多环境中)

    实现是特定于平台的,通常意味着需要指示编译器输出这些信息。gdb就是这样一个程序的例子。指针仍然必须正确键入才能使其有用


    对于序列化类型,通常使用您建议的值进行标记。这些标记不必和内存中的数据一起存储。它们可以由输出例程添加

    C标准不允许直接这样做。C++标准有一定的能力(<代码>动态> CAST < /COD>和<代码> Type ID>代码>
    typeof
    GCC附带了一个工具,根据您所做的工作,它可能会很有用

    条件运算符

    条件运算符(如:代码>X= y==0?1:0;)中的条件运算符和冒号(该文是关于C++的,但条件运算符的类型安全性在C中是相同的)。至少可以说,它的用途并不明显

    这两种技术(
    typeof
    和条件运算符)仅限于编译时可用的信息。也就是说,您不能将
    void*
    传递给函数,然后使用
    typeof
    计算指针指向该函数内部的对象的原始类型(因为在编译时该函数内部没有此类信息)


    关于这个问题,GTK+是用C编写的,你可以考虑仿真。看起来他们使用的是类型ID,但不是将ID放在结构中,而是使用宏进行查找。

    避免将ID成员放在结构中的一种方法是使用多态性,如:

    typedef struct {
            char const *name;
            int id;
            /* ... */
    } object_info_t;
    
    typedef struct {
            object_info_t *info;
    } object_t;
    
    typedef struct {
            object_t object;
            int a;
    } foo_t;
    
    typedef struct {
            object_t object;
            int b;
    } bar_t;
    
    int object_get_id(object_t *object)
    {
            return object->info->id;
    }
    
    注意:您可以使用函数指针扩充
    object\u info\t
    ,同时避免检查
    id
    s:

    typedef struct {
            char const *name;
            int id;
            int (*do_something)(object_t *);
    } object_info_t;
    
    int object_do_something(object_t *self)
    {
            return self->info->do_something(self);
    }
    

    所有贴在这里的答案都是“你不能”,他们是对的。你不能

    但是,我甚至不愿提及,有一些游戏可以玩。这些游戏是个坏主意。在任何情况下我都不推荐它们

    游戏是什么?在地址的未使用部分中填充多余的数据位,并在使用地址的任何地方将其剥离

    假设你有指向32字节大小的结构或类的指针。如果确保内存分配与32字节地址对齐(这对于动态分配来说很容易,但对于堆栈分配来说更难保证),那么地址的低位将全部为0。这意味着地址底部有5个空闲位,足以让您放置标志、ID号、状态值等。存储是空闲的! 即使你有一个奇特的结构大小,实际上任何C或C++编译器和OS都会将每个地址对齐到4个字节。 在64位中,您通常可以在地址的高端找到大量空闲位。。。很可能有16个空闲未使用的位,正在等待您。当然,这取决于操作系统。也是一个糟糕的坏主意。你喜欢危险,不是吗

    两个不利因素是:

  • 你必须确保掩盖真相 在你尝试之前,先把价值观拿出来 取消引用指针,或传递它 任何可能尝试的事情。这使得 丑陋的代码
  • 你跳着舞,跳出了舞台的边缘 愚蠢的不可移植性 危险。这就像喝了一杯酒 一瓶龙舌兰酒和一辆破旧的自行车 在饥饿的老虎身上走钢丝。裸体的
    (来源:)

    有太多的方式,这将爆炸成错误,崩溃,和痛苦。雷姆