unsigned和signed int指针之间的区别

时间:2021-01-03 11:36:49

Is there anything such as an unsigned int* which is different from int*. I know that unsigned has a higher range of values. Still, can't int* even point to any unsigned int?

是否存在诸如unsigned int *之类的东西,它与int *不同。我知道unsigned有更高的值范围。仍然,int *甚至不能指向任何unsigned int?

6 个解决方案

#1


14  

int * and unsigned int * are two different pointer types that are not compatible types. They are also pointers to incompatible types. For the definition of compatible types, please refer to § 6.2.7 in the C Standard (C11).

int *和unsigned int *是两种不兼容类型的不同指针类型。它们也是不兼容类型的指针。有关兼容类型的定义,请参阅C标准(C11)中的第6.2.7节。

Being pointers to incompatible types means that for example that this:

指向不兼容类型的指针意味着例如:

unsigned int a = 42;

int *p = &a;  // &a is of type unsigned int *

is not valid (the constraints of the assignment operator are violated).

无效(违反赋值运算符的约束)。

Another difference between the two types is as for most other pointer types (although unlikely here) there is no guarantee from C they have the same size or the same representation.

两种类型之间的另一个区别是大多数其他指针类型(尽管这里不太可能),但是不能保证C具有相同的大小或相同的表示。

#2


13  

Using an unsigned pointer to point to a signed version of the same type is defined by C Standard.

使用无符号指针指向相同类型的签名版本由C Standard定义。

Therefore interpreting an int through an unsigned int pointer and vice-versa is valid.

因此,通过unsigned int指针解释int是相反的,反之亦然。

ISO/IEC 9899:201x 6.5 Expressions, p7:

ISO / IEC 9899:201x 6.5表达式,第7页:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 88)

对象的存储值只能由具有以下类型之一的左值表达式访问:88)

— a type that is the signed or unsigned type corresponding to the effective type of the object,

- 对应于对象的有效类型的有符号或无符号类型,

— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

- 对应于对象有效类型的限定版本的有符号或无符号类型,

88) The intent of this list is to specify those circumstances in which an object may or may not be aliased.

88)此列表的目的是指定对象可能或可能没有别名的情况。

Effective type is basically the type of the object:

有效类型基本上是对象的类型:

The effective type of an object for an access to its stored value is the declared type of the object, if any.

用于访问其存储值的对象的有效类型是对象的声明类型(如果有)。


An issue has been raised about the interpretation of the above rule. The following is my additional rationale about it.

对上述规则的解释提出了一个问题。以下是我的另外理由。

This text below is listed purely for semantic reasoning of the word: corresponding ,and not for the direct rules it specifies.

下面的文本纯粹用于单词的语义推理:对应,而不是它指定的直接规则。

6.2.5 Types

6.2.5类型

p6: For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword unsigned) that uses the same amount of storage (including sign information) and has the same alignment requirements.

p6:对于每个有符号整数类型,都有一个相应的(但不同的)无符号整数类型(用关键字unsigned指定),它使用相同的存储量(包括符号信息)并具有相同的对齐要求。

p9: The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the representation of the same value in each type is the same.41)

p9:有符号整数类型的非负值范围是相应无符号整数类型的子范围,每种类型中相同值的表示相同.41)

p12: For each floating type there is a corresponding real type, which is always a real floating type. For real floating types, it is the same type. For complex types, it is the type given by deleting the keyword _Complex from the type name.

p12:对于每个浮点类型,都有一个相应的实数类型,它总是一个真正的浮点类型。对于实际浮动类型,它是相同的类型。对于复杂类型,它是通过从类型名称中删除关键字_Complex而给出的类型。

p27: Further, there is the _Atomic qualifier. The presence of the _Atomic qualifier designates an atomic type. The size, representation, and alignment of an atomic type need not be the same as those of the corresponding unqualified type

p27:此外,还有_Atomic限定符。 _Atomic限定符的存在指定原子类型。原子类型的大小,表示和对齐不必与相应的非限定类型的大小,表示和对齐相同

6.2.6.2 Integer types

6.2.6.2整数类型

p2: For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; signed char shall not have any padding bits. There shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type

p2:对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位。不需要任何填充位; signed char不应有任何填充位。应该只有一个符号位。作为值位的每个位应具有与相应无符号类型的对象表示中的相同位相同的值

p5: The values of any padding bits are unspecified.54)A valid (non-trap) object representation of a signed integer type where the sign bit is zero is a valid object representation of the corresponding unsigned type, and shall represent the same value.

p5:未指定任何填充位的值.54)符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值。

