繁体   English   中英

类型转换(char *)和(size_t)之间的区别

[英]Difference between type casting (char*) and (size_t)

我试图通过减法找到两个指针的区别,但一个是int * ,另一个是char * 结果,由于指针类型不兼容,它给了我一个错误,正如我所料。

int main() {  
   char * ca="test";
    int *ia=malloc(12);
    *ia=45;
    printf("add char * =%p, add int = %p \n", ca, ia);
    printf("add ca-va * =%p\n", ca-ia);
        return(0);
}

test3.c:22:35:错误:无效的二进制操作数-(具有'char *'和'int *')

但是,当我将cast int*键入size_t我成功地减去了地址。 有人可以解释一下size_t在这里做了什么吗?

int main() {  
   char * ca="test";
    int *ia=malloc(12);
    *ia=45;
    printf("add char * =%p, add int = %p \n", ca, ia);
    printf("add ca-va * =%p\n", (ca-(size_t)ia));

    return(0);
}

您在这里有2个问题:

两个指针值之间的差以指针指向的数据类型为单位进行计数。 如果您有两种不同的数据类型,则无法使用。

指针算术仅允许在同一数据对象中使用。 您只能减去指向同一数组或动态分配的内存块的指针。 在您的代码中情况并非如此。

减去不符合这些条件的指针无论如何都没有多大意义。

编译器抱怨是正确的。

这只是指针算法。

对于某些指针ptr和整数offsetptr - offset表示ptr之前的地址offset元素 请注意,这是元素 (无论指针指向什么),而不是字节。 您也可以在这里使用加法。 ptr[i]*(ptr + i)简写。

对于两个相同类型的指针(例如,两个char* ), ptr1 - ptr2表示两个指针之间的元素数 例如,如果ptr1 - ptr2 == 5 ,则ptr1 + 5 == ptr2

对于两个不同类型的指针(例如char*int* ), ptr1 - ptr2没有任何意义。

在您的第一段代码中,发生错误是因为您试图减去不同类型的指针。 第二段代码有效,因为您的强制转换导致它使用ptr - offset版本。 但这当然不是您真正想要的,因为指针已转换为偏移量并且结果是指针。

您可能想要的是Paul Hankin在评论中提到的内容:

intptr_t pc = (intptr_t)ca;
intptr_t pa = (intptr_t)ia;
printf("add ca-va = %" PRIdPTR "\n", pc - pa);

这会将指针转换为能够保存地址的整数类型,然后进行减法运算。 您将需要#include <inttypes.h>来获得PRIdPTRinttypes.h内部包括提供intptr_t stdint.h )。

size_t是整数类型。 将指针转换为整数类型时,结果是实现定义的(如果它可以适合目标类型;否则行为不是C标准定义的)。

根据C标准中的非规范性说明,“用于将指针转换为整数或将整数转换为指针的映射功能旨在与执行环境的寻址结构一致。”在具有简单内存地址方案的机器上,将指针转换为整数的结果通常是内存地址。 该答案的其余部分将假定我们具有这样的C实现。

因此,如果ca指向地址9678处的char数组,并且ia指向4444处的一些已分配内存,则将ia转换为size_t的结果将为4444。然后,当从ca减去4444时,我们不会减去两个指针而是从指针中减去一个整数。 通常,此行为不是C标准定义的,因为只允许在一个数组的边界内对指针进行加减运算,并且在此示例中4444远远超出了ca 但是,编译器可能要做的只是将整数转换为指向的元素的大小,然后从地址中减去结果。 由于cachar ,和的大小char是一个字节,变换4444 4444个的大小char元素仅仅是4444个字节。 那么9678-4444是5234,因此结果是一个指向地址5234的指针。

当您需要将指针转换为整数时,在<stdint.h>标头中定义了一种更好的类型uintptr_t (评论指出intptr_t ,但是除非有特殊原因要使用签名版本,否则应使用无符号版本。)然后,如果将两个指针都转换为uintptr_t ,例如(uintptr_t) ca - (uintptr_t) ia您将避免第一个指针可能指向大小不是一个字节的某种类型的问题。 然后,具有平坦内存地址空间的计算机上的结果通常是两个地址之间的差。

由于此处涉及实现定义和未定义的行为,因此您不能依靠它,并且在常规代码中不应以这种方式操作指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM