2016-04-10 4 views
1

Возможно ли прямое наведение-caste указатель на пустоту без проблем? Ниже приведен небольшой фрагмент кода, который я извлек из кода here (пример под Pthread Joining).Тип-литье пустота * до длинного

{ 
    void *status; 
    long t; 
    rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 
    rc = pthread_join(thread[t], &status); 
    printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status); 
} 

Как this manual page говорит, что pthread_join() копирует состояние выхода целевого потока (то есть, значение, которое целевой поток подается в pthread_exit()) в месте, на который указывает * RetVal (* состояние в этом дело). Но в программе, о которой я упоминал, статус не указывает на какое-либо местоположение. Тогда как же программа по-прежнему работает?

И, во-вторых, насколько мне известно, статус не может содержать длинное значение, то как статус typecasting дает нам значение, которое длинное, а не адрес?

+1

дубликата HTTP: // StackOverflow .com/questions/12949383/converting-primitive-data-type-to-void-pointer-type? –

+0

@MartinR: Поскольку [this] (http://man7.org/linux/man-pages/man3/pthread_join.3.html) говорит, что ** pthread_join() копирует статус выхода целевого потока (т. Е. значение, которое целевой поток передан pthread_exit (3)) в место, на которое указывает * retval **.Но в программе, о которой я упоминал, _status_ не указывает на какое-либо место, то как работает эта программа? –

+0

Это работает случайно. Статус переменной не инициализируется, поэтому он будет записывать на все точки состояния. Случайно, это может быть где-то законным. Если это где-то незаконно, вы получите крах. – cup

ответ

1

Быстрый ответ: Нет, использовать intptr_t

Длинный ответ: долго не гарантируется, чтобы вписаться в пустоту *. На некоторых системах (в частности, на 64-разрядных машинах Intel Linux) он будет работать с void *, а длинные - как 64-битные, так и процессоры Intel не имеют других различий типов. На других машинах, таких как 32-разрядная Intel Linux, он не будет работать с тех пор, как долго это 64-битные и void * 32-бит на этих машинах. Более экзотические машины имеют разные свойства.

Стандартный тип, который поддерживает int < -> преобразования указателей - intptr_t, найденный в stdint.h. Согласно POSIX Руководство программиста:

Следующий тип обозначает знаковое целое число типа с тем свойством, что любой допустимый указатель к мочеиспусканию могут быть преобразованы к этому типу, а затем преобразуется обратно в указатель на пустоту, и результат будет сравнивать равен исходный указатель: intptr_t

Так intptr_t это знаковый целый типа неустановленной длиной, который гарантированно поддерживает преобразование от и к мочеиспусканию *. Существует также unsigned uintptr_t.

Here is the definition of intptr_t in glibc. Как вы можете видеть, на 64-битных машинах intptr_t и long действительно являются одним и тем же типом.

+0

В этой документации указано, что 'intptr_t' может содержать значение любого указателя, а не наоборот. Например, если указатели 32-разрядные, а 'intptr_t' - 64-разрядные, то они будут соответствовать требованиям. (То есть, приведение от указателя к целому и обратно будет работать.) Я не думаю, что существует какой-либо тип, гарантирующий наличие противоположного свойства. – Nemo

+0

Это хороший момент, хотя, читая источник glibc, я уверен, что он действительно будет работать с этой конкретной реализацией. Но я согласен с тем, что стандарт не требуется. Не стесняйтесь редактировать мой ответ, чтобы уточнить. – jforberg

0

эта линия:

rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t); 

не является правильным.

Предлагайте с помощью:

rc = pthread_create(&thread[t], &attr, BusyWork, (void *)&t); 

Тогда 'проблема' исчезает

Примечание: в функции Busywork() получить фактическое значение обратно:

long myVar = *parmVoidPtr; 
Смежные вопросы