Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.80
sledge
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
#1

Вопрос о строках. - C++

12.08.2009, 19:14. Просмотров 1214. Ответов 20
Метки нет (Все метки)

Здравствуйте, все.

Талдычу строки.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <stdio.h>
using namespace std;
 
int main() {
 
    char * pstr1="tes"; 
    short offset=strlen(pstr1)+1;
    
    pstr1="wxyz";
    for(offset*=-1;offset<(short)strlen(pstr1);offset++){
        cout<<"pstr1["<<offset<<"]=="<<*(pstr1+offset)<<endl;
    }
    return 0;
}
вывод
pstr1[-4]==t
pstr1[-3]==e
pstr1[-2]==s
pstr1[-1]==
pstr1[0]==w
pstr1[1]==x
pstr1[2]==y
pstr1[3]==z

Получается, что если присвоить указателю на символ новую строку, то выделятется новый кусок памяти(см. вывод).
Вопрос 1.
Нужно ли заботиться о уплывших байтах? Что-то подсказыватет, что надо.
Вопрос 2.
Если нужно, то подскажите как правильно все сделать.

Спасибо заранее читающим || отвечающим.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Haster
инженер-системотехник
109 / 108 / 2
Регистрация: 10.03.2009
Сообщений: 533
12.08.2009, 19:33     Вопрос о строках. #2
Что ты понимаешь под уплывающими байтами? Вообще данные строки Являются статическими, т.е. размещаются на этапе компиляции и освобождать память из-под них не нужно. В то же время не факт, что вторую строку он разместит сразу за первой. Так что твои результаты - частный случай...
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
12.08.2009, 19:52     Вопрос о строках. #3
Получается, что если присвоить указателю на символ новую строку, то выделятется новый кусок памяти(см. вывод).
Выделяется память из стека,предназначенная для локальных переменных,и все локальные объекты уничтожаются по выходе из блока.(Я полагаю,вызывается деструктор.)
Вопрос 1.
Нужно ли заботиться о уплывших байтах? Что-то подсказыватет, что надо.
Вопрос 2.
Если нужно, то подскажите как правильно все сделать.
В данном случае не нужно.
Но если был использован оператор new,то тогда память нужно освобождать с помощью delete.
C++
1
2
3
4
   char *str = new char;
  ...
   delete [] str;// или
   delete str;
Потому что память выделяется "динамически".То есть программист сам выделяет её из общего доступного пространства и сам должен её освобождать.Я пока сам смутно понимаю данную тему,но вроде так.
zim22
depict1
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
12.08.2009, 20:02     Вопрос о строках. #4
Цитата Сообщение от #pragma Посмотреть сообщение
* *char *str = new char;
* ...
* *delete [] str;// или
* *delete str;
что значит "// или"? в данном случае мы выделяем память используя operator new не для массива, а для одиночного объекта. так что первая форма записи
C++
1
delete [] str
ошибочна
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
12.08.2009, 20:04     Вопрос о строках. #5
А если так?
C++
1
char *str = new char [1]
То есть один элемент не может быть массивом?И потом,при записи
C++
1
char *str=new char;
Выделяется же память под один байт,а если записать туда больше байт?Это ведь тоже будет массив?
Gravity
558 / 552 / 39
Регистрация: 29.01.2009
Сообщений: 1,274
12.08.2009, 20:11     Вопрос о строках. #6
#pragma, если записать туда больше одного байта, то можно нарваться на ячейку памяти кем-то уже занятую.
#pragma
Временно недоступен
952 / 223 / 6
Регистрация: 12.04.2009
Сообщений: 921
12.08.2009, 20:14     Вопрос о строках. #7
Но всё таки запись
C++
1
delete []str
корректна,я проверил с компиляцией "gcc -ansi -pedantic -Wall"
Rififi
2336 / 1051 / 44
Регистрация: 03.05.2009
Сообщений: 2,656
12.08.2009, 20:46     Вопрос о строках. #8
#pragma,

