Страницы

Поиск по вопросам

пятница, 13 декабря 2019 г.

Разница между const LPSTR и const char*

#cpp #c #winapi


Есть такой код:

const LPSTR str = "str";
const char* str2 = "str";

int main()
{
    char* w = str;
    char* w2 = str2; //error: cannot convert from 'const char *' to 'char *'
    return 0;
}


Почему появляется такая ошибка понятно. Но почему такой ошибки нет строчкой выше,
когда используется LPSTR? Ведь это только typedef char* LPSTR;
    


Ответы

Ответ 1



Потому что typedef - это не макрос, т.е. не текстовая подстановка. В const LPSTR str = "str"; const уже относится к самому str, а не к указуемым данным. То есть это эквивалентно следующему объявлению char *const str = "str"; Отличие от const char* str2 = "str"; очевидно. Поэтому и нет ошибки в char* w = str;. Формально в современном С++ const LPSTR str = "str"; является некорректным кодом. Указатель на некостантный char нельзя просто так поставить указывать на строковый литерал.

Ответ 2



для начала разберемся с типами переменных: Инициализация const указателя на char посредством строкового литерала. Наличие const слева может вводить в заблуждение, так как он применяется ко всему типу LPSTR, а не только к его левой части, то бишь к char. Поведение для С и С++ в этом случае различается. const LPSTR str = "str"; // аналогично LPSTR const str = "str"; char * const str = "str"; Инициализация указателя на const char посредством строкового литерала. Вот тут const применяется непосредственно к типу char. Ничего криминального. const char* str2 = "str"; // аналогично char const * str2 = "str"; char const * const str2 = "str"; const LPCSTR str2 = "str"; LPCSTR const str2 = "str"; Инициализация указателя на char посредством const указателя на char. Ничего криминального. char* w = str; Инициализация указателя на char посредством указателя на const char. Это ошибка как в С, так и в С++. char* w2 = str2; Ответ для языка C: В стандарте C89 и C99 строковые литералы имеют тип "массив char" (без const), соответственно строковой литерал можно использовать для инициализации переменной типа char *. Однако попытка модификации буфера, на который будет указывать в этом случае указатель приводит к неопределенному поведению. Если код в вопросе собрать как С код, то наличие только одной ошибки будет корректно - переменную с типом char * нельзя инициализировать значением с типом const char *. Ответ для языка С++: В современном С++ строковые литералы имеют тип "массив const char", соответственно строковой литерал для инициализации переменной типа char * использовать нельзя. Строка const LPSTR str = "str"; должна вызывать ошибку, однако в Visual Studio старых версий по-умолчанию используется некомфорное поведение "как в С". Выключить его в VS2015 можно указав компилятору опцию /Zc:strictStrings-, в VS2017 опцию /permissive-.

Комментариев нет:

Отправить комментарий