当前位置: 首页 > 知识库问答 >
问题:

所有指针在C中的大小都一样吗?

姜志
2023-03-14

我知道了

所有指针具有相同的大小是很常见的,但是指针类型具有不同的大小在技术上是可能的。

但是后来我看到这个上面写着:

虽然指针的大小都一样,因为它们只存储一个内存地址,但我们必须知道它们指向的是什么类型的东西。

现在,我不确定哪一个是正确的。第二个引用的陈述看起来像是来自佛罗里达州立大学计算机科学的注释。

以下是我的想法:

  1. 说我们有:
int i = 0;
void* ptr = &i;

现在,假设C标准允许指针有不同的大小。进一步假设在某些任意机器/编译器上(因为标准允许),一个void*大小为2字节,而一个int*大小为4字节。

现在,我认为这里有一个问题,上面代码片段中所示语句的右侧有一个大小为4字节的int*,而左侧有一个大小为2字节的void*。因此,当隐式转换从int*void*发生时,会有一些信息丢失。

所以这是(IMO)所有指针应该具有相同大小的第一个原因。

利用以上两点,我认为第二句话是正确的。

我的第一个问题是C标准对此有何规定?

我的第二个问题是,如果C标准允许指针大小不同,那么这有什么原因吗?我的意思是,允许指针大小不同对我来说似乎有点不自然(考虑到我上面解释的两点)。所以,我很确定标准委员会一定已经考虑过(指针可以有不同的大小),并且已经有理由允许指针有不同的大小。请注意,只有当标准允许指针具有不同的大小时,我才会问这个问题(第二个问题)。

共有3个答案

濮冠宇
2023-03-14

一些规则:

>

  • 普通旧数据指针的大小可以不同,例如双*可以(并且经常)大于int*。(想想具有板外浮点单元的架构。)

    void*必须足够大,以容纳任何对象指针类型。

    任何非普通旧数据指针的大小都与其他指针相同。换句话说,sizeof(myclass*)==sizeof(yourclass*)

    sizeof(const T*)与任何Tsizeof(T*)相同;普通的旧数据或其他

    成员函数指针不是指针,指向非成员函数的指针,包括<代码>静态 成员函数,是指针。

  • 杨起运
    2023-03-14

    成员函数指针可以不同:

    void* ptr;
    
    size_t (std::string::*mptr)();
    
    std::cout << sizeof(ptr) << '\n';
    std::cout << sizeof(mptr) << std::endl;
    

    这是印刷的

    8
    16
    

    在我的系统上。背景是成员函数指针需要保存额外的信息,例如关于虚拟性等。

    从历史上看,有些系统上存在“近”和“远”指针,它们的大小也不同(16位对32位)——不过,据我所知,它们现在不再扮演任何角色了。

    巢靖
    2023-03-14

    虽然很容易得出结论,所有指针都是相同大小的,因为“指针只是地址,地址只是相同大小的数字”,但标准并不能保证这一点,因此不能依赖它。

    C标准明确保证:

    • void*的大小与char*([basic.component]/5)
    • T const*T volatile*T const volatile*的大小与T*相同。这是因为同一类型的cv限定版本与布局兼容,指向布局兼容类型的指针具有相同的值表示形式([basic.component]/3)
    • 类似地,具有相同基础类型的任何两个枚举类型都是布局兼容的([dcl.enum]/9),因此指向此类枚举类型的指针大小相同

    标准并不能保证,但在实践中,指向所有类类型的指针具有相同的大小,这基本上总是正确的。原因如下:指向不完整类类型的指针是完整类型,这意味着您有权询问编译器sizeof(T*),即使T是不完整类类型,并且如果在定义了T之后,在翻译单元中再次询问编译器sizeof(T*),结果必须相同。此外,在声明T的每一个其他翻译单元中,结果也必须相同,即使它从未在另一个翻译单元中完成。因此,编译器必须能够确定T*的大小,而不知道T里面有什么。从技术上讲,编译器仍然被允许玩一些把戏,比如说如果类名以特定前缀开头,那么编译器将假设您希望该类的实例受到垃圾回收机制的约束,并使指向它的指针比其他指针更长。在实践中,编译器似乎没有使用这种自由,你可以假设指向不同类类型的指针具有相同的大小。如果你依赖这个假设,你可以在你的程序中放一个static_assert,并说它不支持违反假设的病理平台。

    此外,在实践中,通常情况下

    • 任何两个函数指针类型具有相同的大小,
    • 任何两个指向数据成员类型的指针都具有相同的大小,并且
    • 任何两个指向函数成员类型的指针都具有相同的大小。

    这样做的原因是,对于上面列出的其他两个类别(expr.reinterpret.cast),您始终可以从一个函数指针类型到另一个函数指针类型,然后返回到原始类型,而不会丢失信息,依此类推。虽然编译器可以通过给它们提供不同的填充量使它们具有不同的大小,但没有实际的理由这样做。

    (然而,MSVC有一种模式,指向成员的指针不一定具有相同的大小。这不是因为填充量不同,而是违反了标准。因此,如果你在代码中依赖于此,你可能应该在

    如果您有一个分段的体系结构,带有近指针和远指针,那么您不应该期望它们具有相同的大小。这是上述规则的一个例外,即某些指针类型对通常具有相同的大小。

     类似资料:
    • 我知道了 所有指针具有相同的大小是很常见的,但是指针类型具有不同的大小在技术上是可能的。 但后来我发现了这样一句话: 虽然指针都是相同的大小,因为它们只存储一个内存地址,但我们必须知道它们指向什么样的东西。 现在,我不确定哪一个是正确的。第二个引用的陈述看起来像是来自佛罗里达州立大学计算机科学的注释。 以下是我的想法: 假设我们有: 现在,假设C标准允许指针有不同的大小。进一步假设在一些任意的机器

    • 我正在编写一个简单的函数,它返回数组中最大的整数。我遇到的问题是在数组中找到元素的数量。 下面是函数头: 我如何获得数组'list'中的整数数。 我试过以下几种方法: 任何帮助都将不胜感激!

    • 问题内容: 我是Java菜鸟。我已经掌握了将C / C ++指针转换为Java引用的概念,并且进展相当顺利。 我打了一段有指针的代码(即* ptr)。我需要取消引用指针并更改其指向的指针的值(即 ptr =&newthing;) 在Java中这似乎要困难得多。是否有人对如何解决此问题有任何想法?快速谷歌搜索什么都没有。 这是C ++中的代码示例。我想在Java中获得类似的工作,但是ptr_to_p

    • 如何精确地找到数组的大小?我读了geeksforgeeks的解释,仍然有点困惑。我想如果你取消引用(&arr+1),那么它会给你一个不存在的值,因为你跳过了前面的6个整数,这可能是内存地址中的任何随机值?而且,如果您能够取消对int类型的引用(&arr+1),那么您如何能够从中减去该值呢?

    • C++ 类 & 对象 在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。 友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。 下面的实例有助于更好地理解 this 指针的概念:#include <iostream> using namespace std; c

    • C++ 类 & 对象 一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。 下面的实例有助于更好地理解指向类的指针的概念: #include <iostream> using namespace std; class Box { public: