是否有unsigned int*
与int*
不同的内容。我知道unsigned
具有更高的值范围。仍然,int*
甚至可以指向任何unsigned int
?
答案 0 :(得分:15)
int *
和unsigned int *
是两种不兼容类型的指针类型。它们也是不兼容类型的指针。有关兼容类型的定义,请参阅§ 6.2.7 in the C Standard (C11)。
指向不兼容类型的指针意味着例如:
unsigned int a = 42;
int *p = &a; // &a is of type unsigned int *
无效(违反了赋值运算符的约束)。
这两种类型之间的另一个区别是大多数其他指针类型(虽然这里不太可能)但是C不能保证它们具有相同的大小或相同的表示。
答案 1 :(得分:14)
使用无符号指针指向相同类型的签名版本由C Standard定义。
因此,通过unsigned int指针解释int,反之亦然。
ISO / IEC 9899:201x 6.5表达式,第7页:
对象的存储值只能由具有其中一个的左值表达式访问 以下类型: 88)
- 对应于有效类型的有符号或无符号类型 对象,
- 对应于合格版本的有符号或无符号类型的类型 有效的对象类型,
88)此列表的目的是指定对象可能存在或不存在别名的情况。
有效类型基本上是对象的类型:
访问其存储值的对象的有效类型是声明的类型 对象,如果有的话。
对上述规则的解释提出了一个问题。以下是我对此的补充理由。
下面的这个文本纯粹是为了单词的语义推理而列出的:相应的,而不是它指定的直接规则。
6.2.5类型
p6:对于每个有符号整数类型,有一个对应的(但不同)无符号 使用相同数量的整数类型(使用关键字unsigned指定) 存储(包括标志信息)并具有相同的对齐要求。
p9:有符号整数类型的非负值范围是。的子范围 对应的无符号整数类型,并在每个类型中表示相同的值 类型是相同的.41)
p12:对于每个浮动类型,都有一个对应的实型,它总是一个真正的浮动 类型。对于实际浮动类型,它是相同的类型。对于复杂类型,它是给定的类型 删除类型名称中的关键字_Complex。
p27:此外,还有_Atomic限定符。 _Atomic限定符的存在 指定原子类型。原子类型的大小,表示和对齐方式 不必与对应的非限定类型
的那些相同6.2.6.2整数类型
p2:对于有符号整数类型,对象表示的位应分为三个 groups:值位,填充位和符号位。不需要任何填充位; signed char不应有任何填充位。应该只有一个符号位。 作为值位的每个位应具有与对象中相同位相同的值 表示对应的无符号类型
p5:未指定任何填充位的值.5)有效(非陷阱)对象表示 符号位为零的有符号整数类型的有效对象表示 相应的无符号类型,并应表示相同的值。
(还有更多与对应词语相同使用的例子)
正如您在上面的代码片段中所看到的,标准使用对应的单词来指代具有不同说明符和/或限定符的不同类型或类型。因此,如上例所示,标准使用了本示例中使用的单词:限定类型对应于类型。
突然使用相应的词用于不同的目的是不合逻辑的:提到完全相同的合格/指定类型,甚至通过在同一句话中包含签名和未签名的词语而没有充分理由来混淆更多的事情。
6.5,p7的意图是:a type that is the signed or unsigned type
有符号或无符号类型corresponding to the effective type of the object
,其他与目标类型匹配(对应)。例如:有效类型是:int,int或unsigned int对应于该类型。
答案 2 :(得分:12)
unsigned int *
和int *
是不同的类型。要将一个转换为另一个,您必须使用强制转换。
如果通过指针读取值,则它会尝试解释存储在该存储器位置的位,就像它们是您正在读取的指针指向的类型的位一样。
如果该内存位置的位不是由您正在读取的相同类型的指针写入,则称为别名。
strict aliasing rule指定哪些类型可能有别名,也可能没有别名;总是允许在类型的signed
和unsigned
版本之间进行切换。
但是,如果这些位不是您正在读取的类型中值的有效表示,则会导致未定义的行为。
在现代系统中,没有这样的"陷阱"表示,所以你没有问题。但是,让我们说你是在1的补充系统中陷入负零点:
unsigned int x = 0xFFFFFFFF;
int *y = (int *)&x;
printf("%d\n", y);
尝试读取y
可能会导致硬件故障或任何其他行为。
答案 3 :(得分:4)
指针的值相同,但它们是不同的类型。根据您解释指针的方式会产生差异 - 例如:解除引用。
unsigned int *u;
int *d;
unsigned int v = 2147483648; /* 2^31 */
u = &v;
d = (int*) &v;
printf("%u\n", *u);
printf("%d\n", *d);
将输出:
2147483648
-2147483648
输出的差异是因为在printf("%d\n", *d)
中,d
被取消引用并打印,好像它指向signed int
,除非它不是。所以你必须在代码中区分两种类型的指针。
答案 4 :(得分:2)
它可以指向两者具有相同的大小。问题是这会引入一个难以发现的错误,因为您将签名值解释为无符号值,反之亦然。
答案 5 :(得分:2)
指针是一个作为内存地址的数字。因此,指针必须具有足够的精度才能满足实现的所有内存。
无论你引用signed还是unsigned int都没有区别于指针的内部结构,因为理论上无论如何,int或unsigned int几乎可以在内存中的任何位置。数据类型(unsigned)必须声明为" help"编译器决定代码的正确性。