【问题标题】:What is the point of pointer types in C++?C++ 中指针类型的意义何在?
【发布时间】:2008-12-19 09:07:22
【问题描述】:

假设我有一些指针叫做:

char * pChar;
int * pInt;

我知道它们都只是保存指向其他位置的内存地址,并且类型声明了特定指针指向的内存位置有多大。例如,一个 char 可能是系统上一个字节的大小,而一个 int 可能是 4 个字节。所以当我这样做时:

pChar++; // I am actually incrementing the address pointed to by pChar by 1 byte;
pInt++; // I am actually incrementing the address pointed to by pInt by 4 bytes;

但是如果我这样做呢:

pChar+2; // increment the address pointed to by pChar by 2 bytes?
pInt+2; // increment the address pointed to by pInt by 2 bytes? what happens to the other two bytes?

谢谢.. 如有任何澄清.. 指针类型是否仅用于 ++ 操作?

编辑:所以 avp 恰当地回答了我的问题,但我有一个后续问题,当我这样做时会发生什么:

memcpy(pChar,pInt,2);

它会复制 2 个字节吗?还是4个字节?我会有访问冲突吗?

编辑:根据 Ryan Fox 的说法,答案是 2 个字节,因为它们被强制转换为 (void*)。谢谢!关闭!

编辑:只是为了让未来的搜索者可以找到这个.. 我发现的另一条信息..

memcpy(pChar+5,pInt+5,2);

不会将 pInt+5bytelocations 指向的内存块的 2 个字节复制到 pChar+5bytelocations.. 发生的情况是 2 个字节从 pInt(4*5)bytelocations 复制到 pChar+5bytelocations.. 难怪我得到了访问违规,我试图在我不应该阅读的地方阅读.. :)

【问题讨论】:

  • 我不确定“typecasted”是正确的术语。我将 void* 视为其他指针类型的一种抽象父类。 void* 参数将接受任何指针,就像具有父类类型的参数将接受子类值一样。

标签: c++ pointers memcpy


【解决方案1】:

"++" 只是 X = X + 1 的别称;

对于指针,递增 1 或递增 N 无关紧要。 无论如何,使用 sizeof(type)*N。在 1 的情况下,它只是 sizeof(type)。

因此,当您增加 2 时(您的第二种情况):
对于 char 是 2*sizeof(char)=2*1=2 字节,
对于 int 将是 2*sizeof(int)=2*4=8 字节。

【讨论】:

  • 哦,我明白了.. 很好,我想这可能是我内存不足的地方哈哈.. 顺便说一句,如果我对指针进行类型转换会发生什么?使用什么尺寸?新的演员阵容?
  • 如果我 memcpy(pChar,pInt,2) 怎么办?发生什么了?会是从 pInt 的开头复制 2 个字节还是..?
  • memcpy 带 void* 参数,表示没有类型信息,所以是的,2 个字节。
【解决方案2】:

啊,现在我明白了。你应该问过 - “指针有类型有什么意义?”

其实有两点:

  • 指针算法;
  • 取消引用(取回存储在指针指向的地址中的值)。

如果不知道指针的类型,两者都是不可能的。

补充:阅读memcpy的文档。最后一个参数是字节数,因为 memcpy 不知道指针的类型是什么。它的两个参数都是空指针。

添加 2: 访问冲突 - 视情况而定。如果您没有超出为这些指针分配的内存,则不会发生访问冲突。复制操作将逐字节复制所有内容,您将获得与预期一样的结果(尽管它可能没有多大意义)。

如果您超出分配的内存范围,那么您可能会遇到访问冲突,但您也可能只是越过为另一个变量分配的内存。当你的程序执行时,几乎不可能知道什么会到达哪里,所以这样做会导致非常不可预测的结果。


指针的三个主要优点:

  1. 您可以“通过引用”将参数传递给函数。这在 C 中更多是一个问题,它没有像 C++ 这样的真正引用,但在许多情况下它仍然非常有用,比如当你必须与外部库合作时。另请注意,通过引用传递不仅在您希望函数修改您传递的变量时有用。它也非常适合将大型数据结构作为参数传递。
  2. 用于构建各种漂亮的动态数据结构,如树、链表等。如果没有指针,这将是不可能的。
  3. 因为能够根据需要将数组重新分配给更大/更小的数组。

附:我知道问题是关于为什么指针很好,仅以算术为例,对吧?

【讨论】:

  • 不是真的,我认为事情就像我的第二个例子一样,显然,不是..所以我想我需要重新表述这个问题..
  • 顺便说一句,哪个 C++ 编译器实现了“真实”引用?我的意思是,不是通过指针?
  • 有什么区别?
  • 顺便说一句,对不起,我想我误导了你,我的问题是“指针类型有什么意义”,而不是“指针有什么意义”..
  • 也很有帮助,但我认为 avp / Ryan Fox 已经总结了它...... :) +1 anwyay :)
【解决方案3】:

指针运算不能以这种方式精确工作。你的第一个例子是正确的,第二个不是。

pChar+2; // increment the address pointed to by pChar by 2 bytes
pInt+2; // increment the address pointed to by pInt by 8 bytes

【讨论】:

    【解决方案4】:

    对于这部分:

    memcpy(pChar+5,pInt+5,2);

    首先,评估“+”,然后进行类型转换。

    所以以字节为单位:

    pChar+5 这里“5”是5个字节,
    pInt+5 这里“5”是 5 个整数,所以 5 * 4 = 20 个字节。
    然后将所有内容都转换为 void* 并复制两个字节。

    如果你使用计数器而不是“5”,就像这里:

    for (int i = 0; i<100; i++)
        memcpy(pChar+i, pInt+i, 2);
    

    然后对于 pChar,您将使用下一个复制命令覆盖一个复制的字节(第二个)。而对于 pInt,您将每一步跳跃 4 个字节(尽管这对于整数数组来说是可以的)。

    【讨论】:

    • 是的,这正是我想要做的。但是我的问题是指针都指向完全相同大小的内存(比如说 100),但是 memcpy 都在增加不同方式的指针.. :) 我想这只是优先级问题.. :)
    【解决方案5】:

    我会说 C++ 中指针类型的意义在于考虑 vtable 偏移量。

    【讨论】:

    • 例如,dynamic_cast 可能返回与传入的地址不同的地址。类型化指针指向该类型的 vtable 条目。转换为 void* 将您指向 vtable 的开头,因此要比较两个抽象对象的标识,应该转换为 void* 以比较指针值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    相关资源
    最近更新 更多