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

Указатели на char

27.11.2014, 20:51. Показов 3368. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помогите разобраться в чём ошибка и как можно проиллюстрировать её.
Было написано:
1)
Code
1
2
3
char *s;
s = "Hello";
s[1] = 'a';
2)
Code
1
2
char *sn;
strcpy (sn,"Hello");
И в 1 и во 2 случае преподаватель указал на ошибку и сказал что так делать нельзя. Надо делать так:
1)
Code
1
2
char *s= "Hello";
s[1] = 'a';
2)
Code
1
2
char *sn = new char [10];
strcpy (sn,"Hello");
Код в принципе работает и так и сяк. В чём конкретно ошибка? И почему? Помогите разобраться, пжлст.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.11.2014, 20:51
Ответы с готовыми решениями:

указатели char
Уважаемые, помогите разобраться с указателями. Вот пример. Есть класс Class P{ public: void SetName(name){ ...

Указатели на char
Доброго времени суток! Никак не могу разобраться с указателями :( Базовые вещи аля подобных примеров int z = 1; int *ptrz =&z;...

Указатели char *
Добрый день, с момента создания прошлой темы про указатели я разобрался в ней. Понял, что конкретно не понятно - когда в функцию передается...

21
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
27.11.2014, 20:58
Boltina, в исправленных случаях память выделяется на стадии инициализации переменных.
И код не должен работать "и так, и сяк". Во всяком случае, непредсказуемо, куда запишется значение.
З.Ы. strcpy тоже не рекомендуемо, из-за отсутствия проверки на количество выделенной памяти и количество символов, которые хотят туда записать.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
27.11.2014, 20:58
Лучший ответ Сообщение было отмечено Boltina как решение

Решение

1) "Hello" - константа. Ее менять нельзя. char* - указатель на изменяемую область памяти. Ссылаться на константу как на изменяемый объект не по феншую.
2) sn не инициализировано, а значит указывает к черту на рога. Соответственно, strcpy пытается написать у черта на рогах, что огорчает чертей.
0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
27.11.2014, 21:01
З.Ы.
Цитата Сообщение от Boltina Посмотреть сообщение
Надо делать так
Необязательно именно так. Можно просто выделить необходимую память, записать нужное значение (чтобы, конечно, оно туда "влезло") и добавить нуль-терминатор.

Добавлено через 1 минуту
Цитата Сообщение от Renji Посмотреть сообщение
Hello" - константа
и правда, что-то я пропустил этот момент..
0
0 / 0 / 1
Регистрация: 27.11.2014
Сообщений: 54
27.11.2014, 21:05  [ТС]
Как - то с пониманием сложно. А можно ещё какие нибудь примеры или ресурсы по этому поводу? Не укладывается потому что код отрабатывает что в билдере что на старом(синем) С. А как нибудь наглядно можно увидеть эти ошибки?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
27.11.2014, 21:27
Все очень просто char* не хранит в себе никаких строк. Он хранит указатель "строка лежит вон там". И если вы этот указатель не инициализировали, то он указывает в произвольное место памяти. По первому примеру - попробуйте угадать результат такой программы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
void test()
{
    char*str="1234";
    cout<<str<<endl;
    str[2]=0;
}
int main()
{
    test();
    test();
    return 0;
}
По второму примеру - strcpy портит рандомную область памяти. Если там ничего ценного не было, ошибка незаметна. А если что-то ценное было, то аукнется ошибка неизвестно когда. До этого будет лежать миной замедленного действия.
0
0 / 0 / 1
Регистрация: 27.11.2014
Сообщений: 54
27.11.2014, 21:49  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
str[2]=0;
Это специально 0 или должно быть так:
C++
1
str[2]='0';
При 0 понятное дело что-то затирается(str=12), если как char, то первый проход затирает константу и уже во втором проходе будет str = 1204, сразу.
Как нужно объявлять чтобы ваш код отработал верно?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
27.11.2014, 21:52
Специально. Строки в стиле C считаются заканчивающимися там, где стоит символ с кодом 0. Соответственно, str[2]=0 обрезает строчку до двух символов.
0
Почетный модератор
Эксперт HTML/CSSЭксперт PHP
 Аватар для KOPOJI
16844 / 6724 / 880
Регистрация: 12.06.2012
Сообщений: 19,967
27.11.2014, 21:58
Цитата Сообщение от Boltina Посмотреть сообщение
или должно быть так:
Можно так, если с использованием символьной константы
C
1
str[2]='\0';
0
0 / 0 / 1
Регистрация: 27.11.2014
Сообщений: 54
27.11.2014, 22:05  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
Специально. Строки в стиле C считаются заканчивающимися там, где стоит символ с кодом 0. Соответственно, str[2]=0 обрезает строчку до двух символов.
Обрезает строку первый раз, а второй раз уже с обрезанной пытается работать, т.е. затирает константу в памяти. Тогда вопрос:
1) Затирает, используем указатель, работает неправильно
C++
1
2
char *str = new char [10];
     str="1234";
