指针的大小可以在数据和函数指针之间变化吗?

Rob*_*nes 21 c pointers

我刚刚阅读了关于指针C FAQ部分.

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

任何人都可以举一个平台的例子,其中指向数据的指针和指向函数的指针实际上有不同的大小?

pmg*_*pmg 10

> 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
Run Code Online (Sandbox Code Playgroud)

tcc -mc在"紧凑"模型中生成代码; tcc -mm在"中"模型中生成代码

  • ... x86 16位实模式 (4认同)
  • "Turbo C版本2.01"是赠品.大约1989年的古董编译器. (3认同)
  • exe文件的日期是1989-11-05 02:01 am - 这是一个很棒的编译器! (3认同)

Mic*_*ael 8

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

例如,"中"存储器模型在数据指针附近使用,但默认情况下用于代码的远指针.

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

  • @Pavel - 问题直接关系到函数指针和数据指针,而不是在不同的数据类型之间. (2认同)

Jon*_*ler 6

请注意,POSIX需要指向对象的指针和指向函数的指针大小相同:

2.12.3指针类型

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

注意:ISO C标准不要求这样,但它是POSIX一致性所必需的.

因此,声称符合POSIX标准的系统将是统一的.如果您只针对此类计算机,那么您不必担心这些差异.

  • 注意:截至2013-03-07,POSIX [数据类型](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_12)似乎缺少此部分,尽管它仍然是在[理由]中提到(http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html#tag_22_02_12_03).我要求OpenGroup澄清这是否是网站上的一个小故障或POSIX 2013与POSIX 2008相比的实质性变化.我不知道何时会收到答案. (5认同)
  • @Mitch:是的,我在2014年3月收到了回复.基本上,这是一个故意的变化,是对错误报告的回应.关于它的讨论可以在http://austingroupbugs.net/view.php?id=74上找到,其中引用的段落被删除,并且描述了`dlsym()`的修改措辞.有时候,我需要把它写得恰到好处 - 我已经意味着在一年中的大部分时间都这样做了(圆形的调整从未有过). (2认同)

Ste*_*non 5

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


Cli*_*ord 5

16位PIC单片机(Microchip PIC24和dsPIC)是具有不同数据和代码空间指针大小的哈佛架构器件的示例.单独的地址空间大小不同 - 片上SRAM的芯片面积成本比Flash存储器要大得多,因此数据指针可以更小.

PIC12,PIC16和PIC18架构也是如此,但dsPIC是我目前正在使用的.