C语言中声明指针和数组有区别吗?

问题描述 投票:0回答:1

我正在将旧的视频游戏模拟器移植到 Arduino MCU 环境。与此同时,我对 C 代码进行了大量重构,因为它需要一些清理和简化。

使用C语言,GCC从Debian 12交叉编译到Arduino Nano ESP-32(Espressif ESP32-S3 MCU)。使用 Visual Code,但我认为我的问题与操作系统或 IDE 无关。由于与某些 Arduino 环境库的兼容性,即使我的代码是纯 C,我实际上也使用 .cpp 扩展文件。

我使用一个简单的 uint8_t(又名 char)数组来存储游戏卡带 ROM 字节。它在头文件(.h)中以这种方式声明:

extern uint8_t rom[8192];

并在对应的.cpp中这样定义

#define ROM_SIZE 8192
uint8_t rom[ROM_SIZE] = {0x84, 0x00, 0x00, 0x84, 0x02...

到目前为止一切都很好,工作正常。

然后我决定尝试运行 16 kB 的程序。所以我需要对虚拟机代码进行一些小的修改,当然还要更改“rom”数组的大小并用更多字节填充它。由于我希望能够运行 8 或 16 kB ROM,我还更改了头文件以获得更大的灵活性:

extern uint8_t *rom;

以及对应的.cpp

#define ROM_SIZE 16384
uint8_t rom[ROM_SIZE] = { ...

现在我的程序仍然可以正常编译/链接,但执行时会使 ESP32 崩溃。它真的崩溃了:RGB LED 疯狂闪烁,没有更多可用的引导加载程序,我需要重置它才能再次访问它。看起来确实像是 SEG FAULT...

只需将头文件中的声明更改为:

extern uint8_t rom[];
一切都好。

所以,我的主要问题是:

将变量声明(不是定义:仅声明)为数组或指针有什么区别。在这两种情况下,我都不使用任何 malloc(),而是使用 C 代码中内容的静态定义:

#define ROM_SIZE 16384 uint8_t rom[ROM_SIZE] = { ...
我一直这么认为:

extern uint8_t *rom; extern uint8_t rom[];
我们也在做同样的事情。现在很明显,至少在这种特殊情况下并非如此,但我不明白为什么。

有什么线索吗?

arrays pointers gcc esp32 arduino-esp32
1个回答
0
投票
当编译器生成代码来访问声明的对象时,

声明数组和指向元素类型的指针时的差异就会发挥作用。

对于

uint8_t rom[]

,符号
rom
数组的地址,要访问元素,需要向rom
添加偏移量。

对于

uint8_t *rom

,符号
rom
是存储指针的地址。代码首先需要从
rom
加载地址,然后添加偏移量。换句话说,还涉及一种间接方式。这就是为什么声明与定义不匹配的代码很容易崩溃。
    

© www.soinside.com 2019 - 2024. All rights reserved.