2013-07-24 3 views
4

C++ Почему следующее неправилен в C++ (но действует в C)разница между недействительными указателями в C и

void*p; 
char*s; 
p=s; 
s=p; //this is wrong ,should do s=(char*)p; 

Зачем мне нужен кастинг, поскольку p теперь содержит адрес char указателя и s также char указатель?

+0

P не является указателем на символ. Назначая _value_ '' '' p', вы также не назначаете _type_. –

+2

(Кстати, ваши указатели оба неинициализированы, поэтому их значения неопределены.) –

+0

Что произойдет, если вы присвоите int-указателю p, а затем s = p? –

ответ

8

Значение не имеет значения, тип делает. Так как p является указателем на пустоту и s указателем на символ, вам нужно отбрасывать, даже если они имеют одинаковое значение. В C это будет нормально, void* является общим указателем, но это неверно в C++.

К сожалению, p не содержит указатель на указатель, это указатель на void и содержит адрес памяти.

+0

'p'is указатель void – Hulk

+0

@Hulk Спасибо, Халк, это была просто ошибка – nouney

16

Это действительно C, но не C++; это два разных языка, даже если они имеют много общих черт.

В C++ отсутствует неявное преобразование от void* к типизированному указателю, поэтому вам нужно сделать бросок. Вы должны предпочесть C++ приведения типа, поскольку они ограничивают какие конверсии разрешены и поэтому помогают предотвратить ошибки:

s = static_cast<char*>(p); 

еще лучше, вы должны использовать полиморфные методы (такие как абстрактные базовые классы и шаблоны), чтобы избежать необходимости в сначала используйте нетипизированные указатели; но это выходит за рамки этого вопроса.

0

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

double d = 0.0; 
int i = 0; 

d = i; // Totally OK 
i = d; // Warning! 

Это то, с чем вам нужно жить.

+0

Что такое« Предупреждение! » должен означать? Вы говорите, что мы не можем назначать какие-то типы другим, но как вы можете это сделать? Он компилируется и работает очень хорошо - http://coliru.stacked-crooked.com/a/2e53040cdfc520f9 - потому что, как и наоборот, 'double' имеет неявное (если возможно сужение) преобразование в' int'. –

+0

@underscore_d Вот что я имел в виду, потенциально сужающийся бит. Вы можете включить это предупреждение в g ++ и заговорить с '-Wconversion'. Обратите внимание, что нет предупреждения для назначения в другом направлении. –

+0

Это объясняет это. Я до сих пор не вижу, как это относится к 'void * 'и к вопросу; что мне не хватает? Неявные преобразования указателей являются действительными или нет; они не могут сужаться, но разрешены. По-видимому, реальный ответ заключается в том, что определение «действительный» изменилось между C и C++. Напротив, я уверен, что сужение правил для несвязанных числовых типов не было. –