我遇到了一些使用这两种代码的代码,看似可以互换。
我会举一个我很困惑的例子:
假设我在双向链表中有一些数据,我想更改一个块中的某些字符/地址。所以我们有:
void* ptr; //points to beginning of block
void* prevPtr; //prev item in LL
void* nextPtr; //next item in LL
*((char *)ptr) = prevPtr;
*(*(char **)(ptr) + sizeof(char*)) = nextPtr;
在这个例子中,底部的两行之间有什么区别(除了明显移动到内存中nextPtr
的位置)?
答案 0 :(得分:3)
*((char *)ptr) = prevPtr;
与:
char *temp = ptr;
*temp = prevPtr;
这是不正确的,因为您正在尝试指定一个字符指针。
*(*(char **)(ptr) + sizeof(char*)) = nextPtr;
与:
char **t1 = ptr;
char *t2 = *t1;
t2[4] = nextPtr; // assuming 4-byte pointers
这也是一个错误的形式,因为它指定了一个指向角色的指针。
在这两种情况下,您都应该收到有关此错误的编译器消息(不要被gcc误导,即使代码实际上是错误,也会对不兼容的类型转换发出“警告”)。
void *
是通用指针类型。它用于具有用于传输各种指针类型的接口的位置。但是,您只能将void *
转换回它来自的指针类型。任何其他指针转换都不能保证正常工作,如果转换为具有不同*
个数的指针类型,则特别可能无法执行预期的操作。
为了帮助您决定在代码中执行哪些操作,您必须首先查看ptr
的分配方式。
答案 1 :(得分:1)
在第一个中,ptr
被转换为指向char
然后prevPtr
的指针,而不是指向prevPtr
的指针,但指定了它存储的地址,到当前指向的字符类型的内存位置ptr
。在第二个中,ptr
被强制转换为指向char
的指针,然后在添加偏移量之前取消引用,这将导致nextPtr
的值(不是它指向的值)在ptr
指向的位置之后写入一个指针大小的偏移量,在您的示例中该位置仍应是一个字符。换句话说,您的示例代码没有意义,但希望我的详细说明有助于您理解。