Зачем бросать short в void *, получая предупреждение, а от int все в порядке? - PullRequest
1 голос
/ 18 августа 2010

Видите, я использую glib, а gpointer - это typedef из void *.(glib сделал этот тип, чтобы прояснить ситуацию, я полагаю).

когда я подключаю сигнал, я должен передать данные как указатель void (void *).

, поэтому кодis (что-то вроде этого):

...
g_signal_connect (object, function, (gpointer) data);
...

Если я использую short в качестве типа данных, я получаю предупреждающее сообщение gcc вроде этого:

warning: приведение к указателю из целогоразного размера

Если я использую int в качестве типа данных, я не получаю предупреждений.

Но в обоих случаях все работает хорошо, так почему я получаю это предупреждение, используя short?

Ответы [ 4 ]

2 голосов
/ 18 августа 2010

Gcc говорит вам, что вы приводите целое число разного размера к указателю, что опасно в основном другим способом (например, от большего типа данных к меньшему). Чтобы отключить предупреждение, вы можете использовать intptr_t в качестве промежуточного типа.

g_signal_connect (object, function, (gpointer)(intptr_t) data);
2 голосов
/ 18 августа 2010

В 32-битной архитектуре указатель составляет 32 бита. Значение int равно , обычно 32 бита, поэтому преобразование равно 1: 1. Короткое замыкание обычно составляет 2 байта, поэтому приведение короткого замыкания к указателю обычно не очень безопасно, поэтому компилятор предупреждает вас.

1 голос
/ 18 августа 2010

Сокращение составляет 2 байта, указатель зависит от платформы, но обычно 4 или 8 байтов. Вот почему вы получаете эту ошибку. Вы, вероятно, хотите передать ссылку на короткую позицию, в которой будет:

(gpointer) &data);
0 голосов
/ 08 декабря 2014

Преобразование целого в указатель зависит от реализации в C. Из стандарта ISO:

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

В качестве короткого (т. Е.Сокращение со знаком) обычно составляет 16 битов, а указатель void * обычно составляет 32 бита на 32-битных архитектурах или 64 бита на 64-битных архитектурах, GCC должен решить, как дополнить дополнительные биты.Что на самом деле делает GCC - это расширение знака коротким, т. Е. Копирование 14-битного 0 в биты 14-битного 0 указателя и копирование 15-го короткого в оставшиеся старшие биты (биты 31-15 из 32-битовый указатель, или биты 63-15 64-разрядного указателя.) Расширение знака сохраняет значение, если указатель позднее преобразуется обратно в целочисленный тип различной ширины.

short s = -1; // i.e. -> 0xffff
void *p = (void *)s; // on 32 bit system -> 0xffffffff

Если знак-расширение не то, что вы хотели, возможно, вы просто хотели получить прямую копию короткого замыкания в биты 15-0 указателя.В этом случае вы бы сделали что-то вроде этого:

short s = -1; // i.e. -> 0xffff
void *p = (void *)((unsigned short)s); // on 32 bit system -> 0x0000ffff
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...