char *str = new char [1]
То есть один элемент не может быть массивом?И потом,при записи
Это связано с особенностью адресной арифметики с C/C++
Указатель - он всегда указывает на ОДИН элемент (а этот элемент может быть например, массивом). при добавлении числа, машинный адрес изменяется на число * (размер области данных), так что если эта память принадлежит процессу, то мы можем юзать её. так достигается иллюзия работы как с массивом.
CheshireCat
Эксперт С++
2891 / 1240 / 78
Регистрация: 27.05.2008
Сообщений: 3,340
12.08.2009, 22:48     Вопрос о строках. #9
Цитата Сообщение от #pragma Посмотреть сообщение
Но всё таки запись [...] корректна,я проверил с компиляцией "gcc -ansi -pedantic -Wall"
Это допустимо с точки зрения компилятора, однако, в соответствии с точным смыслом Стандарта (5.3.5/2), приводит к undefined behavior - неопределенному поведению программы. Если тебе повезет - программа будет работать, как будто ничего не произошло. Если не повезет.... значит, не повезет. В самом неудачном случае невезения будет время от времени появляться невоспроизводимый глюк в программе. И, по закону подлости, он обязательно проявится именно при демонстрации программы Самому Главному Боссу....
novi4ok
550 / 503 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
13.08.2009, 00:21     Вопрос о строках. #10
Цитата Сообщение от #pragma Посмотреть сообщение
Выделяется память из стека,предназначенная для локальных переменных,и все локальные объекты уничтожаются по выходе из блока.
в данном случае - нет. и прав Haster: строки находятся в поле констант.

хотите убедиться - посмотрите сюда:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void func(){
    DWORD_PTR stackPtr;
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in func: "<<stackPtr<<endl;
    char *pstr1="testestestestestestestestestestestestestestesAAA";
    cout<<"pstr1 in func: "<<pstr1<<endl;
}
 
void func2(){
    DWORD_PTR stackPtr;
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in func2: "<<stackPtr<<endl;
    char *pstr1="111111111111111111111111111111111111111111111111111111222";
    cout<<"pstr1 in func2: "<<pstr1<<endl;
}
 
 
int main(...) {
    DWORD_PTR stackPtr;
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in main before func() call: "<<stackPtr<<endl;
    func();
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in main before func2() call: "<<stackPtr<<endl;
    func2();
    __asm mov [stackPtr], esp;
    cout<<"stack pointer in main after func2() call: "<<stackPtr<<endl;
}
выполните и посмотрите (советую в дибаггере посмотреть что расположено по данным адресам) куда указывает указатель стэка, и где находятся эти строчки. все поймете.

Добавлено через 33 минуты 56 секунд
дополню: указатели
C++
1
char *pstr1
, конечно, будут находиться именно в стэке
CheshireCat
Эксперт С++
2891 / 1240 / 78
Регистрация: 27.05.2008
Сообщений: 3,340
13.08.2009, 10:21     Вопрос о строках. #11
Кстати, коллеги, вот простой тест, показывающий разницу между delete и delete[] формами:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;
 
class test
{
public:
    test() { cout << "test ctor" << endl; }
    ~test() { cout << "test dtor" << endl; }
};
 
int main()
{
    test* p = new test[5];
    cout << "----------" << endl;
    delete p;
    //delete[] p;
 
    return 0;
}
 
/*
output:
test ctor
test ctor
test ctor
test ctor
test ctor
----------
test dtor
 
*/
Поскольку это частая ошибка начинающих программистов, мне представляется полезным проиллюстрировать ее.
novi4ok
550 / 503 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
13.08.2009, 12:06     Вопрос о строках. #12
теперь проверьте, правильно ли сработают

C++
1
2
    test** p = new test[5][10];
    delete[][] p;
,
C++
1
2
    test*** p = new test[5][10][20];
    delete[][][] p;
...

зачем такие заморочки писать, даже если это "правильно работает"?
ISergey
Maniac
Эксперт С++
1347 / 880 / 52
Регистрация: 02.01.2009
Сообщений: 2,645
Записей в блоге: 1
13.08.2009, 12:11     Вопрос о строках. #13
Цитата Сообщение от novi4ok Посмотреть сообщение
теперь проверьте, правильно ли сработают

C++
1
2
    test** p = new test[5][10];
    delete[][] p;
,
C++
1
2
    test*** p = new test[5][10][20];
    delete[][][] p;
Даже не скомпелится..
sledge
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
13.08.2009, 15:41  [ТС]     Вопрос о строках. #14
Спасибо за ответы всем. :-) Прочитал и понял как много нужно узнать :-).

Поставлю вопрос, касающийся моего листинга, так:
Переменная pstr1 будет размещена в стеке. Симолы "tes" и "wxyz" будут размещены в стеке или в динамической памяти или еще где-то?

Еще вопрос:
Что за стек пресловутый такой? Читал - про гору тарелок. получается, если в функции main() объявить три переменных(положить 3 тарелки друг на друга), то как мне достать нижнюю переменную? Куда положить две снятые тарелки?

