Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54

Безопасное приведение типа - const_cast

12.01.2018, 13:37. Показов 1601. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Проблемы с функцией strcpy_s. Ошибки:
1)функция не принимает 2 аргументов
2)отсутствуют экземпляры перегруженная функция "strcpy_s", соответствующие списку аргументов


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string.h>
using namespace std;
void Func(const char* s)
{
    char* str;
    str = const_cast<char*>(s);
    strcpy_s(str,"New string");
}
int main()
{
    char* source = "Initial string";
    cout << "Before Func() source = " << source << '\n';
    Func(source);
    cout << "After Func() source = " << source << '\n';
    system("pause");
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.01.2018, 13:37
Ответы с готовыми решениями:

Безопасное приведение
Заинтересовало безопасное приведение типов. То есть чтобы определяло ужимание и выдавало ошибку. Вышло как-то так. А как бы сделали...

Конструкторы, приведение типа и ошибка "Не найден оператор, принимающий правый операнд типа 'char *'"
#include &lt;stdio.h&gt; class A { int somemember; public: A(){printf(&quot;A()\n&quot;);} A(char*){printf(&quot;A(char*)\n&quot;);} ...

приведение типа
Здравствуйте. у меня такой вопрос. как можно в c++ 2008 поменять тип. мне нужно char перевести в int, я пробовала char a; int y; y=(int)a;...

19
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 14:56
C++
1
char[] source
или изучай динамические массивы.

Добавлено через 2 минуты
И
Цитата Сообщение от Tasen Посмотреть сообщение
strcpy(str,"New string");
Но при этом ты сам должен гарантировать, что в копируемой строке будет не больше символов чем в "Initial string"

Добавлено через 16 секунд
http://en.cppreference.com/w/c/string/byte/strcpy
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 16:44  [ТС]
TRam_, поправлю вас, правильно будет
C++
1
char source[]
а не
C++
1
char[] source
Ваш ответ частично привел меня к решению проблемы. После того как я написал char source[], ошибки все равно остались. Пришлось сделать просто strcpy, вместо strcpy_s и отключить предупреждения, только после этого все скомпилировалось. Но мне все равно не понятно почему в первоначальном варианте копирование не работает?
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 17:24
Потому что

1) char* source = "Initial string"; создаёт на самом деле указатель на строку в неизменяемой памяти, и такая запись на самом деле возможна только для совместимости, правильно было бы написать const char* source = "Initial string"; и соответственно не получить никакой возможности редактировать свою строку.

Подробнее - https://www.cyberforum.ru/blogs/18334/blog97.html

2) внимательно нужно смотреть определение strcpy_s, и соответственно вызывать
C++
1
strcpy_s(str, sizeof(str), "New string");
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 17:41  [ТС]
Но даже после этих корректировок:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string.h>
using namespace std;
void Func(const char* s)
{
    char* str;
    str = const_cast<char*>(s);
    strcpy_s(str, sizeof(str), "New string");
}
int main()
{
    const char* source = "Initial string";
    cout << "Before Func() source = " << source << '\n';
    Func(source);
    cout << "After Func() source = " << source << '\n';
    system("pause");
}
Программа просто аварийно закрывается, а во время отладки выбрасывает исключение:
Вызвано исключение по адресу 0x00AECE4F (ucrtbased.dll) в Project5.exe: 0xC0000005: нарушение прав доступа при записи по адресу 0x00DC9B40.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 17:52
Цитата Сообщение от Tasen Посмотреть сообщение
str = const_cast<char*>(s);
Из серии "говорили же, что пальцами в розетку лазить нельзя, так не верю, обязательно надо проверить, что от этого будет".

Добавлено через 1 минуту
Собственно и получил вылет из-за попытки изменить неизменяемую память.

Добавлено через 4 минуты
А чтобы изменять, нужен либо статический, либо динамический массив. Либо его обёртка в виде std::vector или std::string
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 17:56  [ТС]
Однако исключение все равно остается даже если сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string.h>
using namespace std;
void Func(char s[])
{
    strcpy_s(s, sizeof(s), "New string");
}
int main()
{
    char source[] = "Initial string";
    cout << "Before Func() source = " << source << '\n';
    Func(source);
    cout << "After Func() source = " << source << '\n';
    system("pause");
}
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 18:17
Лучший ответ Сообщение было отмечено Tasen как решение

Решение

А вот код
C++
1
2
3
4
    char source[] = "Initial string";
    cout << "Before Func() source = " << source << '\n';
    strcpy_s(source, sizeof(source), "New string");
    cout << "After Func() source = " << source << '\n';
Работает без проблем

Добавлено через 1 минуту
И вот такой - тоже
C++
1
2
3
4
5
6
7
8
9
10
11
12
void Func(char s[], int size)
{
    strcpy_s(s, size, "New string");
}
int main()
{
    char source[] = "Initial string";
    cout << "Before Func() source = " << source << '\n';
    Func(source, sizeof(source));
    cout << "After Func() source = " << source << '\n';
    system("pause");
}
1
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 18:35  [ТС]
TRam_, точно! Проблема была в sizeof. Полагаю, что он брал размер указателя и тем самым выделялось не достаточно памяти для копирования.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 18:58
char s[] - это не указатель, это статический массив. Неизвестного размера...
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 19:40  [ТС]
TRam_, я про sizeof(s), имя массива это есть указатель на первый элемент
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 20:02
Цитата Сообщение от Tasen Посмотреть сообщение
имя массива это есть указатель на первый элемент
запусти
C++
1
2
3
char source1[] = "Initial string";
const char *source2 = "Initial string";
cout << sizeof(source1) << " " << sizeof(source2);
и убедись в обратном

