C 指针的大小在数据指针和函数指针之间会有所不同吗?

C 指针的大小在数据指针和函数指针之间会有所不同吗?,c,pointers,C,Pointers,我刚才在看报纸的那一节 它讨论了不能使用void*指针来保存函数指针,因为在某些平台上,指向数据的指针和指向函数的指针的大小可能不同,并且void*只能保证足够大以保存指向数据的指针 有谁能举一个平台的例子,其中指向数据的指针和指向函数的指针实际上有不同的大小?在实模式x86上,代码和数据是通过段+偏移量访问的,每个都是16位的量。“近”指针仅为16位并使用当前段,“远”指针为32位并指定段和偏移量。对于C编译器,有几种不同的内存模型可供选择,代码和数据的近指针或远指针的默认值不同 例如,“中等

我刚才在看报纸的那一节

它讨论了不能使用
void*
指针来保存函数指针,因为在某些平台上,指向数据的指针和指向函数的指针的大小可能不同,并且
void*
只能保证足够大以保存指向数据的指针


有谁能举一个平台的例子,其中指向数据的指针和指向函数的指针实际上有不同的大小?

在实模式x86上,代码和数据是通过段+偏移量访问的,每个都是16位的量。“近”指针仅为16位并使用当前段,“远”指针为32位并指定段和偏移量。对于C编译器,有几种不同的内存模型可供选择,代码和数据的近指针或远指针的默认值不同

例如,“中等”内存模型默认情况下对数据使用近指针,而对代码使用远指针

如果一些现代嵌入式处理器有类似的内存型号,我不会感到惊讶。

这是一种“视情况而定”的情况。在C++中,我记得成员函数指针实际上是两个指针,但这可能只是一个实现细节。

在一些真正老式的PC前系统中,指针的大小也可能取决于所引用的内容(但也可能有11位字符:D)

使用a的机器对指令和数据有单独的存储,相应地,对指令和数据有单独的地址空间。在这样的体系结构中,没有真正的理由让两个地址空间(或支持它们的物理内存)大小相同。

>type ppp.c
> type ppp.c
#include <stdio.h>
#include <stdlib.h>

int global = 0;

int main(void) {
    int local = 0;
    static int staticint = 0;
    int *mall;
    int (*fx)(void);

    fx = main;
    mall = malloc(42); /* assume it worked */
    printf("#sizeof pointer to local: %d\n", (int)sizeof &local);
    printf("#sizeof pointer to static: %d\n", (int)sizeof &staticint);
    printf("#sizeof pointer to malloc'd: %d\n", (int)sizeof mall);
    printf("#sizeof pointer to global: %d\n", (int)sizeof &global);
    printf("#sizeof pointer to main(): %d\n", (int)sizeof fx);
    free(mall);
    return 0;
}
> tcc -mc ppp.c
Turbo C  Version 2.01 ...
warnings about unused variables elided ...
Turbo Link  Version 2.0 ...
> ppp
#sizeof pointer to local: 4
#sizeof pointer to static: 4
#sizeof pointer to malloc'd: 4
#sizeof pointer to global: 4
#sizeof pointer to main(): 2
> tcc -mm ppp.c
> ppp
#sizeof pointer to local: 2
#sizeof pointer to static: 2
#sizeof pointer to malloc'd: 2
#sizeof pointer to global: 2
#sizeof pointer to main(): 4
#包括 #包括 int global=0; 内部主(空){ int local=0; static int static int=0; 国际购物中心; 国际货币(*fx)(无效); fx=主要; mall=malloc(42);/*假设它有效*/ printf(#sizeof指针指向本地:%d\n),(int)sizeof&local); printf(#sizeof指针指向静态:%d\n),(int)sizeof&staticint); printf(“#指向malloc'd的指针大小:%d\n”,(int)mall的大小); printf(#指向全局的sizeof指针:%d\n),(int)sizeof&global); printf(“#sizeof指针指向main():%d\n”,(int)sizeof fx); 免费(商场); 返回0; } >tcc-mc ppp.c Turbo C版本2.01。。。 关于未使用变量的警告已删除。。。 涡轮链接版本2.0。。。 >购买力平价 #指向本地的指针的大小:4 #指向静态的指针的大小:4 #指向malloc'd的指针的大小:4 #指向全局的指针的大小:4 #指向main()的指针的大小:2 >tcc-mm ppp.c >购买力平价 #指向本地的指针的大小:2 #指向静态的指针的大小:2 #指向malloc'd的指针的大小:2 #指向全局的指针的大小:2 #指向main()的指针的大小:4

tcc-mc
以“紧凑”模式生成代码
tcc-mm
以“中等”模式生成代码

16位PIC微控制器(微芯片PIC24和dsPIC)是具有不同数据和代码空间指针大小的哈佛体系结构设备的示例。不同的地址空间大小不同——片上SRAM的芯片面积成本比闪存大得多,因此数据指针可以更小


PIC12、PIC16和PIC18体系结构也是如此,但dsPIC正是我目前使用的。请注意,POSIX要求指向对象的指针和指向函数的指针大小相同:

2.12.3指针类型

所有函数指针类型应具有与指向void的类型指针相同的表示形式。将函数指针转换为void*不应改变表示形式。这种转换产生的void*值可以使用显式转换转换回原始函数指针类型,而不会丢失信息

注: ISO C标准不要求这一点,但要求符合POSIX标准


因此,声称符合POSIX的系统将是统一的。如果你只针对这样的机器,那么你就不必担心它们之间的差异。

复制品:@dmckee,IMO,不是复制品。@strager:不,原版更全面。但这一条不应该被删除,因为我怀疑它的标题更易于搜索,并且对POSIX
void*
返回有一些很好的回答,这正是我来到这里的原因:与其链接到维基百科,不如澄清为什么会出现这种情况。这是公平的;我认为维基百科的内容非常丰富,并且认为它本身就足够清晰,但理性的人可能会有所不同。虽然这是一个很好的指针(哈!),但哈佛体系结构并不需要指针大小的差异,地址空间的大小才是。您可以在一个地址空间中嵌入两个独立的物理内存,在这种情况下,您可能不需要区分void*s的大小和其他指针的大小。但我同意哈佛体系结构的机器很可能是一个开始寻找具有独立数据和函数指针的机器的地方。哦,它当然不要求它们具有不同的指针大小,它只是使其更有可能,并解释了为什么您可能期望一个标准来支持这些东西。我所看到的唯一的实际例子是(修改)哈佛体系结构,实际上不可能用少于2个机器字在C++中实现成员函数指针;原因是1)通过成员指针进行的调度必须是虚拟的,因此您不能只存储方法的地址;2)声明成员指针转发已声明的类是合法的,因此您不知道该类事先是否有任何虚拟方法。旧的DOS和早期的Windows环境就是这样,对于某些编译器。@Pavel-问题直接涉及函数指针和数据指针,而不是不同数据类型之间的问题。我假设这是在X86机器上?我认为是X86。。。我不确定。我在x86-64 Linux主机上的虚拟机中运行DOS。“Turbo C 2.01版”是最好的选择