Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: struct и кракозяблы  (Прочитано 1662 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн [DarkNet]Alpha

  • Автор темы
  • Активист
  • *
  • Сообщений: 987
  • Эмоциональный эльдар
    • Просмотр профиля
    • EBM-радио
struct и кракозяблы
« : 07 Октября 2010, 23:19:43 »
Делаю лабораторную работу по c++. Задача - создать структуру из работников некого отдела, содержащую ФИО и месяц рождения, а потом выбрать сотрудников, родившихся в определённый месяц. Тестируя вывод, наткнулся на проблему кракозябл.
(Нажмите, чтобы показать/скрыть)
(Нажмите, чтобы показать/скрыть)

Пользователь решил продолжить мысль 07 Октября 2010, 23:27:32:
Внезапно вылечилось указанием явной длины строк f, i, o в структуре. Можете объяснить, почему так?
« Последнее редактирование: 07 Октября 2010, 23:27:32 от [DarkNet]Alpha »

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #1 : 07 Октября 2010, 23:41:21 »
Где у тебя выделяется и освобождается память под строки? Попробуй представить как твой массив структур располагается в памяти и куда ты пишешь.

Цитировать
otdel otdel1[n], *p=&otdel1[0];
А тут что за новости? n у тебя не константа и не define, теперь внимание вопрос сколько элементов в твоём массиве???

Ещё по мелочи: Зачем делать цикл по индексу и указателю на текущий элемент если ты не используешь индекс в теле цикла?

По форматированию: очень сложно читать код когда в одной строке делается объявление массива и указателя. Не экономь на строках.

Оффлайн [DarkNet]Alpha

  • Автор темы
  • Активист
  • *
  • Сообщений: 987
  • Эмоциональный эльдар
    • Просмотр профиля
    • EBM-радио
Re: struct и кракозяблы
« Ответ #2 : 07 Октября 2010, 23:51:58 »
Уважаемый невнимательно читает.
Цитировать
А тут что за новости? n у тебя не константа и не define, теперь внимание вопрос сколько элементов в твоём массиве???
cout << "Сколько сотрудников работает в отделе? ";
cin >> n;

Цитировать
Зачем делать цикл по индексу и указателю на текущий элемент если ты не используешь индекс в теле цикла?
Так написано в методичке =( А как здесь сделать правильно?

Цитировать
По форматированию: очень сложно читать код когда в одной строке делается объявление массива и указателя. Не экономь на строках.
Спасибо, учту.
« Последнее редактирование: 07 Октября 2010, 23:55:15 от [DarkNet]Alpha »

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #3 : 08 Октября 2010, 00:00:14 »
Еще раз повторю слова коллеги, "n у тебя не константа и не define", а переменная типа int, что не даст желаемого результата. Нужно под массив выделять память с помощью new и освобождать её как только она станет не нужна с помощью delete.

И попутный вопрос опытным программистам c/c++, разрешите полюбопытствовать, а как вообще возможна такая конструкция
int a=12345;
char с[a];
и что в реале получается? Наверное это чтото из оперы char 20[c], но как разворачивается char c[a] и почему это глотает компилятор я не пойму...

Оффлайн [DarkNet]Alpha

  • Автор темы
  • Активист
  • *
  • Сообщений: 987
  • Эмоциональный эльдар
    • Просмотр профиля
    • EBM-радио
Re: struct и кракозяблы
« Ответ #4 : 08 Октября 2010, 00:07:53 »
Еще раз повторю слова коллеги, "n у тебя не константа и не define", а переменная типа int, что не даст желаемого результата. Нужно под массив выделять память с помощью new и освобождать её как только она станет не нужна с помощью delete.
Можно пример, как правильно?

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #5 : 08 Октября 2010, 00:09:07 »
otdel *p = new otdel[n];

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #6 : 08 Октября 2010, 00:13:24 »
Цитировать
И попутный вопрос опытным программистам c/c++, разрешите полюбопытствовать, а как вообще возможна такая конструкция
int a=12345;
char с[a];

Я тоже не понял, но походу он это прямо на стеке и разворачивает. Прошёл по коду:
    int n;
    std::cout << "array dimention: " << std::endl;
    std::cin >> n;

    int arr[n];
    for (int i = 0; i < n; i++) {
        arr[i] = i;
    }
valgrind'ом он говорит всё в порядке память нигде не портиться. Как и ожидалось alloc/free count: 0/0

Может при этом g++ генерит код просто для сдвига указателя стека на заданное количество байт (sizeof(int)*n). Тут бы дизасмблером посмотреть но я не умею им пользоваться.

Но мне почему-то кажется, что это поведение заведомо не соответствует стандарту C++98. Может расширение C++0x, но вроде же они по дефолту выключены, или я что-то проспал. По идее компилято вообще есть не должен эту конструкцию.
« Последнее редактирование: 08 Октября 2010, 00:16:49 от VestniK »

Оффлайн [DarkNet]Alpha

  • Автор темы
  • Активист
  • *
  • Сообщений: 987
  • Эмоциональный эльдар
    • Просмотр профиля
    • EBM-радио
Re: struct и кракозяблы
« Ответ #7 : 08 Октября 2010, 00:14:50 »
Опять указатели... Ппц.
После паскля и питона с++ всё больше кажется мне набором костылей =(

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #8 : 08 Октября 2010, 00:31:19 »
В паскале ты тоже под динамические массивы память не выделял? То что ты постишь это дикая смесь C и C++. Если бы ты пользовался STL то многих проблем бы не было. Кстати вы C изучали или сразу с C++ начали?

Оффлайн [DarkNet]Alpha

  • Автор темы
  • Активист
  • *
  • Сообщений: 987
  • Эмоциональный эльдар
    • Просмотр профиля
    • EBM-радио
Re: struct и кракозяблы
« Ответ #9 : 08 Октября 2010, 00:47:16 »
Изучал, но настолько мало, что этим можно пренебречь.

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #10 : 08 Октября 2010, 01:18:33 »
И попутный вопрос опытным программистам c/c++, разрешите полюбопытствовать, а как вообще возможна такая конструкция
int a=12345;
char с[a];
и что в реале получается? Наверное это чтото из оперы char 20[c], но как разворачивается char c[a] и почему это глотает компилятор я не пойму...
Всё что нарыл в гугле за последний часик сводится к тому, что это верно с точки зрения стандарта C99 и, по идее, должно быть в C++0x, но вот с точки зрения C89 и C++98 это не верно. g++ даже с ключём -ansi, а так же и с эквивалнтным ему ключём -std=c++98 даже варнинга не выдаёт, единственный способ заставить его делать хоть что-то это использовать -pedantic тогда он генерит на эту конструкцию предупреждение:
g++ test.cpp -Wall -pedantic -o test
test.cpp: In function ‘int main(int, char**)’:
test.cpp:10: warning: ISO C++ forbids variable length array ‘arr’

Нужно это за тем, чтобы уменьшить фрагментирование памяти и избежать частых вызовов malloc/free внутри функции, размещая массив прямо на стеке:
void do_something(double *arr, int size)
{
    double buf[n];
    // work with arr and buf
}
этот код будет работать несколько быстрей нежели если в начале буфер будет создаваться в динамической памяти а потом освобождаться, особенн это хорошо, тем, что куча не фрагментируется из за частых промежуточных malloc/free. В обсуждениях C++0x довольно интересные конструкции попадались, позволяющие использовать эту фичу в классах и структурах:
struct Matrix { float data[]; Matrix(int M, int N) : data[M,N](0) {} };

Пользователь решил продолжить мысль 08 Октября 2010, 01:28:09:
Вот только сразу замечу, что если значение переменной которая будет переданна в качестве размерности ассива идёт не из на 100% надёжного источника, то мы получим stack overflow и приложение рухнет, так что это расширение не очень безопасно, и работать с ним нужно с умом и большой осторожностью.

Например,сли при чтени данных из сокета первые 4 байта это размер последующего сообщения. Сообщения складываются в VLA массив, объявление которого сделанно до проверки вычитанной длинны сообщения на разумность, то завалить такой сервис удалённой атакой задача тривиальная.
« Последнее редактирование: 08 Октября 2010, 01:28:09 от VestniK »

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #11 : 08 Октября 2010, 01:29:40 »
походу он это прямо на стеке и разворачивает
Ага, собака, разворачивает:
(Нажмите, чтобы показать/скрыть)

После паскля и питона с++ всё больше кажется мне набором костылей =(
Вот паскаль и питон это языки более высокого уровня, и именно к ним скорее всего применима фраза "удобный набор костылей". А C/C++ это ближе к истокам, т.е. в них виднеется голая правда архитектуры компьютера.

Сам C/C++ язык не "на скорую руку", чтоб пасьянсы с саперами лепить, а для системных и требующих приемлемую производительность задач.

Пользователь решил продолжить мысль [time]Fri Oct  8 01:35:53 2010[/time]:
Значит, [DarkNet]Alpha, мы на тебя смуту навели. Так, как у тебя сейчас есть с памятью под структуры, работать будет. А чтобы все остальное заработало, замени в структуре char[] на string.
« Последнее редактирование: 08 Октября 2010, 15:37:41 от Mam(O)n »

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #12 : 08 Октября 2010, 01:44:16 »
Цитировать
Значит, [DarkNet]Alpha, мы на тебя смуту навели. Так, как у тебя сейчас есть с памятью под структуры, работать будет.
Будет если пользователь ввёл не сильно большое число. Это именно та ситуация, в которой использовать VLA небезопасно. То же самое, что в моём примере с чтением данных из сокета.

Если ты работаешь с 2х, 3х и 4х мерными векторами и хочешь писать на чистом C функции, которые будут просто принимать размерность вектора как параметр, а алгоритм будет описан лишь однажды, то тут, под временные буферы внутри функций, VLA идеально подходит. Но если размерность массива задаётся пользователем, приходит по сети или вычисляется с помощью нетривиальных математических операций, то лучше старые добрые malloc/free с проверкой что память не кончилась.

Оффлайн Mam(O)n

  • Старожил
  • *
  • Сообщений: 5855
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #13 : 08 Октября 2010, 02:01:08 »
То есть разумные пределы это те, пока стек не упал на кучу?

Пользователь решил продолжить мысль 08 Октября 2010, 02:02:39:
А существует защита от переполнения стека и порчи кучи?
« Последнее редактирование: 08 Октября 2010, 02:02:39 от Mam(O)n »

Оффлайн VestniK

  • Активист
  • *
  • Сообщений: 594
    • Просмотр профиля
Re: struct и кракозяблы
« Ответ #14 : 08 Октября 2010, 02:19:05 »
То есть разумные пределы это те, пока стек не упал на кучу?
Именно
А существует защита от переполнения стека и порчи кучи?
в том то и фишка, что нет. В стандарте сказанно undeined behaviour :)

VLA штука конечно полезная, но с ней нужно быть осторожным.

 

Страница сгенерирована за 0.021 секунд. Запросов: 21.