Добавлено через 1 минуту
Хотя вот для адресной арифметики - да, так его можно рассматривать.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.01.2018, 20:03
Цитата Сообщение от Tasen Посмотреть сообщение
char* source = "Initial string";
Цитата Сообщение от Tasen Посмотреть сообщение
Func(source);
Цитата Сообщение от Tasen Посмотреть сообщение
strcpy_s(str,"New string");
снятие константности с объекта,
который изначально был рожден как константа - это UB

так в принципе нельзя делать.

Добавлено через 1 минуту
Цитата Сообщение от TRam_ Посмотреть сообщение
char s[] - это не указатель, это статический массив. Неизвестного размера...
в аргументах функций:
Цитата Сообщение от TRam_ Посмотреть сообщение
void Func(char s[], int size)
это именно что указатель.

на языке с++ не существует никаких массивов неизвестного размера.
1
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 20:07  [ТС]
TRam_, убеждаюсь в том, что sizeof(source1) возвращает 15, а sizeof(source2) 4
Цитата Сообщение от TRam_ Посмотреть сообщение
C++
1
2
3
char source1[] = "Initial string"; 
const char *source2 = "Initial string"; 
cout << sizeof(source1) << " " << sizeof(source2);
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
12.01.2018, 20:11
Tasen, и это значит что указатель и статический массив таки отличаются. По крайней мере в размере
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 20:28  [ТС]
hoggy,
Цитата Сообщение от hoggy Посмотреть сообщение
снятие константности с объекта,
который изначально был рожден как константа - это UB
так в принципе нельзя делать.
1)Если так в принципе делать нельзя, однако такое все равно существует, значит для чего-то когда-то оно было нужно или это баловство?
2)Что такое UB?

Добавлено через 6 минут
на 2-й вопрос я нашел ответ
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.01.2018, 20:38
Цитата Сообщение от Tasen Посмотреть сообщение
Если так в принципе делать нельзя, однако такое все равно существует
если объект изначально не был константным,
то снятие константности с его алиасов - технически корректно.

по сути это - хак, и используется он для разруливания ситуаций
плохо продуманных интерфейсов.

наличие const_cast в коде - признак ущербной архитектуры.

рассмотрим пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <cstring>
using namespace std;
void Func(const char* s)
{
    char* str = const_cast<char*>(s);
    strcpy_s(str, 11, "New string");
}
int main()
{
    char source[] = "Initial string";
    cout << "Before Func() source = " << source << '\n';
    Func(source);
    cout << "After Func() source = " << source << '\n';
}
в этом примере
какой то балбес почему то заюзал в качестве аргумента
указатель на константу.

допустим теперь у нас легаси.
а нам кровь из носу нужно модифицировать объект.
на рефактор нет времени.

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

Цитата Сообщение от Tasen Посмотреть сообщение
Что такое UB?
undefined behavior

неопределенное поведение.

ситуация, когда произойти может все что угодно.
например: все может прекрасно отработать.
а в другой раз - поломаться в самом неожиданном месте.
ну или компилятор может сгенерить код,
который отправит вам открытку по почте.

в вашем случае, вы делали запись по адресу константного объекта.
зная, что объект рожден константой,
и в угоду оптимизаций,
компилятор мог расположить объект в области памяти "только для чтения".
попытка записи в этот участок памяти - сигнал смерти от операционной системы.
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 20:59  [ТС]
hoggy, здорово.
Цитата Сообщение от hoggy Посмотреть сообщение
в этом примере
какой то балбес почему то заюзал в качестве аргумента
указатель на константу.
Вот пример из первоисточника (книга по с++ Глушакова и Дуравкиной 2008 года)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void Func(const char* s)
{
char* str;
str = const_cast<char*>(s);
strcpy(str, "New string");
}
int main()
{
char* source = "Initial string";
cout << "Before Func() source = " << source << '\n';
Func(source);
cout << "After Func() source = " << source<< '\n';
return 0;
}
Можно ли их называть балбесами? Или просто книга слишком старая и за 10 лет язык претерпел множество изменений...
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
12.01.2018, 21:08
Лучший ответ Сообщение было отмечено Tasen как решение

Решение

Цитата Сообщение от Tasen Посмотреть сообщение
Вот пример из первоисточника (книга по с++ Глушакова и Дуравкиной 2008 года)
Цитата Сообщение от Tasen Посмотреть сообщение
Можно ли их называть балбесами?
либо вы что то не правильно скопипастили.
либо какая то опечатка от издательства.
либо они балбесы)
0
2 / 2 / 0
Регистрация: 31.07.2017
Сообщений: 54
12.01.2018, 21:18  [ТС]
hoggy, можете быть абсолютно уверены, что может быть 2-е или 3-е, либо ни то и не другое
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.01.2018, 21:18
Помогаю со студенческими работами здесь

Приведение типа указателя
Здравствуйте, у меня такой вопрос: как организовать приведение типа указателя к другому? Есть указатель string *ptr; на поле класса, нужно...

C-style приведение типа: (T) x
Есть современные формы приведения типа: static_cast&lt;T&gt;(x) dynamic_cast&lt;T&gt;(x) reinterpret_cast&lt;T&gt;(x) const_cast&lt;T&gt;(x) ......

Приведение типа указателя на метод
Здравствуйте. Есть функция, принимающая void (*f)(), возможно ли использовать ее в классе, передавая ей не-static метод этого класса? ...

Приведение производного типа к предку
Есть класс-обертка Inherit, есть класс Base: class Inherit : public Base { public: int c; Inherit(int a, b, _c) :...

Приведение типа через указатель
#include &lt;iostream&gt; using namespace std; int main() { double b = 2.3; int* pb; pb = (int*)&amp;b; *pb =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru