首页 文章

C无效指针

提问于
浏览
3

我在想,为什么不能有一个不是指针的void数据类型?

当然,你可以通过拥有可以超越整个确定尺寸的东西

void4
void8
void32

然后只允许将一个void数据类型“强制转换”为另一个类,如果它的大小等于或小于类的大小 .

有什么东西我不知道,或者C委员会只是认为这是不好的做法?

编辑:

我没有很好地解释自己,所以我将举例说明它的用法:

main()
{
    /* 

     Lets make a list of unknown elements

     std::string is 8 bytes, and float is 4
     bytes, so we'll reserve 8 byte sequences

     */

    vector<void8> elements;

    elements.push_back((void8) string("First string element"));

    elements.push_back((void8) float(5.76) );

    elements.push_back((void8) string("Third string element"));

    // Ect.

    cout << (string) elements[0];
    cout << (float) elements[1];
    cout << (string) elements[2];
    cout << (float) elements[2]; // Garbage


    void1 data;

    data = (void1) bool(1);
    data = (void1) unsigned int(80094); // Error, not enough size
}

它名为void,因为你不知道它当前存储的类型,类似于void指针 .

10 回答

  • 2

    在强类型语言中,所有数据都有一个类型,因此没有“void”概念作为数据类型 . 在C和C中,它的含义是“无数据”(作为返回值),或“您不知道的类型的数据”(作为指针目标) .

    您提出的中间状态为“您不知道但其大小与您相同的数据”,可能是您通过值传递的类型的不透明版本 . 除了相当危险之外(因为你必须在更改真实类型的大小时使用opaque类型手动更新所有代码),这可以在不添加语言的奇怪扩展的情况下完成,例如:

    struct void8 { char bytes[8]; };
    

    这可以与_1081334一起使用,将POD类型作为不透明的块传递,就像你建议的那样 . 与非POD类型一起使用它比使用 void* 引用非POD类型更有可能调用未定义的行为 .

    将opaque类型作为指针或对已声明但尚未定义的命名类型的引用处理是更安全和更惯用的,或者如果你想要值语义,则更像 boost::any . 很少需要在C中使用"void"作为占位符类型 .

  • 0

    它被称为boost :: variant或boost :: any . 它是允许的最大数据类型sizeof(指针)的大小,完全是类型安全的 .

  • 0

    什么是无效的?没什么,空虚 . Void32,哈哈! void用于指定不返回任何内容的函数 . 在其他语言中有关键字'procedure'或'sub' . 指向void的指针是指向未知的指针(void的第二种用法) . 这有两个目的无效 .

    更新:我认为,作者想要指定已知大小的未知类型 . void32 *是指向某个大小为32位的实体的指针,void8 *是指向8位实体的指针,依此类推 . 但它很容易用int32 *,char *模拟,没有语言扩展 .

  • 0

    您正在寻找的东西已经存在 . 它被称为 char . char 数组可用于存储未知对象,因为 char 基本上是C的一个字节的名称 . 因此,要将未知或可变类型的对象存储到单个数组中,可以使用字节数组,而不是任何数组,这将是 void .

    void 指针中的一点是我们不知道它指向的是什么 . 我们不知道它指向的对象的大小 . 因此,如果我们知道对象's size. The only thing we can do with an unknown object is to point to it. We can' t将它存储在任何地方,那么 void4 不会't make much sense. It',因为我们不知道它有多大或者它的对齐要求 . 所以我们当然不会将它存储到数组中 . 我们所能做的只是创建一个指向它的指针,我们已经有了 void 指针 .

    当然,这是一个有趣的小问题:

    这里的T型是什么?

    void foo(void* p) {
       T q = *p;
    }
    

    void4void32 ?或者只是 void ?物体有多大?我们对此了解多少?它是POD类型吗?

  • 0

    “void”数据类型的含义是什么?我不认为有一个有效的,所以这可能是它不存在的原因 .

  • 3

    拥有void数据类型会使事情变得更加复杂 . 而且如果它被称为void,那么数据类型会做什么 .

    我猜你指的是一个可能像虚空一样的数据类型,但你可能想要更改名称而不是将其称为无效 .

  • 2

    void* 不是无效的指针,如无效 . 它是指向虚空的指针,因为那里没有任何东西 .

    类型类型 void 本身由缺少值定义 . 其表示中没有位 . 它不能形成对象 .

    您所描述的内容可以进出 . 因此它包含信息 . 因此,它不是一个空虚的空洞 .

    你所描述的只是一个 int ,其中数值被忽略 . 但建议的用途是不好的做法 .

  • 8

    void 是"uninhabited"类型,表示没有类型 void 的可能值 . 既然有没有可能的值,它不需要空间来存储 void . 因此,大小 void 值将毫无意义 .

    退一步:C和C相当一致地认为 void 意思是"nothing" . 你可以有一个指向任何东西的指针,并使用它来携带一个指针周围的东西的值,但你不能取消引用它 - void 没有你可以做任何事情的 Value .

    还要注意 void -is-nothing会进入void指针的情况:虽然某些编译器(例如GNU)允许你对 void* 值进行指针运算,就好像它们是 char* 一样,标准禁止 void* 上的指针运算,因为 void 没什么,它没有任何有意义的大小 .

    所以,我认为答案是:这将毫无意义 . void 什么都没有,你不能在值中存储任何东西 .

  • 2

    我会假设你对存储的东西有更多了解,而不仅仅是它们的尺寸,否则我不相信存储这些东西有多大意义 .

    我想你可能想看看工会 . 联盟保留足够的空间来容纳联盟中最大的成员,然后根据您引用联盟的方式,选择“适当”的空间量并将其作为您请求的类型提供给您 .

    也就是说,就像将一组字符转换为您实际需要的任何类型一样,在使用此类功能之前,您应该仔细思考 .

  • 0

    如果有一个void数据类型,我认为它应该代表什么,只是吞下存储在其中的任何东西 .

    你可以说

    (void)func1();
    

    所以为什么不呢

    void x;
    x = func1();
    

    要么

    void func2() {
       void x;
       ...
       return x;
    }
    

    和作为函数参数

    int func3(int x, void y, char z);
    
    void x = func3(1,2);
    x = func3(1,x,2);
    

    在表达式中使用void是一个错误

    我可以在一些模板编码中看到这种用法 .

相关问题