当 int 和 long 相同时指针不兼容?
Incompatible pointer when int and long are the same?
在为 int 和 long 均为 32 位且 long long 为 64 位的平台(如 clang 或 gcc -m32
或 clang 的 wasm32-unknown-wasi 目标)编译 C 时,我收到关于不兼容的指针类型:
int32_t *i1 = NULL;
long *l1 = i1;
int64_t *i2 = NULL;
long *l2 = i2;
sizeof.c:13:11: warning: incompatible pointer types initializing 'long *' with an expression of type 'int32_t *' (aka 'int *') [-Wincompatible-pointer-types]
long *l1 = i1;
^ ~~
sizeof.c:15:11: warning: incompatible pointer types initializing 'long *' with an expression of type 'int64_t *' (aka 'long long *') [-Wincompatible-pointer-types]
long *l2 = i2;
^ ~~
2 warnings generated.
我觉得很奇怪,int32_t
和int64_t
都不兼容long
。
为什么int和long相同会有警告?
C 关于什么使类型兼容的规则部分是关于类型的“含义”,而不仅仅是它有多大,它代表什么值,或者它如何代表它们。在这些规则中,指向 int
和 long
的指针是不同且不兼容的类型,即使它们使用相同的字节数并以相同的方式编码地址并指向 int
和 long
使用相同的字节数并以相同的方式编码数字。
C 标准可能允许 C 实现定义(由 typedef
)int32_t
和 int64_t
为 int
、long
或 long long
,视情况而定。在这种情况下,相应的类型不仅兼容而且相同。然而,该标准还允许将它们定义为扩展类型,与基本整数类型不同,即使它们的功能相同。正如 chqrlie 指出的那样,您的 C 实现可能将 int32_t
定义为 int
并将 int64_t
定义为 long long
,因此两者都不兼容 long
.
类型的“含义”涉及一些关于人类计划将类型用于什么以及它对编译器意味着什么的事情。 int
最初意味着在某种意义上适合目标处理器的尺寸,但随着时间的推移已经减弱。可以使用相同的元素定义两种结构类型,但一种包含二维图形的 x-y 坐标,另一种包含复数的实部-虚部。让它们成为独立且不兼容的类型有助于程序员避免一些错误。
总的来说,int32_t x; int *p = &x;
之类的代码是错误编写的,需要一个警告来指出这一点。并且警告不是障碍,因为很容易编写按预期运行的代码而不会收到警告。
long *
与 int32_t *
和 int64_t *
都不兼容的原因是这些类型在您的平台上是这样定义的:
typedef int int32_t;
typedef long long int int64_t;`
标准类型 int
、longand
long long` 是不同的,即使它们具有相同的大小 and/or 表示。
C 标准中没有任何内容要求 int
、long
和 long long
应该用于指定大小的整数,前提是其中之一与其位数匹配和二进制补码表示要求。 int32_t
甚至可以定义为具有适当排名的单独扩展类型。
您必须在代码中使用正确的指针类型,并避免对基本整数类型的实际表示进行假设。
在为 int 和 long 均为 32 位且 long long 为 64 位的平台(如 clang 或 gcc -m32
或 clang 的 wasm32-unknown-wasi 目标)编译 C 时,我收到关于不兼容的指针类型:
int32_t *i1 = NULL;
long *l1 = i1;
int64_t *i2 = NULL;
long *l2 = i2;
sizeof.c:13:11: warning: incompatible pointer types initializing 'long *' with an expression of type 'int32_t *' (aka 'int *') [-Wincompatible-pointer-types]
long *l1 = i1;
^ ~~
sizeof.c:15:11: warning: incompatible pointer types initializing 'long *' with an expression of type 'int64_t *' (aka 'long long *') [-Wincompatible-pointer-types]
long *l2 = i2;
^ ~~
2 warnings generated.
我觉得很奇怪,int32_t
和int64_t
都不兼容long
。
为什么int和long相同会有警告?
C 关于什么使类型兼容的规则部分是关于类型的“含义”,而不仅仅是它有多大,它代表什么值,或者它如何代表它们。在这些规则中,指向 int
和 long
的指针是不同且不兼容的类型,即使它们使用相同的字节数并以相同的方式编码地址并指向 int
和 long
使用相同的字节数并以相同的方式编码数字。
C 标准可能允许 C 实现定义(由 typedef
)int32_t
和 int64_t
为 int
、long
或 long long
,视情况而定。在这种情况下,相应的类型不仅兼容而且相同。然而,该标准还允许将它们定义为扩展类型,与基本整数类型不同,即使它们的功能相同。正如 chqrlie 指出的那样,您的 C 实现可能将 int32_t
定义为 int
并将 int64_t
定义为 long long
,因此两者都不兼容 long
.
类型的“含义”涉及一些关于人类计划将类型用于什么以及它对编译器意味着什么的事情。 int
最初意味着在某种意义上适合目标处理器的尺寸,但随着时间的推移已经减弱。可以使用相同的元素定义两种结构类型,但一种包含二维图形的 x-y 坐标,另一种包含复数的实部-虚部。让它们成为独立且不兼容的类型有助于程序员避免一些错误。
总的来说,int32_t x; int *p = &x;
之类的代码是错误编写的,需要一个警告来指出这一点。并且警告不是障碍,因为很容易编写按预期运行的代码而不会收到警告。
long *
与 int32_t *
和 int64_t *
都不兼容的原因是这些类型在您的平台上是这样定义的:
typedef int int32_t;
typedef long long int int64_t;`
标准类型 int
、longand
long long` 是不同的,即使它们具有相同的大小 and/or 表示。
C 标准中没有任何内容要求 int
、long
和 long long
应该用于指定大小的整数,前提是其中之一与其位数匹配和二进制补码表示要求。 int32_t
甚至可以定义为具有适当排名的单独扩展类型。
您必须在代码中使用正确的指针类型,并避免对基本整数类型的实际表示进行假设。