Подтвердить что ты не робот

Разница между неподписанным и подписанным указателем int

Есть ли что-то вроде unsigned int*, которое отличается от int*. Я знаю, что unsigned имеет более высокий диапазон значений. Тем не менее, не может int* указывать на любой unsigned int?

4b9b3361

Ответ 1

int * и unsigned int * - два разных типа указателей, которые не являются совместимыми. Они также указывают на несовместимые типы. Для определения совместимых типов обратитесь к § 6.2.7 в стандарте C (C11).

Указание на несовместимые типы означает, что, например, это:

unsigned int a = 42;

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

недействителен (ограничения оператора присваивания нарушены).

Другая разница между этими двумя типами такова, как и для большинства других типов указателей (хотя это маловероятно), у C нет гарантии, что они имеют одинаковый размер или то же представление.

Ответ 2

Использование указателя unsigned для указания на подписанную версию того же типа определяется стандартом C.

Поэтому интерпретация int через unsigned int pointer и наоборот верна.

ISO/IEC 9899: 201x 6.5 Выражения, p7:

Объект должен иметь сохраненное значение, доступ к которому имеет только выражение lvalue, которое имеет один из следующие типы: 88)

- тип, который является подписанным или неподписанным типом, соответствующим эффективному типу Объект,

- тип, который является подписанным или неподписанным типом, соответствующим квалифицированной версии эффективный тип объекта,

88) Цель этого списка - указать те обстоятельства, при которых объект может или не может быть сглажен.

Эффективный тип - это в основном тип объекта:

Эффективным типом объекта для доступа к его сохраненному значению является объявленный тип объект, если он есть.


Возникла проблема интерпретации приведенного выше правила. Ниже приводится мое дополнительное обоснование.

Этот текст ниже указан исключительно для семантического рассуждения слова: соответствующего, а не для прямых правил, которые он определяет.

6.2.5 Типы

p6: для каждого из знаковых целочисленных типов существует соответствующая (но другая) неподписанная целочисленный тип (обозначенный ключевым словом unsigned), который использует такое же количество (включая информацию о знаках) и имеет те же требования к выравниванию.

p9: Диапазон неотрицательных значений знакового целочисленного типа является поддиапазоном соответствующий беззнаковый целочисленный тип и представление одного и того же значения в каждом тип тот же .41)

p12: для каждого плавающего типа существует соответствующий реальный тип, который всегда является реальным плавающим тип. Для реальных плавающих типов это тот же тип. Для сложных типов это тип удалив ключевое слово _Complex из имени типа.

p27: Кроме того, существует _Atomic квалификатор. Наличие спецификатора _Atomic обозначает атомный тип. Размер, представление и выравнивание атомного типа не обязательно должны быть такими же, как у соответствующего неквалифицированного типа

6.2.6.2 Целочисленные типы

p2: для знаковых целых типов биты представления объекта должны быть разделены на три группы: биты значений, биты заполнения и знаковый бит. Не должно быть никаких битов заполнения; подписанный char не должен иметь никаких битов заполнения. Должен быть ровно один знаковый бит. Каждый бит, который является битом значения, должен иметь то же значение, что и один бит в объекте представление соответствующего неподписанного типа

p5: Значения любых битов дополнений не определены .54) Действительное (нелокальное) представление объекта знакового целочисленного типа, где знаковый бит равен нулю, является действительным объектным представлением соответствующий неподписанный тип, и должен представлять одно и то же значение.

(И еще много примеров с одинаковым использованием соответствующего слова)

Как вы можете видеть в приведенных выше фрагментах, Standard использует слово, соответствующее другим типам или типам с разными спецификаторами и/или квалификаторами. Поэтому, как видно из приведенных выше примеров, стандарт использует слово, которое будет использоваться в этом примере: квалифицированный тип соответствует типу.

Было бы нелогично внезапно использовать слово, соответствующее другой цели: ссылаться на полностью идентично квалифицированные/заданные типы и даже путать вопросы больше, включив слова, подписанные и неподписанные в том же предложении, по уважительной причине.

Цель 6.5, p7: a type that is the signed or unsigned type либо подписанный, либо неподписанный тип corresponding to the effective type of the object, что othervise соответствует (соответствует) целевому типу. Например, эффективный тип: int, int или unsigned int соответствуют этому типу.

Ответ 3

unsigned int * и int * - разные типы. Чтобы преобразовать один в другой, вы должны использовать листинг.

Если вы читаете значение через указатель, он пытается интерпретировать биты, хранящиеся в этой ячейке памяти, как если бы они были битами для типа, на который указывает указатель, который вы просматриваете.

Если биты в этом месте памяти не были записаны указателем того же типа, который вы читаете, тогда это называется сглаживанием.

строгое правило псевдонимов указывает, какие типы могут быть или не быть псевдонимом; всегда допускается слияние между версиями типа signed и unsigned.

Однако, если бит не является допустимым представлением значения в типе, который вы читаете, он вызывает поведение undefined.

В современных системах таких "ловушек" не существует, поэтому у вас нет проблем. Но позвольте сказать, что вы были в системе с 1 дополнением, которая оказалась на отрицательном ноле:

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

Попытка прочитать y может привести к аппаратной ошибке или другим поведением.

Ответ 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, за исключением того, что это не так. Таким образом, вы должны вести различие между двумя типами указателей в вашем коде.

Ответ 5

Он может указывать, что оба имеют одинаковый размер. Проблема заключается в том, что вам будет трудно найти ошибку, потому что вы будете интерпретировать знаковое значение как unsigned или наоборот.

Ответ 6

Указатель - это номер, который является адресом памяти. Таким образом, указатели должны иметь достаточную точность, чтобы иметь возможность адресовать всю память для реализации.

Независимо от того, ссылаетесь ли вы на подписанный или unsigned int, нет никакой разницы во внутренней структуре указателя, потому что, в любом случае, int или unsigned int могут быть почти в любой точке памяти. Тип данных (без знака) должен быть объявлен "помогать", когда компилятор определяет правильность кода.