外部声明,T * V / S T [] [英] extern declaration, T* v/s T[]

查看:194
本文介绍了外部声明,T * V / S T []的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到一个旧的项目下面的一段code的。

  / * * token.c /
结构令牌id_tokens [MAX_TOKENS]/ * analyse.c(V1)* /
EXTERN结构令牌* id_tokens;提出了我的眉毛/ *,id_token声明了一个指针* /

我坚持改变 analyse.c 包含如下声明:

  / * analyse.c(V2)* /
EXTERN结构令牌id_tokens []; / *我很高兴这一点。 id_tokens声明未指定大小的数组。 * /

我想 V2 ,因为指针至T 不一样的 T的数组。我朋友的柜台argumented都是相同的这种行为,所以它不会不管我使用v1和v2。

问题1:是否不完整的类型的数组消耗的指针

问题2:是我的朋友的权利,这两个版本行为上保证等同


解决方案

  / * * token.c /
结构令牌id_tokens [MAX_TOKENS]/ *
 id_tokens
  + ----- + ----- + ----- + ----- + ... + ----- +
  | | | | | | |
  + ----- + ----- + ----- + ----- + ... + ----- +
    [0] [1] [2] [3] ... [MAX_TOKEN-1]  要访问id_tokens [I],第i个元素添加偏移
  即I *的sizeof(结构令牌)的** **地址
  阵令牌
 * /

因此​​,在您 analyse.c ,将与这个声明会生成以下说明。


  

      
  1. 的extern结构令牌id_tokens [];
    id_tokens [I]
    一个。 id_tokens地址可能从其他编译单元链接
      取
    湾我的偏移量加到
    ℃。值引用

  2.   

  / * analyse.c(V1)* /
EXTERN结构令牌* id_tokens;/ *
 id_tokens
  + ------ + + ----- + ...
  |地址| ----------> | |
  + ------ + + ----- + ...
  要访问id_tokens [I],取** contetnts指针**
  令牌,加入第i个元素的偏移,即我的sizeof *(结构令牌)
  被添加到这一点。
 * /

因此​​,在您 analyse.c ,下面的说明将这一声明产生:


  <醇开始=2>
  
  • 的extern结构令牌* id_tokens;
    id_tokens [I]
    一个。从id_tokens地址的内容是从其他链接
      编译单元取。

       (会导致编译错误,如果因为类型不匹配的同一编译单元present)
    湾我的偏移量加到
    ℃。
      值引用

  •   

    假设sizeof的 id_token [0] 2 字节和sizeof指针 id_token [0] 4 字节。

    您稍后声明可(MIS)间$ P $私人的 id_tokens [0] &安培; id_tokens [1] 作为一个地址,并添加一些偏移到它(这可能是现有的或不存在的地址,对齐或不对齐谁知道地址)。

    如果这是你的好日子,程序可能会崩溃或立即段错误,你会得到一个机会来修正错误。如果这是你糟糕的一天,节目可能只是乱用一些其他的内存或传达错误的状态的一些模块,这可能会导致难以跟踪的错误,并导致了一场噩梦。


    现在我想你明白为什么你有(无)中的先生。 32的回答

    I saw following piece of code in a legacy project.

    /* token.c */
    struct token id_tokens[MAX_TOKENS];
    
    /* analyse.c (v1) */
    extern struct token *id_tokens; /* Raised my eyebrow, id_token declares a pointer */
    

    I insisted on changing analyse.c to contain the declaration as below:

    /* analyse.c (v2) */
    extern struct token id_tokens[]; /* I am happy with this. id_tokens declares array of unspecified size. */
    

    I want v2 because pointer to T is not same as array of T. My friend's counter argumented that behaviour of both are same, so it doesn't matter whether I use v1 and v2.

    Question 1: Does array of incomplete type deplete to a pointer?

    Question 2: Is my friend right that both versions are behaviorally guaranteed to be equivalent?

    解决方案

    /* token.c */
    struct token id_tokens[MAX_TOKENS];
    
    /*
     id_tokens
      +-----+-----+-----+-----+...+-----+
      |     |     |     |     |   |     |
      +-----+-----+-----+-----+...+-----+
        [0]   [1]   [2]   [3]  ...  [MAX_TOKEN-1]
    
      To access id_tokens[i], add offset of ith element
      i.e. i * sizeof(struct token) to the **address**
      of array token
     */
    

    So in your analyse.c, following instructions would be generated with this declaration.

    1. extern struct token id_tokens[];
      id_tokens[i]
      a. Address of id_tokens that might be linked from other compilation unit is taken
      b. offset of i is added
      c. Value is referenced

    /* analyse.c (v1) */
    extern struct token *id_tokens;
    
    /*
     id_tokens
      +------+           +-----+...
      | addr |---------->|     |
      +------+           +-----+...
    
    
      To access id_tokens[i], fetch **contetnts** of pointer
      token, add offset of ith element i.e. i * sizeof(struct token)
      is added to this.
     */
    

    So in your analyse.c, following instructions would be generated with this declaration:

    1. extern struct token *id_tokens;
      id_tokens[i]
      a. Contents from address of id_tokens that is linked from other compilation unit is taken.
      (Will result in compilation error if present in same compilation unit because of type mismatch)
      b. offset of i is added
      c. Value is referenced

    Let's assume sizeof id_token[0] is 2 byte and sizeof pointer to id_token[0] is 4 byte.

    Your later declaration may (mis)interprete the id_tokens[0] & id_tokens[1] as an address and add some offset to it (which may be an existing or non-existing address, aligned or non-aligned address who knows).

    If it is your good day, program may crash or segfault immediately and you get a chance to fix the bug. If it is your bad day, program may just mess up with some other memory or communicate a wrong state to some module which can result in difficult to track bug and cause a nightmare.


    Now I guess you understand why you got (nil) as output in Mr. 32's answer.

    这篇关于外部声明,T * V / S T []的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