2)Не затирает, тоже указат, работает правильно
C++
1
2
char *str = new char [10];
    strcpy (str,"Hello");
3)Не затирает, исп. массив,работает правильно
C++
1
char str[] = "1234";
Так в каких случаях что использовать? Когда указатель, а когда char str[]?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
27.11.2014, 22:17
Лучший ответ Сообщение было отмечено Boltina как решение

Решение

1) В str заносится адрес массива созданного в динамической памяти. Затем он затирается адресом константы.
2) В str заносится адрес массива созданного в динамической памяти. В массив копируется константа.
3) В стеке создается символьный массив (строка) инициализированный константой.

Со случаями же все просто.
1) Нужна строковая константа (менять ее не требуется) - const char*str="1234";.
2) Нужна строка которую можно менять - char str[]="1234";
3) Нужна строка которую надо менять и ее размер неизвестен - char*str=new char[размер вычисленный на стадии исполнения];. Не забыть потом вызвать delete.
1
0 / 0 / 1
Регистрация: 27.11.2014
Сообщений: 54
27.11.2014, 22:31  [ТС]
Цитата Сообщение от Renji Посмотреть сообщение
1) В str заносится адрес массива созданного в динамической памяти. Затем он затирается адресом константы.
2) В str заносится адрес массива созданного в динамической памяти. В массив копируется константа.
3) В стеке создается символьный массив (строка) инициализированный константой.
Со случаями же все просто.
1) Нужна строковая константа (менять ее не требуется) - const char*str="1234";.
2) Нужна строка которую можно менять - char str[]="1234";
3) Нужна строка которую надо менять и ее размер неизвестен - char*str=new char[размер вычисленный на стадии исполнения];. Не забыть потом вызвать delete.
2) Второй случай правильно работает если размер мы не меняем? Вот к примеру...
C++
1
2
3
4
5
6
7
char str[] = "Hello";
str[1]='a';
str[5]='s';
str[8]=0;
str[7]='q';
str[6]='f';
Label1->Caption = str;
Я вроде как бы изменяю размер, но то что оно там затирает в памяти неизвестно, так? (выводит строку до терминатора)
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
27.11.2014, 22:35
Да. Если нужно менять размер, то надо что-то вроде char str[1024]="1234"; (резервируем память под 1023 символа и ноль в конце). Или std::string который вмещает сколько угодно символов.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
27.11.2014, 22:44
Цитата Сообщение от Boltina Посмотреть сообщение
C++
1
2
3
char *s;
s = "Hello";
s[1] = 'a';
В языках С и С++ строковые литералы являются немодифициремыми объектами. Этот код пытается модифицировать строковый литерал. Поведение не определено.

Более того, в языке С++11 окончательно запрещено преобразование строковых литералов к типу 'char *'. Строковый литерал может быть преобразован только к типу 'const char *'. Т.е. в современном С++ этот код даже не будет компилироваться.

Цитата Сообщение от Boltina Посмотреть сообщение
C++
1
2
char *sn;
strcpy (sn,"Hello");
Код выполняет попытку доступа через неинициализированный указатель. Поведение не определено.

