crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
rp80
  опции профиля:
сообщение 4.11.2011, 0:12
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 36
Регистрация: 10.9.2011
Пользователь №: 2860

Спасибо сказали: 0 раз(а)




Репутация:   0  


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

void cpy(char* p, const char* q)
{
    while(*p++=*q++);
}

int main(int argc, char *argv[])
{
    const char* str="abcderrasdfafawefwaeqweqweqweqdsasafw";

    char* str_copy;//Падает
    char* str_copy="c";//Падает

    char* str_copy=new char[1];//Работает


    cpy(str_copy,str);

    std::cout<<str_copy<<std::endl;
}


2 вопроса:
1. Правильны ли следующие рассуждения относительно первых двух объявлений str_copy? В первом случае указатель объявлен, но еще не инициализирован, т.е. фактически никуда не указывает ещё, поэтому и обращения к нему некорректны. Во втором случае str_copy объявлена как строковый литерал, т.е. как const char[2] и во-первых изменять значения такого массива нельзя, а во-вторых указатель выходит за рамки массива после 2.

2. Почему работает последний вариант? Ведь по идее надо бы выделить память следующим образом char* str_copy=new char[strlen(str)];

Спасибо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.11.2011, 9:46
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


rp80, это не код, это полный пииип )))

а зачем вот это чудо тут ?

void cpy(char* p, const char* q)
{
    while(*p++=*q++);
}


а почему работает копирование в константу - это чистая случайность

Цитата
char* str_copy=new char[1];//Работает


тоже до поры до времени. Нет терминатора!

Сообщение отредактировал Алексей1153 - 4.11.2011, 9:45
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
rp80
  опции профиля:
сообщение 4.11.2011, 9:55
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 36
Регистрация: 10.9.2011
Пользователь №: 2860

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Алексей1153 @ 4.11.2011, 10:46) *
rp80, это не код, это полный пииип )))

а зачем вот это чудо тут ?

void cpy(char* p, const char* q)
{
    while(*p++=*q++);
}


Это не пиип, а пример expression-oriented coding из Страуструпа. Функция работает так как и задумано.

Цитата(Алексей1153 @ 4.11.2011, 10:46) *
а почему работает копирование в константу - это чистая случайность

Цитата
char* str_copy=new char[1];//Работает


тоже до поры до времени. Нет терминатора!


char* str_copy=new char[1] - не константа далеко. И терминатор в этой строке не нужен, потому что в нее копируем а не из нее.

Я уже в общем понял почему так происходит.. Хоть память выделена и под 1 чар, но за этим сегментом есть какие-то следующие, поэтому q++ существует и туда можно записать.
Но память все равно нужно выделять под весь массив, ибо иначе мы можем залезть в память , выделенную под другие объекты.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 4.11.2011, 10:10
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


В первом случае указатель не инициализирован и может содержать любой адрес, так что первый случай может и падать и не падать. Как повезет. :) При debug-сборке этот указатель принудительно зануляется, поэтому у тебя и падает всегда.
Во втором случае, указатель указывает на сегмент данных, запись в который может быть запрещена. Поэтому падает.
В третьем случае не падает сразу. Но возможно падение потом, причем трудно обнаруживаемое. Т.к. возможно разрушение управляющих структур кучи.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.11.2011, 12:17
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


rp80, ну что ж, успехов )




Цитата
char* str_copy=new char[1] - не константа далеко. И терминатор в этой строке не нужен, потому что в нее копируем а не из нее.


это не константа, я не про эту строку говорил :)



а вот нечитаемое это безобразие
Цитата
while(*p++=*q++);


надлежит заменять на человеческий код
::memmove(p,q,::strlen(q)+1);


Сообщение отредактировал Алексей1153 - 4.11.2011, 18:56
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
rp80
  опции профиля:
сообщение 4.11.2011, 21:06
Сообщение #6


Студент
*

Группа: Участник
Сообщений: 36
Регистрация: 10.9.2011
Пользователь №: 2860

Спасибо сказали: 0 раз(а)




Репутация:   0  


И ещё пара вопросов тут напишу, чтоб темы не плодить.

1. Корректно ли следующее освобождение памяти?
int pi=*::new int(4);
delete &pi;


2. Здесь имеет место Placement new и неважно чар буффер или инт, главное выделить достаточно памяти?

int buffer[1];//Так работает
char buffer[sizeof(int)];// И так работает
int i2=*::new(buffer) int(87);

Спасибо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 4.11.2011, 21:23
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(Алексей1153 @ 4.11.2011, 13:17) *
а вот нечитаемое это безобразие
Цитата
while(*p++=*q++);


Вообще это обычный strcpy.

Цитата(Алексей1153 @ 4.11.2011, 13:17) *
надлежит заменять на человеческий код
::memmove(p,q,::strlen(q)+1);

В первый проход вычисляем длину строки, а во второй ее копируем? Не много ли проходов? strcpy и вышеприведенная функция делает все в один проход. :)

Цитата(rp80 @ 4.11.2011, 22:06) *
1. Корректно ли следующее освобождение памяти?

Нет. Это попытка освободить память на стеке. :)

Цитата(rp80 @ 4.11.2011, 22:06) *
главное выделить достаточно памяти?

Да. А там хоть:
float arr[ 100 ];
:)

Кстати, такая конструкция чревата утечками памяти:
int i = *::new int(87);

Здесь ты переменной i2 присваиваешь значение из безымянной переменной, которая создается на куче. Дальше указатель на эту переменную теряется... ну и соответственно память не освобождается.

Сообщение отредактировал BRE - 4.11.2011, 22:30
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.11.2011, 21:50
Сообщение #8


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


BRE, неважно, что там два прохода. Зато читаемость :) А оптимизировать там, где это нифига не явно - не нужно, лучше пусть читаемость будет. То есть всё поближе к ООП.

Вот когда тесты показали, что скорости недостаточно, а профайлер ткнул пальцем в это место, тогда будем мудрить.

А кроме того, предлагаю сделать тестик и замерить скорость выполнения обоими способами - не факт, что мой будет медленнее :)

Сообщение отредактировал Алексей1153 - 4.11.2011, 21:51
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 4.11.2011, 21:55
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(Алексей1153 @ 4.11.2011, 22:50) *
BRE, неважно, что там два прохода. Зато читаемость :) А оптимизировать там, где это нифига не явно - не нужно, лучше пусть читаемость будет. То есть всё поближе к ООП.

Читаемость лучше? Здесь?
::memmove(p,q,::strlen(q)+1);


И чем это ближе к ООП, по сравнению с strcpy? :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.11.2011, 21:59
Сообщение #10


фрилансер
******

Группа: Участник
Сообщений: 2943
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


читаемость конечно лучше. И ещё лучше, если заменить на strcpy , но лично я им не пользуюсь, не предоставлялось случаев ) Я обычно для строк использую std::string, std::wstring , а когда надо с отдельными литерами работать - предпочитаю контролировать каждый байтик (а я навскидку не помню, как strcpy обрабатывает терминатор - копирует его тоже или нет)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 23.6.2025, 14:11