(And many more examples with identical usage of the word corresponding )

(还有更多相同用法的例子)

As you can see in the above snippets, Standard uses the word corresponding to refer to different types or types with different specifiers and/or qualifiers. Therefore, as seen in the above examples Standard uses the word as would be used in this example: qualified type is corresponding to type.

正如您在上面的代码片段中所看到的,Standard使用相应的单词来指代具有不同说明符和/或限定符的不同类型或类型。因此,如上例所示,标准使用了本例中使用的单词:限定类型对应于类型。

It would be illogical to suddenly use the word corresponding for a different purpose: referring to completely identically qualified/specified types and even confuse the matters more by including the words signed and unsigned in the same sentence for no good reason.

突然使用相应的词用于不同的目的是不合逻辑的:提到完全相同的限定/指定的类型,甚至通过在同一句子中包括签名和未签名的单词而没有充分理由来混淆更多的事情。

The intention of the 6.5, p7 is: a type that is the signed or unsigned type either a signed or unsigned type corresponding to the effective type of the object that othervise matches( corresponds ) to the target type. So for example: effective type is: int, int or unsigned int correspond to that type.

6.5,p7的意图是:有符号或无符号类型的类型,有符号或无符号类型,对应于othervise与目标类型匹配(对应)的对象的有效类型。例如:有效类型是:int,int或unsigned int对应于该类型。

#3


10  

unsigned int * and int * are different types. To convert one to the other you must use a cast.

unsigned int *和int *是不同的类型。要将一个转换为另一个,您必须使用强制转换。

If you read a value through a pointer then it attempts to interpret the bits stored at that memory location as if they were bits for the type being pointed to by the pointer you are reading through.

如果通过指针读取值,则它会尝试解释存储在该存储器位置的位,就像它们是您正在读取的指针指向的类型的位一样。

If the bits at that memory location were not written by a pointer of the same type you are reading through, then this is called aliasing.

如果该内存位置的位不是由您正在读取的相同类型的指针写入,则称为别名。

The strict aliasing rule specifies which types may or may not be aliased; alasing between a type's signed and unsigned versions is always permitted.

严格别名规则指定哪些类型可能有别名,也可能没有别名;总是允许在类型的有符号和无符号版本之间进行删除。

However, if the bits are not a valid representation of a value in the type you are reading , then it causes undefined behaviour.

但是,如果这些位不是您正在读取的类型中值的有效表示,则会导致未定义的行为。

On modern systems there are no such "trap" representations so you have no issue. But let's say you were on a 1's complement system that trapped on negative zero:

在现代系统上,没有这样的“陷阱”表示,所以你没有问题。但是,假设你使用的是1的补充系统,它被置于负零点:

unsigned int x = 0xFFFFFFFF;
int *y = (int *)&x;
printf("%d\n", y);

The attempt to read y could cause a hardware fault or any other behaviour.

尝试读取y可能会导致硬件故障或任何其他行为。

#4


4  

The value of the pointer is the same, but they are different types. A difference will arise depending on the way you interpret the pointer - for eg: dereferencing.

指针的值是相同的,但它们是不同的类型。根据您解释指针的方式会产生差异 - 例如:解除引用。

unsigned int *u;
int *d;
unsigned int v = 2147483648; /* 2^31 */
u = &v;
d = (int*) &v;
printf("%u\n", *u);
printf("%d\n", *d);

will output:

将输出:

2147483648
-2147483648

The difference in the output arises because in printf("%d\n", *d), d is dereferenced and printed as if it points to a signed int, except it isn't. So you have to keep a distinction between the 2 types of pointers in your code.

输出的差异是因为在printf(“%d \ n”,* d)中,d被取消引用并打印,好像它指向一个有符号的int,除非它没有。所以你必须在代码中区分两种类型的指针。

#5


2  

It can point as both has the same size. The problem is this will introduce a hard to find bug, because you'll interpret a signed value as an unsigned or vice-versa.

它可以指向两者具有相同的大小。问题是这会引入一个难以发现的错误,因为您将签名值解释为无符号值,反之亦然。

#6


2  

A pointer is a number that is a memory address. So pointers have to have enough precision to be able to address all of memory for the implementation.

指针是一个作为内存地址的数字。因此,指针必须具有足够的精度才能为实现寻址所有内存。

Whether you reference a signed or unsigned int makes no difference in the internal structure of the pointer, because, in theory anyway, the int or unsigned int could be almost anywhere in memory. The datatype (unsigned) has to be declared to "help" the compiler decide correctness of the code.

