为什么这些函数使用不同的指针和空指针?

Why are different pointers and void pointers being used by these functions?

我有一个 ATMega328,我正在使用 <avr/eeprom.h> 函数来使用内置的 EEPROM

我可以正确使用 EEPROM,但我不理解传递给 EEPROM 函数的函数参数。

例如,要写入不同类型的数据我可以使用

void eeprom_update_byte (uint8_t *addr, uint8_t value);
void eeprom_update_word (uint16_t *addr, uint16_t value);
void eeprom_update_dword (uint32_t *addr, uint32_t value);
void eeprom_update_float (float *addr, float value);

void eeprom_update_block (const void *src, void *dst, size_t n);

列出的前四个函数定义了正在写入的对象的类型。所以在内部函数可能是这样的:

void eeprom_update_float (float *addr, float value)
{
    *addr = value;
}

通过确保目标指针与源变量相同,这提供了类型安全优势(例如不能将 float 写入 uint16_t)。

最终版本void eeprom_update_block()简单地将任意内存块写入给定地址。它可能在下面使用了类似 memcpy 的东西:

void eeprom_update_block (const void *src, void *dst, size_t n)
{
    memcpy(dst, src, n);
}

此版本的函数没有任何类型安全优势,但可用于将重要数据写入内存。比如一个struct可以这样写:

eeprom_update_block(&myStruct, dst, sizeof(myStruct));

在前四个 API 中采用特定于类型的指针背后没有技术原因。这些函数可以用 void* 重新定义,而不需要重新编译依赖它们的代码:

void eeprom_update_byte (void *addr, uint8_t value);
void eeprom_update_word (void *addr, uint16_t value);
void eeprom_update_dword (void *addr, uint32_t value);
void eeprom_update_float (void *addr, float value);

EEPROM 中没有特殊的对齐要求,所以我猜测 Atmel 团队出于美观原因使用了特定类型的指针。

Also, the use of the void* in the EEPROM function below is confusing me.

eeprom_update_block 是类型特定 eeprom_update_XXX 函数的无类型版本。请注意,由于第二个参数是 void*,现在需要第三个指定块大小的参数,而 eeprom_update_XXX 函数从其参数类型中暗示大小。