Разница между static_cast <char *> и (char *) - PullRequest
6 голосов
/ 11 ноября 2011

это мой первый вопрос:)

У меня есть один файл стопки, и я открыл его, как показано ниже;

ifstream in ( filename,  ios :: binary | ios :: in ) 

Тогда я бы хотел хранить 2-байтовые данные в неподписанном int hold;

unsigned int hold;
in . read(static_cast<char *>(&hold), 2); 

Мне кажется, это правильно. Однако, когда я компилирую это с

g++  -ansi -pedantic-errors -Werror - -Wall  -o main main.cpp 

Компилятор выдает ошибку

error: invalid static_cast from type ‘unsigned int*’ to type ‘char*’ 

На самом деле, я решил эту проблему, изменив static_cast на (char *), то есть

unsigned int hold;
in . read((char*)(&hold), 2); 

Мои вопросы:

  • В чем разница между static_cast<char*> и (char*)?
  • Я не уверен, безопаснее ли использовать (char*). Если у вас достаточно знаний, вы можете сообщить мне об этой теме?

ПРИМЕЧАНИЕ: Если у вас есть идея получше, пожалуйста, помогите мне, чтобы я мог улучшить свой вопрос?

Ответы [ 5 ]

11 голосов
/ 11 ноября 2011

static_cast безопаснее, чем неявное приведение в стиле C.Если вы попытаетесь привести сущность, которая не совместима с другой, то static_cast выдает ошибку времени компиляции в отличие от неявного приведения в стиле c.

static_cast выдает здесь ошибку, потому что выПопытка сказать, это взять int и попытаться вписать его в char, что невозможно.int требуется больше памяти, чем занимает char, и преобразование не может быть выполнено безопасным способом.

Если вы все еще хотите добиться этого, вы можете использовать reinterpret_cast, Это позволяет вам выполнить два типасовершенно разные типы данных, но это небезопасно.
Единственная гарантия, которую вы получаете с reinterpret_cast, заключается в том, что если вы приведете результат обратно к исходному типу, вы получите то же значение, но никаких других гарантий безопасности.

3 голосов
/ 11 ноября 2011
  • сначала - вы можете легко найти _cast и найти любой c ++ cast. Поиск бросков в стиле c намного сложнее.
  • секунда - если вы используете приведение c ++, вам нужно выбрать правильное. В вашем случае это reinterpret_cast.
    Состав в стиле c делает все.

Вы также можете проверить здесь: http://www.cplusplus.com/doc/tutorial/typecasting/ для различий различных приведений c ++. Я настоятельно рекомендую использовать только приведения C ++. Таким образом, вы можете легко найти и проверить их позже, и вам придется задуматься о том, что вы на самом деле делаете там. Это улучшает качество кода!

1 голос
/ 11 ноября 2011

static_cast здесь недопустимо; вы бросаете между не связанными типы указателей. Решение для его компиляции было бы использовать reinterpret_cast (в этом случае (char*) разрешается). Что, конечно, говорит вам, что код не переносим, ​​и на самом деле, если вы не делаете какую-то работу очень низкого уровня, вероятно, не будет работать правильно во всех случаях.

В этом случае, конечно, вы читаете необработанные данные и утверждаете, что это unsigned int. Что это не так; что читать входные данные сырые данные, которые вы все равно придется вручную конвертировать во все, что вам нужно, в соответствии с Формат, используемый при записи файла. (Нет такой вещи как неформатированные данные. Просто данные с недокументированным, неуказанным или неизвестный формат. & Ldquo; неформатированный & rdquo; вход и выход в iostream предназначен для чтения и записи char буферов, которые вы форматируете вручную. Потребность в reinterpret_cast здесь однозначное предупреждение что-то не так с вашим кодом. (Есть исключения, из конечно, но они немногочисленны.)

1 голос
/ 11 ноября 2011

Вы должны были использовать reinterpret_cast<char *> вместо static_cast<char *>, потому что типы данных не связаны: вы можете конвертировать между указателем на подкласс, например, в суперкласс, или между int и long, илимежду void * и любым указателем, но unsigned int * до char * не "безопасны", и поэтому вы не можете сделать это с static_cast.

Разница в том, что в C ++ у вас есть различные типыбросает:

  • static_cast для «безопасных» преобразований;

  • reinterpret_cast для «небезопасных» преобразований;

  • const_cast, который предназначен для удаления атрибута const;

  • dynamic_cast, который предназначен для снижения (приведение указателя / ссылки изсуперкласс к подклассу).

Приведение в стиле C (char *)x может означать все вышеперечисленное, поэтому оно не так ясно, как в C ++.Кроме того, легко выполнить grep для приведения в стиле C ++ (просто grep для _cast), но довольно сложно найти все приведения в стиле C.

0 голосов
/ 12 июля 2017

Обычно вы получаете эти ошибки во время ввода / вывода двоичных файлов, используя ifstream, ofstream или fstream. Проблема в том, что у этих потоков есть методы, которые принимают const char*, в то время как у вас есть массив другого типа. Вы хотите записать свой массив как двоичные биты в файл.

Традиционный способ сделать это - использовать приведение в старом стиле (char*), которое в основном просто говорит, что к любому указателю я отношусь как (char*). Броски старого стиля не поощряются педантичным / строгим режимом . Чтобы избавиться от этих предупреждений, эквивалент C ++ 11 - reinterpret_cast<const char*>.

Я бы сказал, что если вы выполняете бинарный файловый ввод-вывод, то вы уже знаете, что вещи могут или не могут быть переносимы в зависимости от того, как вы сохраняете файл в одной ОС и читаете в другой ОС. Это совсем другая проблема, однако, не пугайтесь reinterpret_cast<const char*>, потому что это то, что вам нужно сделать, если вы хотите записать байты в файл.

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