无论你引用有符号还是无符号的int都没有区别于指针的内部结构,因为理论上无论如何,int或unsigned int几乎可以在内存中的任何位置。必须声明数据类型(unsigned)以“帮助”编译器决定代码的正确性。

#1


14  

int * and unsigned int * are two different pointer types that are not compatible types. They are also pointers to incompatible types. For the definition of compatible types, please refer to § 6.2.7 in the C Standard (C11).

int *和unsigned int *是两种不兼容类型的不同指针类型。它们也是不兼容类型的指针。有关兼容类型的定义,请参阅C标准(C11)中的第6.2.7节。

Being pointers to incompatible types means that for example that this:

指向不兼容类型的指针意味着例如:

unsigned int a = 42;

int *p = &a;  // &a is of type unsigned int *

is not valid (the constraints of the assignment operator are violated).

无效(违反赋值运算符的约束)。

Another difference between the two types is as for most other pointer types (although unlikely here) there is no guarantee from C they have the same size or the same representation.

两种类型之间的另一个区别是大多数其他指针类型(尽管这里不太可能),但是不能保证C具有相同的大小或相同的表示。

#2


13  

Using an unsigned pointer to point to a signed version of the same type is defined by C Standard.

使用无符号指针指向相同类型的签名版本由C Standard定义。

Therefore interpreting an int through an unsigned int pointer and vice-versa is valid.

因此,通过unsigned int指针解释int是相反的,反之亦然。

ISO/IEC 9899:201x 6.5 Expressions, p7:

ISO / IEC 9899:201x 6.5表达式,第7页:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 88)

对象的存储值只能由具有以下类型之一的左值表达式访问:88)

— a type that is the signed or unsigned type corresponding to the effective type of the object,

- 对应于对象的有效类型的有符号或无符号类型,

— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

- 对应于对象有效类型的限定版本的有符号或无符号类型,

88) The intent of this list is to specify those circumstances in which an object may or may not be aliased.

88)此列表的目的是指定对象可能或可能没有别名的情况。

Effective type is basically the type of the object:

有效类型基本上是对象的类型:

The effective type of an object for an access to its stored value is the declared type of the object, if any.

用于访问其存储值的对象的有效类型是对象的声明类型(如果有)。


An issue has been raised about the interpretation of the above rule. The following is my additional rationale about it.

对上述规则的解释提出了一个问题。以下是我的另外理由。

This text below is listed purely for semantic reasoning of the word: corresponding ,and not for the direct rules it specifies.

下面的文本纯粹用于单词的语义推理:对应,而不是它指定的直接规则。

6.2.5 Types

6.2.5类型

p6: For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword unsigned) that uses the same amount of storage (including sign information) and has the same alignment requirements.

p6:对于每个有符号整数类型,都有一个相应的(但不同的)无符号整数类型(用关键字unsigned指定),它使用相同的存储量(包括符号信息)并具有相同的对齐要求。

p9: The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the representation of the same value in each type is the same.41)

p9:有符号整数类型的非负值范围是相应无符号整数类型的子范围,每种类型中相同值的表示相同.41)

p12: For each floating type there is a corresponding real type, which is always a real floating type. For real floating types, it is the same type. For complex types, it is the type given by deleting the keyword _Complex from the type name.

p12:对于每个浮点类型,都有一个相应的实数类型,它总是一个真正的浮点类型。对于实际浮动类型,它是相同的类型。对于复杂类型,它是通过从类型名称中删除关键字_Complex而给出的类型。

p27: Further, there is the _Atomic qualifier. The presence of the _Atomic qualifier designates an atomic type. The size, representation, and alignment of an atomic type need not be the same as those of the corresponding unqualified type

p27:此外,还有_Atomic限定符。 _Atomic限定符的存在指定原子类型。原子类型的大小,表示和对齐不必与相应的非限定类型的大小,表示和对齐相同

6.2.6.2 Integer types

6.2.6.2整数类型

p2: For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; signed char shall not have any padding bits. There shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type

p2:对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位。不需要任何填充位; signed char不应有任何填充位。应该只有一个符号位。作为值位的每个位应具有与相应无符号类型的对象表示中的相同位相同的值

p5: The values of any padding bits are unspecified.54)A valid (non-trap) object representation of a signed integer type where the sign bit is zero is a valid object representation of the corresponding unsigned type, and shall represent the same value.

p5:未指定任何填充位的值.54)符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值。

(And many more examples with identical usage of the word corresponding )

(还有更多相同用法的例子)

