2016-07-23 2 views
1

Я создал динамический массив struct Vector, внутренности которого я скрываю от пользователей. Вместо функции предусмотрены для взаимодействия с ними, такими какКак вернуть указатель функции как const?

bool Vector_push(struct Vector *vector, const void *value) 

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

void Vector_set_type_destructor(struct Vector *vector, void (*type_destructor)(void *)) 

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

const void (*Vector_type_destructor(const struct Vector *vector))(void *); 

Обратите внимание, как я добавил const ключевое слова, как я хотел типа деструктор будет только изменяемым через сеттер, а не через возвращенный указатель. Тем не менее, я получил следующее предупреждение от clang.

src/Vector.c:184:66: warning: function cannot return qualified void type 
     'const void' [-Wqualified-void-return-type] 
const void (*Vector_type_destructor(const struct Vector *vector))(void *) { 
                   ^
src/Vector.c:185:12: warning: incompatible pointer types returning 
     'void (*const)(void *)' from a function with result type 
     'const void (*)(void *)' [-Wincompatible-pointer-types] 
    return vector->type_destructor; 

Как правильно вернуть указатель void (*type_destructor)(void *) через функцию, не подвергая его возможной модификации?

+1

Я не понимаю. Как пользователь может изменить указатель на функцию деструктора? Первый сценарий: я вызываю getter и сохраняю результат в локальной переменной x. Позже я изменяю содержимое x. Теперь локальная переменная указывает на другую функцию. Но указатель функции, хранящийся в структуре Vector, по-прежнему указывает на исходную функцию. Нет проблем! Второй сценарий: я вызываю getter, сохраняю результат в x. Затем я разыгрываю x и изменяю байты, хранящиеся по его адресу. То есть, я изменяю код функции деструктора. Ни один здравомыслящий человек не сделает этого. - Какой сценарий вы пытаетесь избежать? –

+0

Ваше имя запрашивает указатель на функцию, код показывает указатель на 'const', и каким-то образом ваш текст, кажется, запрашивает указатель' const'. Также как «void *» вступает в игру? См. [Ask], ваш вопрос довольно туман. – Olaf

ответ

4

Попробуйте положить const рядом с * вместо:

void (*const Vector_type_destructor(const struct Vector *vector))(void *); 
+0

Компилятор замолчал, так что это правильный ответ. Не могли бы вы объяснить, как это должно быть прочитано как возвращающее константный указатель 'void (* p) (void *)'? –

+0

Я предлагаю прочитать статью, в которой объясняется, как читать декларации типов в C. Например, см. Https://stackoverflow.com/a/5503393 и https://stackoverflow.com/a/89100. – Rufflewind

+0

Спасибо. Обычно у меня их больше, но это просто неприятно. –