可能是sizeof(T*)!= sizeof(const T*)的情况?

P45*_*ent 67 c++ language-lawyer

我正和我的老板争论这件事.他们说"是的,他们可以是不同的."

有可能是sizeof(T*) != sizeof(const T*)一种类型T

小智 81

不,他们不可能不同.对于足够不同的T1T2,sizeof(T1 *)可以从不同的sizeof(T2 *),但如果T2仅仅是const T1,则:

3.9.2复合类型[basic.compound]

3 [...]布局兼容类型的cv限定版和cv不合格版(3.9.3)的指针应具有相同的值表示和对齐要求(3.11).[...]

任何类型T都与自身布局兼容:

3.9类型[basic.types]

11如果两种类型的T1T2具有相同的类型,则T1T2布局兼容的类型.[...]


值表示与对象表示有关,如果没有相同的对象表示,则不能具有相同的值表示.后者意味着需要相同数量的比特.

3.9类型[basic.types]

4 类型对象的对象表示是由类型对象占据TN个 unsigned char对象的序列T,其中N等于sizeof(T).对象的值表示是保存type值的位集T.对于简单的可复制类型,值表示是对象表示中的一组位,用于确定,该是实现定义的值集的一个离散元素.44

44)意图是C++的内存模型与ISO/IEC 9899编程语言C的内存模型兼容.

的要求来看,它不只是说,两种类型具有相同的对象表示,其原因是T *const T *不仅有相同的位数,而且,它的同位T *const T *组成值.这意味着不仅要保证这一点sizeof(T *) == sizeof(const T *),而且这意味着即使您可以使用memcpyT *指针值复制到指针值,const T *反之亦然,并获得有意义的结果,您将获得完全相同的结果const_cast.

对齐要求也提供了一些额外的保证,但是它们很难解释并且与这个问题没有直接关系,并且标准中存在破坏某些预期保证的问题,因此我认为这里最好忽略.

  • 请注意,这只是标准.我使用了嵌入式目标的实际编译器,其中`T*`和`const T*`的大小不同(RAM指针和ROM指针). (33认同)
  • @ElderBug:注意标准要求你可以有一个`const T*`到RAM.因此,如果您需要不同的指令来访问ROM和RAM,您不能假设解除引用`const T*`等于使用ROM访问指令.这是C++的基础; 数百万的`int Foo :: getX const()`方法会破坏. (17认同)
  • 在PIC的情况下,你所拥有的是一个`rom const T*`,而不仅仅是一个`const T*`,所以这条规则不适用. (8认同)
  • @hvd我认为没有,但区分"T*"和"const T*"是一些小型嵌入式目标的正确选择.标准在这一点上确实存在缺陷,因为它假设可以使用相同的指针访问RAM和ROM.我记得的目标有不同的访问RAM(短16位指针)和ROM(长32位指针)的指令,因此编译器拒绝尝试在它们之间进行转换. (4认同)
  • @ElderBug虽然这绝对是有趣的信息,但该编译器是否声称符合任何标准? (3认同)
  • @ BlueRaja-DannyPflughoeft嗯,这是一个观点.我并不是真的不同意,但是很多人说Visual C++是一个C++编译器,甚至认为它是不符合要求的. (3认同)

Jos*_*hua 8

Microchip发布了这样一个C编译器,其中sizeof(T*)2 sizeof(const T*)是3 但是3.

C编译器在某些方面不符合标准,所以这没有说明这是有效的(我怀疑它不是和其他答案一致).

  • 这两个标准在这一点上都是一致的 (4认同)
  • 我很高兴怀疑C和C++在这里有不同的标准. (3认同)
  • 此外,这是一个C++问题 (2认同)

PkP*_*PkP 5

嗯,这是非常深奥的,但我认为理论上可能有一个架构,例如,在地址0中有256字节的RAM,比如在更高地址中有几千字节的ROM.并且可能有一个编译器会创建一个8位指针,int *i因为8位足以保存高度受限的RAM区域中的任何对象的地址,当然任何可变对象都隐含地知道在RAM区域中.类型的指针const int *i需要16位,以便它们可以指向地址空间中的任何位置.8位指针int *i可以转换为16位指针const int *i(但反之亦然),因此可以满足C标准的可铸性要求.

但如果存在这样的架构,我肯定希望看到它(但不是为它编写代码):)

  • 首先,这个问题是关于C++,而不是关于C.其次,C有同样的要求,我在答案中提到`T*`和`const T*`具有相同的表示,并将其短语为:"同样,指针合格或不合格版本的兼容类型应具有相同的表示和对齐要求." 您的假设实施违反了该要求. (4认同)
  • @Bathsheba我强烈怀疑,因为,是的,`sizeof(T*)`可以与`sizeof(S*)`不同,但`int`应该能够保存[-32767,+ 32767]中的所有值,需要至少16位.所以`int`不能长8位. (3认同)
  • 有很多哈佛架构,数据和代码空间不同,常​​量可以存储在只读代码空间中,因此可能有不同的指针大小 (2认同)