Я видел этот код в проекте.
b
Тип void*
:
void *b = ...;
int a = (int) (unsigned long) b;
Является ли эта линия бессмысленной? Я имею в виду, что это так же, как a = (int) b
во всех случаях?
Я видел этот код в проекте.
b
Тип void*
:
void *b = ...;
int a = (int) (unsigned long) b;
Является ли эта линия бессмысленной? Я имею в виду, что это так же, как a = (int) b
во всех случаях?
Это, вероятно, избегает предупреждения компилятора в 64-разрядных Unix-системах, где unsigned long
- это 64-разрядное количество и, следовательно, достаточно большое, чтобы удерживать указатель, но int
- это 32-разрядное количество, которое недостаточно велико для того, чтобы удерживайте указатель. Приведение в (unsigned long)
сохраняет все биты адреса; последующий листинг в int
выбрасывает 32-битные адреса высокого порядка, но делает это, не получая предупреждения по умолчанию.
Чтобы продемонстрировать:
int main(void)
{
void *b = (void *)0x12345678;
int a = (int)(unsigned long)b;
int c = (int)b;
return a + c;
}
$ gcc -O3 -g -std=c99 -Wall -Wextra -c ar.c
ar.c: In function ‘main’:
ar.c:5:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
$
Использование GCC 4.7.1 в Mac OS X 10.8.4, по умолчанию 64-битная компиляция.
Интересно спрогнозировать, что будет сделано со значением "части адреса".
Прямо typecasting для указателя на меньший тип say int может привести к ошибке компиляции некоторого компилятора (например, Clang) в среде x64 бит.
Например:
void *p = GetSomeAddress;
int i = (int)p; //error on compilers like Clang.
Решение:
int i = (int)(unsigned long)p;
или
int i = (int)(long)p;
Это связано с тем, что в Unix в модели LP64 длинная 64-разрядная версия.
В таких случаях вам нужно тщательно изучить, почему вам нужен метод typecast от указателя к int или другому меньшему типу, который может привести к потере данных.
Этот вопрос также может помочь вам. Как мне обрабатывать "cast from 'void * to' int loses precision" при компиляции 32-битного кода на 64-битной машине?
Я тоже вижу это в своем проекте.
В моем случае содержимое "b" заполняется другими источниками/промежуточным программным обеспечением, используемым для межпроцессного взаимодействия.
После заполнения "b" программа получит содержимое "b" с приведением в правильное поле "a". приложение затем использует "a" для обработки.
В моем проекте используется char * вместо void *.