Спасибо за ответы.
novi4ok
550 / 503 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
13.08.2009, 17:00     Вопрос о строках. #15
Цитата Сообщение от sledge Посмотреть сообщение
Переменная pstr1 будет размещена в стеке.
правильно.
Цитата Сообщение от sledge Посмотреть сообщение
Симолы "tes" и "wxyz" будут размещены в стеке или в динамической памяти или еще где-то?
"еще где-то". в области констатн. проще выражаясь, они будут являться частью тела вашего скомпилированного модуля.

Цитата Сообщение от sledge Посмотреть сообщение
Еще вопрос:
Что за стек пресловутый такой? Читал - про гору тарелок. получается, если в функции main() объявить три переменных(положить 3 тарелки друг на друга), то как мне достать нижнюю переменную? Куда положить две снятые тарелки?
вам не нужно об этом заботиться вообще, если вы пишете на с++, а не на ассемблере. вы обращаетесь к тарелкам по их именам, а не работаете с указателем стека непосредственно. эти детали берет на себя компилятор.
sledge
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
13.08.2009, 20:42  [ТС]     Вопрос о строках. #16
Цитата Сообщение от novi4ok Посмотреть сообщение
правильно.

"еще где-то". в области констатн. проще выражаясь, они будут являться частью тела вашего скомпилированного модуля.
Похоже что так и есть.
C++
1
2
char * pstr1="tes";
for(int i=0;i<2;i++) *(pstr1+i)=char(i+65); pstr1[2]='\0';
Вылетает с ошибкой.

Прочитал - есть 5 областей. Мож кому интересно будет.
1. область глоб.перем. - хранятся глобальные переменные.
2. динамическая - создается/уничтожается new/delete.
3. регистровая память (хранятся вершина пресловутого стека,адрес команды...)
4. сегменты программы - программный код.
5. стековая память(Пресловутая )

Если пойти методом от противного то получается, что если объявить
C++
1
char * pstr1="tes";
то pstr1 попадет в стековую память, а сама строка "tes" в сегменты программы.
Поправьте.

Спасибо всем.
odip
Эксперт С++
7155 / 3295 / 59
Регистрация: 17.06.2009
Сообщений: 14,164
13.08.2009, 20:55     Вопрос о строках. #17
Не в сегмент программы, а в read-only область данных программы (где хранятся все константы, строки).
CheshireCat
Эксперт С++
2891 / 1240 / 78
Регистрация: 27.05.2008
Сообщений: 3,340
13.08.2009, 22:19     Вопрос о строках. #18
Если говорить о Win32-программе, в ней все инициализированные константы, и, в частности, строковые литералы (а упомянутый "tes" - это именно строковый литерал, а не строка!) размещаются в специальной секции PE-модуля с именем .rdata - read-only data. Хотя, зависит от компилятора, - компилятор от Борланда любит размещать такие константы прямо в секции .code - которая, разумеется, тоже read-only
Устройство эльф-модуля из никсов я подробно не копал, но, думаю, будет то же самое.
sledge
0 / 0 / 0
Регистрация: 27.07.2009
Сообщений: 13
13.08.2009, 22:29  [ТС]     Вопрос о строках. #19
Цитата Сообщение от odip Посмотреть сообщение
Не в сегмент программы, а в read-only область данных программы (где хранятся все константы, строки).
odip,CheshireCat , если Вас не затруднит - киньте ссылкой или скажите где почитать про эти чуднЫе области памяти, Потому как в той книге, что я читаю, - я нашел упоминание только о тех областях, которые я запостил в предыдущем сообщении.

Спасибо заранее.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.08.2009, 23:18     Вопрос о строках.
Еще ссылки по теме:

Общий фрагмент в строках C++
Замена слов в строках C++
Элементы, расположеные на главной диагонали, в первых 3 строках выше диагонали и в последних 2 строках ниже диагонали переместить в одномерный массив C++
C++ Ошибка в простейших строках
Работа с функциями в строках C++

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

Или воспользуйтесь поиском по форуму:
CheshireCat
Эксперт С++
2891 / 1240 / 78
Регистрация: 27.05.2008
Сообщений: 3,340
13.08.2009, 23:18     Вопрос о строках. #20
Например, вот: http://www.rsdn.ru/article/baseserv/pe_coff.xml
Yandex
Объявления
13.08.2009, 23:18     Вопрос о строках.
Ответ Создать тему
Опции темы

Текущее время: 05:02. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru