外部声明,T * v / s T []

我在遗留项目中看到了下面的代码.
/* token.c */
struct token id_tokens[MAX_TOKENS];

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

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

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

我想要v2,因为T的指针与T的数组不一样.我的朋友的反对者认为两者的行为是一样的,所以我是否使用v1和v2并不重要.

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

问题2:我的朋友是否对这两个版本的行为保证是等同的?

解决方法

/* 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
 */

因此,在您的analyse.c中,将使用此声明生成以下说明.

  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.
 */

因此,将使用此声明生成以下说明:

  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

我们假设sizeof id_token [0]是2字节,sizeof指向id_token [0]的指针是4字节.

你以后的声明可能(误)插入id_tokens [0]& id_tokens [1]作为地址,并添加一些偏移量(可能是现有或不存在的地址,对齐或不对齐的地址谁知道).

如果这是您的美好日子,程序可能会立即崩溃或破坏,并有机会修复错误.如果这是糟糕的一天,程序可能会混乱一些其他内存,或者向一些模块传达错误的状态,这可能导致难以追踪错误并导致噩梦.

现在我想你明白为什么你在Mr. 32’s answer年(零)作为输出.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录<future>future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...