Цитата Сообщение от Boltina Посмотреть сообщение
И в 1 и во 2 случае преподаватель указал на ошибку и сказал что так делать нельзя. Надо делать так:
C++
1
2
char *s= "Hello";
s[1] = 'a';
Это преподаватель такое сказал? Это какая-то ерунда. Код ничем принципиально не отличается от оригинального варианта и содержит все те же ошибки. Замена присваивания на инициализацию ничего не меняет.

Цитата Сообщение от Boltina Посмотреть сообщение
C++
1
2
char *sn = new char [10];
strcpy (sn,"Hello");
Ну тут как бы все верно, но это не пример из области как "надо" делать. "Надо" чтобы указатель указывал на буфер достаточного размера, а вот как получен этот буфер - это вопрос посторонний. Можно и так

C++
1
2
3
char buffer[100];
char *sn = buffer + 10;
strcpy (sn,"Hello");
0
0 / 0 / 1
Регистрация: 27.11.2014
Сообщений: 54
27.11.2014, 22:48  [ТС]
C++
1
2
3
char buffer[100];
char *sn = buffer + 10;
strcpy (sn,"Hello");
Почему +10? Это к чему?
0
27.11.2014, 22:52

Не по теме:

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Код ничем принципиально не отличается от оригинального варианта и содержит все те же ошибки
Меняет, размер выделенной памяти..

0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
27.11.2014, 22:58
Цитата Сообщение от KOPOJI Посмотреть сообщение
Меняет, размер выделенной памяти..
Не вижу там в упор никакого изменения "размера выделенной памяти".

Добавлено через 1 минуту
Цитата Сообщение от Boltina Посмотреть сообщение
Почему +10? Это к чему?
Чисто к примеру. Речь идет о том, указатель должен указывать на достаточное количество памяти. Если это условие соблюдено, то откуда взялась эта память - вопрос посторонний. Можно написать +42 вместо +10.
0
0 / 0 / 1
Регистрация: 27.11.2014
Сообщений: 54
27.11.2014, 23:02  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Чисто к примеру. Речь идет о том, указатель должен указывать на достаточное количество памяти. Если это условие соблюдено, то куда именно он указывает - не важно. Можно написать +42 вместо +10.
+ 10 - в данном случае увеличит объём памяти, на который указывает указатель, на 10?
0
27.11.2014, 23:03

Не по теме:

TheCalligrapher, и правда, что-то сегодня не так с головой.. указатель спутать с массивом :facepalm:
Прошу прощения за мою глупость :)

0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12925 / 6793 / 1819
Регистрация: 18.10.2014
Сообщений: 17,190
27.11.2014, 23:16
Цитата Сообщение от Boltina Посмотреть сообщение
+ 10 - в данном случае увеличит объём памяти, на который указывает указатель, на 10?
Нет, никакого отношения к объему памяти это +10 не имеет. Общий размер буфера в моем примере, как несложно видеть, равен 100. А это +10 лишь определяет, в какое место этого буфера будет скопирована строка "Hello".
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.11.2014, 23:16
Помогаю со студенческими работами здесь

Тип char и указатели
Вопрос... Тип может хранить только символы, или строки тоже? Если только символы, то почему этот код работает?: ... void...

Массив символов char и указатели
В общем нужно сохранить путь к диску в переменную, что бы потом использовать в _findfirst Но сколько бы я не бился над этим, ничего не...

Указатели при работе со строками char*
Помогите разобраться с указателями #include &lt;iostream&gt; #include &lt;string.h&gt; using namespace std; int main() { char*...

Указатели char* - конкатенация без <string.h>
char *pp,*p,*s1; // p и s1 имеют свои значения, по сути необходимо из &quot;p&quot; сделать соединение &quot;s1+p&quot; (строго без...

Строки (массив char), указатели. Не могу понять логику! Help!
Вообщем проблема в том что выводятся лишние символы в строках.. хотя в них есть признак окончания строк - нулевой байт я новичок в С...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru