Присвоение const неконстантным в C - PullRequest
3 голосов
/ 11 февраля 2011

В следующих случаях:

struct adt { void * A; };

int new_adt(const void * const A)
{
    struct adt * r = malloc(sizeof(struct adt));
    r->A = A;
}

Я получаю:

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


IЯ знаю, что могу использовать

memcpy(&(r->A), &A, sizeof(void *));

, чтобы обойти это, но я должен спросить: есть ли альтернатива?

Используя const void * const, я притворяюсь, что никаких изменений не произойдетвход.Кроме того, теперь, когда я думаю об этом, const void * будет достаточно, не так ли?(Так как я не могу изменить указатель так, чтобы он влиял на абонента)

Спасибо, что нашли время для чтения.

Ответы [ 3 ]

7 голосов
/ 11 февраля 2011

Используя const void * const, я притворяюсь, что никакие изменения не будут внесены во входные данные.

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

Вы НЕ ДОЛЖНЫ делать то, что вы делаете.

5 голосов
/ 11 февраля 2011

Если вы никогда не захотите изменить A через его указатель из adt, то вы должны также сделать этот указатель константным, т. Е .:

struct adt {
    const void * A;
};

Это устранит ошибку.

Если вы делаете , хотите изменить A до adt, тогда new_adt должен принимать неконстантный указатель.


Редактировать: более общее примечание, которое может помочь:

Ключевое слово const, как правило, применяется к типу непосредственно к его left . Однако, если слева от него нет типа, он будет применяться к типу справа. Так: const int * A совпадает с int const * A (const применяется к int, а не к указателю), но в int * const A const применяется к указателю, а не к int.

В Википедии есть более полное объяснение: const-правильность . Раздел «Указатели и ссылки» на этой странице содержит пример, который охватывает различные комбинации const и non-const, которые вы можете применить к указателю.

0 голосов
/ 11 февраля 2011

Вы можете отбросить константу:

r->A = (void *) A;

Однако проблема не в том, как избежать предупреждения, а в том, что вы пытаетесь сделать.Компилятор предупреждает вас, потому что вы говорите компилятору, что «A» не доступен для записи, но вы пытаетесь сохранить его в месте, которое определяет его как доступное для записи.Как правило, это не совсем нормально, семантически.

Представьте, что «A» указывает на местоположение в разделе данных вашего двоичного файла;попытка записи в него после отбрасывания const, скорее всего, вызовет segfault.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...