在许多标准的开源代码中,我看到在不同的地方使用了不同的指针类型,例如:
uint32 fooHash (uint8 *str, uint32 len)
我没有得到以下内容: - 为什么要将 int 声明为 uint32、uint8?所有这些都将在用户空间本身中运行,那么为什么不直接保留为 uint 本身呢?以后便携性不是问题吗?
- 另外,如果你想在 32 位系统上运行开源代码,为什么要有一个指针为 uint8 *ptr?
指针的类型是指它包含的数据类型,而不是指针本身的大小。实际上所有指针的大小都是一样的。([*] 但请参阅下面的评论)
如果您有,则指针指向值uint8*
数组。uint8
这与 不同uint32*
,后者指的是uint32
值数组。
回答你问题的另一面......这些类型被明确表示的原因是因为并非所有编译器都同意int
. 这是一个便携的东西。
另外,如果你想在 32 位系统上运行开源代码,为什么要有一个指针为 uint8 *ptr?
uint8_t
是指针指向的东西的大小,而不是指针本身的大小;表达式 的类型*ptr
是uint8_t
。对象 的类型ptr
是uint8_t *
,它与系统需要的一样大(32 位、64 位等)。
在计算指针算术时,基本类型很重要。给定一个指针声明
T *p;
该表达式的p + i
计算结果为i
'类型after的第一个元素的地址。如果是,则给我们后面的第' 个整数的地址。如果是,则给我们以下第 'th 巨大结构的地址。例如:T
p
T
int
p + i
i
p
T
struct humongous
p + i
i
p
#include <stdio.h>
#include <stdint.h>
int main(void)
{
uint8_t *p0 = (uint8_t *) 0x00004000;
uint32_t *p1 = (uint32_t *) 0x00004000;
printf("p0 = %p, (p0 + 1) = %p\n", (void *) p0, (void *)(p0 + 1));
printf("p1 = %p, (p1 + 1) = %p\n", (void *) p1, (void *)(p1 + 1));
return 0;
}
产生输出
p0 = 0x4000, (p0 + 1) = 0x4001 p1 = 0x4000, (p1 + 1) = 0x4004
指针不必都具有相同的大小或具有相同的表示。例如,在哈佛架构中,指令和数据存储在不同的内存区域中,并且可能具有不同大小的总线,因此对象指针 ( int *
, char *
, float *
) 可能是一种大小(比如 8 位),而函数指针 ( int (*foo)(void)
) 可能是不同的大小(比如 16 位)。类似地,在字寻址架构上,achar *
可能比其他指针类型宽几位,以指定字的偏移量。
并非所有数据都应存储为signed int
. Auint8*
可用于多种用途:字符串、二进制数据(例如网络数据包或文件的一部分)。
有时您只需要 uint8 因为您要存储的值的范围位于[0,256[
.
不要忘记我们不是在讨论指针的类型,而是在讨论指向的数据的类型。指针是一个指针(根据体系结构将具有正确的大小),无论它指向什么类型。
这完全取决于您使用的硬件和编译器。
如果你只使用一个 int 你可以得到不同的大小。您还可以在 unix 和 windows 上获得不同的尺寸。
编译器所需的全部来自 C99 标准
sizeof(short) <= sizeof(int) <= sizeof(long) < sizeof(long long)
以下是 Windows 平台的 int 类型大小(位):
Type C99 Minimum Windows 32bit
char 8 8
short 16 16
int 16 32
long 32 32
long long 64 64
你应该看看
以下保证是它们命名的大小
int8_t
int16_t
int32_t
int64_t
int8_t