2014-10-07 2 views
-1

Указатель на void (void*) совместим и может содержать любой другой тип указателя. Это также верно для указателя на const void (const void*).Использование const void * вместо void *, для любого типа

С:

6.3.2.3, р2: Для любого спецификатора д, указатель на не-Q-квалифицированного типа может быть преобразован в указатель на Q-квалифицирован вариант типа; значения, хранящиеся в исходных и преобразованных указателях , сравниваются равными.

Поскольку я позволил этому:

int n = 0 ; 
void* p = &n ; 

я также позволил этому:

int n = 0 ; 
const void* p = &n ; 

Это подводит меня к конечной точке, которая является то, что все это должно также проводить для сложных литералов.

void SomeFunc(const void* p) { printf("%p",p) } ; 

SomeFunc(&(int){ 12345 }) ; 

Должен быть определен (и разрешен) стандартом C?

ответ

2

Я согласен прямо. Я редко нахожу потребность в составных литералах в C, но ваш синтаксис определенно обоснован. Если я правильно понимаю ваш вопрос, нужно попытаться определить, приводит ли вышеупомянутый адрес оператора к составному литералу в const против указателя не-const.

Это не константа, если само соединение не является const-квалифицированным. Я не имею C99 стандарта удобного, но самый лучший примером, который я могу всунуть для этого является поучительным примером в:

C11 стандарт §6.5.2.5 p11

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

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6} 

в сочетании с описанием квалификации для хранения составных литералов из:

С11 стандартных §6.5.2.5 р5

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

Таким образом, хранилище также существует (то есть оно не находится где-то в постоянном запоминающем устройстве). Если const квалифицирован, составной литерал является, по сути, неконстантным (данные/элементы в нем, если массив или структура составного литерала могут, по сути, иметь свою квалификацию const).

Механика перевода с Type * на любой void* или const void* являются надеемся, очевидно, но стоит отметить какой-затяжка вашего образца:

void SomeFunc(void* p) { printf("%p\n",p); } ; 
void SomeFuncConst(const void* p) { printf("%p\n",p); } ; 

int main() 
{ 
    SomeFunc(&(int){ 12345 }) ;  // OK. int* to void* 
    SomeFuncConst(&(int){ 12345 }) ; // OK. int* to const void* 
    SomeFuncConst &(const int){12345}); // OK. const int* to const void* 
    SomeFunc(&(const int){ 12345 }) ; // ERROR. const int* not allowed as void* 
} 

Учитывая все это, вполне вероятно, я неправильно понял ваш вопрос, и если да, то любезно проясните, как я достигаю ссылки delete.

+0

Да, я пропустил, что у вас есть две функции. – 2501

+0

Да, моя проблема заключалась в преобразовании из типа * и const type * в const void *. – 2501

+0

Думаю, я должен доверять вам на const int * на const void *. – 2501

1

Там нет никаких проблем с этим вызовом

SomeFunc(&(int){ 12345 }) ; 

Аналогичным примером есть в C Стандартного

drawline(&(struct point){.x=1, .y=1}, 
     &(struct point){.x=3, .y=4}); 

Согласно стандарту C (6.5.2.2 вызовов функций)

7 Если выражение, обозначающее вызываемую функцию, имеет тип, который содержит прототип, аргумент nts неявно преобразуются, как , если по назначению, к типам соответствующих параметров, принимая тип каждого параметра, который является неквалифицированной версией его объявленного типа .

Похоже, что существует пробел в стандарте C относительно преобразований. Более подробные неявные преобразования описаны в стандарте C++

1 Стандартные преобразования - это неявные преобразования со встроенным значением. В пункте 4 перечисляется полный набор таких преобразований. Стандартная последовательность преобразования представляет собой последовательность стандартных преобразований в следующем порядке:

- Нулевое или одно преобразование из следующего набора: преобразование lvalue-to-rval, преобразование матрицы в указатель и преобразование функции в указатель ,

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

- Zero или один квалификация изменение.

Таким образом, как видно, стандартная последовательность преобразования включает в себя одно преобразование указателя и одно преобразование квалификации.

Стандарт C может дать аналогичное подробное описание.

+0

Что такое прототип drawline. Требуется ли const const void *? – 2501

+0

@ 2501 Как следует из примера, functopn принимает два указателя на структурную точку. Тем не менее любой указатель может быть неявно преобразован в указатель void. Таким образом, нет проблемы с const void *. –

+0

Ваше последнее утверждение логически не вытекает из предыдущего. Не могли бы вы ответить на этот вопрос? – 2501

Смежные вопросы