extern declaration, T* v/s T[]

眉间皱痕 提交于 2019-11-28 21:56:11
Mohit Jain
/* 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.

The first version is wrong. Arrays are NOT pointers, the declaration extern struct token *id_tokens; doesn't match the definition type struct token id_tokens[MAX_TOKENS];.

Reference: C FAQ: I had the definition char a[6] in one source file, and in another I declared extern char *a. Why didn't it work?. Also, see this.

lets understand same stuff by program

test.c

#include<stdio.h>
#include"head.h"
struct token id_tokens[10];
int main()
{
printf("In original file: %p",id_tokens);
testing();
}

head.h

struct token {
int temp;
};

test1.c with v1

#include<stdio.h>
#include"head.h"
extern struct token* id_tokens;
void testing () {
printf("In other file %p",id_tokens);
}

Output : In original file: 0x601040In other file (nil)


test1.c with v2

#include<stdio.h>
#include"head.h"
extern struct token id_tokens[];
void testing () {
printf("In other file %p",id_tokens);
}

Output : In original file: 0x601040In other file 0x601040


This clearly shows that v1 is not correct and v2 is correct.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!