【问题标题】:Are different pointers considered to be different data types?不同的指针是否被认为是不同的数据类型?
【发布时间】:2020-07-24 15:11:13
【问题描述】:

为了更好地理解指针,我想澄清一下。 不同的数据类型需要不同的指针,例如char*int*。是所有这些指针都被认为是不同的数据类型还是它们只是相同的数据类型?

【问题讨论】:

  • different types of the same data type 到底是什么?
  • @SouravGhosh 因为警告以不同的方式标记不同的指针(char* int* 等),我可能认为这类似于同一数据的不同类型,但当然我不太确定是什么我在说,否则我不会问
  • 尽量简明扼要地总结几个优秀的答案:“指针”不是数据类型,而是数据类型的类别。类型限定符和指向的数据类型的每种组合都代表了不同的指针类型。
  • 我已经纠正了,现在问题并没有说相同数据类型的不同类型,只是相同的数据类型
  • @JohnBollinger 好吧,如果 'pointer' 不是一种数据类型和一个类别,那么特定的单个指针本身是什么?该类别的元素是什么?

标签: c pointers types


【解决方案1】:

不同的指针是否被认为是不同的数据类型?

是的。

不同的数据类型需要不同的指针,例如char*int*。是所有这些指针都被认为是不同的数据类型,还是只是同一数据类型的不同类型?

都是指针,只是指向不同类型的对象时类型不同。

注意旁边的指针类型的区别;它们在内存中的大小也可以不同:

也没有像“相同数据类型的不同类型”这样的东西。要么类型不同,要么相同。

【讨论】:

  • 是的,这让我感到困惑:名称相同(指针),但类型不同。其他数据类型似乎没有这个问题
  • @Kaiyaha 指针始终与它们指向的对象的类型相关联。所以如果它们指向的对象的类型不同,它们(指针)就不同了。
【解决方案2】:

除非两种类型是“同一类型”,否则它们是不同的类型:

  • intlong 是不同的类型,即使它们对相同的事物使用完全相同的位数。我们知道这一点是因为 C 2018 6.3.1.1 告诉我们他们有不同的等级(关于促销和转换的规则中的层次结构)。
  • struct foo { int x; }struct bar { int x; } 是不同的类型,尽管它们对相同的事物使用完全相同的位数。
  • typedef 为现有类型定义了一个新名称;新名称不是不同的类型,只是同一类型的不同名称。
  • char *const char * 是不同的类型,int *long * 也是如此,即使 intlong 的大小相同。

除此之外,C 还具有“兼容”类型的概念。粗略地说,如果在某些情况下可以使用一种类型代替另一种类型,则两种类型是兼容的。例如,int [3](三个int 的数组)与int [](未指定数量的int 的数组)兼容,因为三个int 的数组可以满足未指定数组的要求int 的数量。填写大小就完成了int []

C 2018 6.7.6.1 告诉我们:

对于要兼容的两个指针类型,两者都应具有相同的限定,并且都应是指向兼容类型的指针。

由此我们可以看出,不仅两种不同的指针类型是不同的类型,而且有些指针类型与其他指针类型不兼容。关于兼容性的规则有些涉及,因为它们需要协调类型的各种灵活或不完整部分,例如没有完整参数列表的函数。

C 2018 6.3.2.3 告诉我们指针类型之间的转换,包括:

  • 指向对象类型的指针可以转换为 void * 并返回。
  • 指向非限定类型的指针可以转换为指向限定类型​​的指针(例如char *const char *)。
  • 如果指向对象类型的指针具有所需的对齐方式,则可以将其转换为指向另一种对象类型的指针。
  • 指向函数类型的指针可以转换为指向另一个函数类型的指针。

同样,仅定义了某些转换这一事实向我们表明,不同类型的指针是不同的,并且可能在根本上会阻止 C 实现在它们之间进行转换。

【讨论】:

    【解决方案3】:

    创建char * 时,它指向的内存区域将容纳char 大小的变量粒度。 int * 将指向可容纳int 大小粒度的内存区域。所以,虽然sizeof(int *) == sizeof(char *) (caveat) 他们有独特的不同属性。

    例如,当考虑为每个创建内存时会发生什么时,这一点变得很明显:

    char *buf = malloc(10);//reserves 10 memory locations, sizeof(char) 
                           //(always 1 byte) wide
    
    int *val = malloc(sizeof(*val)*10);// reserves 10 memory locations sizeof(int)
                                       // (typically 4 bytes wide for 32bit target) 
    

    请注意,在请求内存分配时,malloc 表达式中使用的字节数应始终是sizeoftype 的一个因素。

    这再次说明,尽管指针变量的大小相同(4 或 8 字节,取决于 32 位或 64 位寻址),但容纳每种类型的 10 元素所需的内存将是明显不同。

    【讨论】:

    • 过早发布? :)
    • @ryyker 好吧,您也对 malloc() 有了更好的理解!我曾经认为这个函数的参数是内存大小本身,而不是大小的数量。谢谢!
    • @RobertSsupportsMonicaCellio - 谢谢,你是对的!我添加了一个caveat 来解决这个问题。
    • @Kaiyaha 这不仅是因为您需要重新输入的内容更少。如果您忘记调整malloc() 调用,您将遇到严重麻烦,因为分配的内存与您认为分配给它的内存不匹配。当分配的内存太少时,此内存的读取或写入操作会调用未定义的行为。为防止这种情况发生,您为 ptr 指向的对象分配内存,并且您始终处于安全的一边。
    • @Kaiyaha - 例如,给定 int *var = malloc(some value of bytes); numberOfElements*sizeof(int)numberOfElements*sizeof(*var) 都可以通过。第二个是惯用的,主要是为了使代码维护更容易一些。即如果有人在以后的编辑中更改typemalloc function call would not have to be touched, i.e. *var` 将始终为*var,无论它是什么类型。
    【解决方案4】:

    是的,它们是不同的数据类型,因为它们指向不同类型的数据。

    换句话说,它们的用法和属性各不相同(例如:不同指针类型上的相同指针运算会产生不同的结果)并且它们具有不同的对齐要求。

    【讨论】:

    • 指向某个类型的指针(如 char**)和 char*** 等指针呢?所有这些也不同吗?我可以说指针类型的数量是无限的吗?
    • @Kaiyaha 是的,它们都是不同的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2023-04-09
    • 2020-08-16
    • 1970-01-01
    相关资源
    最近更新 更多