Man*_*cob 6 c posix pointers language-lawyer c11
对int *a, int *b,是否a == b暗示(intptr_t)a == (intptr_t)b?我知道在现代X86 CPU上也是如此,但C标准或POSIX或任何其他标准是否能为此提供保证?
Eri*_*hil 10
C标准无法保证这一点.(这个答案没有说明POSIX或其他标准是否intptr_t有所说明.)C标准(2011年,草案N1570)所说的intptr_t是:
7.20.1.4 1以下类型指定一个带符号的整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将等于原始指针:intptr_t
作为理论证明,一个反例是具有24位地址的系统,其中高8位未使用,但可用的整数类型是8位,16位和32位.在这种情况下,C实现可以产生intptr_t一个32位整数,它可以intptr_t通过将24位地址复制到32位整数并忽略高8位来转换指针.这些比特可能会遗留在之前的任何东西上.当intptr_t值转换回指针时,编译器会丢弃高8位,从而产生原始地址.在该系统中,当a == b用于评估的指针a和b,编译器通过比较只有地址的24位实现此.因此,如果a和b指向同一个对象a == b将是真的,但(intptr_t) a == (intptr_t) b由于忽略的高位可能会评估为假.(需要注意的是,严格地说,a并且b应该是指针void或应转换为指针void被转换成前intptr_t.)
另一个例子是使用一些基址和偏移寻址的系统.在该系统中,指针可能由指定某个基址的16位和指定偏移的16位组成.基数可能是64字节的倍数,因此由base和offset表示的实际地址 是base •64 + offset.在此系统中,如果指针a具有基数2和偏移量10,则它表示b与具有基数1和偏移量74的指针相同的地址.比较指针时,编译器将评估每个指针的基数 •64 + 偏移量并比较结果,因此a == b评估为真.但是,在转换intptr_t为时,编译器可能只是复制这些位,从而产生131,082(2•65536 + 10)(intptr_t) a和65,610(1•65536 + 74)(intptr_t) b.然后(intptr_t) a == (intptr_t) b评估为false.但是将intptr_t返回转换为指针类型的规则会使原始指针仍然成立,因为编译器只会再次复制这些位.