为什么这些函数使用不同的指针和空指针?
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);
但为什么地址的指针类型(addr
参数)会根据使用的函数而改变?如果 addr
只是指向一个有效的 EEPROM
地址,为什么每个函数的类型不同?
此外,下面EEPROM
函数中void *
的使用让我很困惑。我知道 void *
可以指向任何地址,所以我假设该函数只是将数据逐字节写入 src
但我不确定这是否正确?
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
函数从其参数类型中暗示大小。
我有一个 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);
但为什么地址的指针类型(
addr
参数)会根据使用的函数而改变?如果addr
只是指向一个有效的EEPROM
地址,为什么每个函数的类型不同?此外,下面
EEPROM
函数中void *
的使用让我很困惑。我知道void *
可以指向任何地址,所以我假设该函数只是将数据逐字节写入src
但我不确定这是否正确?
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
函数从其参数类型中暗示大小。