As you can see in the above snippets, Standard uses the word corresponding to refer to different types or types with different specifiers and/or qualifiers. Therefore, as seen in the above examples Standard uses the word as would be used in this example: qualified type is corresponding to type.

正如您在上面的代码片段中所看到的,Standard使用相应的单词来指代具有不同说明符和/或限定符的不同类型或类型。因此,如上例所示,标准使用了本例中使用的单词:限定类型对应于类型。

It would be illogical to suddenly use the word corresponding for a different purpose: referring to completely identically qualified/specified types and even confuse the matters more by including the words signed and unsigned in the same sentence for no good reason.

突然使用相应的词用于不同的目的是不合逻辑的:提到完全相同的限定/指定的类型,甚至通过在同一句子中包括签名和未签名的单词而没有充分理由来混淆更多的事情。

The intention of the 6.5, p7 is: a type that is the signed or unsigned type either a signed or unsigned type corresponding to the effective type of the object that othervise matches( corresponds ) to the target type. So for example: effective type is: int, int or unsigned int correspond to that type.

6.5,p7的意图是:有符号或无符号类型的类型,有符号或无符号类型,对应于othervise与目标类型匹配(对应)的对象的有效类型。例如:有效类型是:int,int或unsigned int对应于该类型。

#3


10  

unsigned int * and int * are different types. To convert one to the other you must use a cast.

unsigned int *和int *是不同的类型。要将一个转换为另一个,您必须使用强制转换。

If you read a value through a pointer then it attempts to interpret the bits stored at that memory location as if they were bits for the type being pointed to by the pointer you are reading through.

如果通过指针读取值,则它会尝试解释存储在该存储器位置的位,就像它们是您正在读取的指针指向的类型的位一样。

If the bits at that memory location were not written by a pointer of the same type you are reading through, then this is called aliasing.

如果该内存位置的位不是由您正在读取的相同类型的指针写入,则称为别名。

The strict aliasing rule specifies which types may or may not be aliased; alasing between a type's signed and unsigned versions is always permitted.

严格别名规则指定哪些类型可能有别名,也可能没有别名;总是允许在类型的有符号和无符号版本之间进行删除。

However, if the bits are not a valid representation of a value in the type you are reading , then it causes undefined behaviour.

但是,如果这些位不是您正在读取的类型中值的有效表示,则会导致未定义的行为。

On modern systems there are no such "trap" representations so you have no issue. But let's say you were on a 1's complement system that trapped on negative zero:

在现代系统上,没有这样的“陷阱”表示,所以你没有问题。但是,假设你使用的是1的补充系统,它被置于负零点:

unsigned int x = 0xFFFFFFFF;
int *y = (int *)&x;
printf("%d\n", y);

The attempt to read y could cause a hardware fault or any other behaviour.

尝试读取y可能会导致硬件故障或任何其他行为。

#4


4  

The value of the pointer is the same, but they are different types. A difference will arise depending on the way you interpret the pointer - for eg: dereferencing.

指针的值是相同的,但它们是不同的类型。根据您解释指针的方式会产生差异 - 例如:解除引用。

unsigned int *u;
int *d;
unsigned int v = 2147483648; /* 2^31 */
u = &v;
d = (int*) &v;
printf("%u\n", *u);
printf("%d\n", *d);

will output:

将输出:

2147483648
-2147483648

The difference in the output arises because in printf("%d\n", *d), d is dereferenced and printed as if it points to a signed int, except it isn't. So you have to keep a distinction between the 2 types of pointers in your code.

输出的差异是因为在printf(“%d \ n”,* d)中,d被取消引用并打印,好像它指向一个有符号的int,除非它没有。所以你必须在代码中区分两种类型的指针。

#5


2  

It can point as both has the same size. The problem is this will introduce a hard to find bug, because you'll interpret a signed value as an unsigned or vice-versa.

它可以指向两者具有相同的大小。问题是这会引入一个难以发现的错误,因为您将签名值解释为无符号值,反之亦然。

#6


2  

A pointer is a number that is a memory address. So pointers have to have enough precision to be able to address all of memory for the implementation.

指针是一个作为内存地址的数字。因此,指针必须具有足够的精度才能为实现寻址所有内存。

Whether you reference a signed or unsigned int makes no difference in the internal structure of the pointer, because, in theory anyway, the int or unsigned int could be almost anywhere in memory. The datatype (unsigned) has to be declared to "help" the compiler decide correctness of the code.

无论你引用有符号还是无符号的int都没有区别于指针的内部结构,因为理论上无论如何,int或unsigned int几乎可以在内存中的任何位置。必须声明数据类型(unsigned)以“帮助”编译器决定代码的正确性。