Я пытаюсь создать динамически выделяемый массив типа unsigned char* на C++. Однако, когда я это делаю, я возвращаю строку вместо заключенного в скобки ({}) массива, чего я хочу.
unsigned char* arr = new unsigned char[arrLen];
Изображение, показывающее разницу между двумя
Вы видите, как последний не исчезает после первого символа? Это то, что я хочу.
Как я могу это исправить?
Спасибо за ваше время.
Также интересно, в чем может быть проблема, не могли бы вы прояснить?
Я не хочу, чтобы это была струна. Функция, в которую я передаю это, нуждается в заключенном в скобки списке. Для контекста содержимое arr будет исполняемым файлом в шестнадцатеричном формате. Исполняемые файлы содержат много нулевых байтов, что добавляет странности, если интерпретируется как строка, потому что они интерпретируют их как конец строки.
Как вы думаете, почему это струна?
А как вы думаете, что такое "массив, заключенный в скобки ({})"?
Не уверен, в чем проблема. Но указатели беззнакового типа char * все время используются как массивы. Они интерпретируются как обычные данные и иногда используются для отображения графики с графическими данными. Но по-разному интерпретируются только при печати с такими командами, как cout. если, например, вы: char * str = "string" cout << str << endl; отобразит: строка. Если это не дает ответа на вопрос, укажите его более четко.
Вы преследуете фантома. Отладчик не знает, насколько велик массив или даже если есть массив на другом конце этого указателя, поэтому все, что он может сделать, это принять символьную строку и показать вам все до нулевого терминатора.
Теперь я понимаю, что отладчик мне «врет». Комментарий к сообщению RichieHindle по этой ссылке (stackoverflow.com/questions/972511/…) довольно хорошо подводит итог. Но разве нет способа заключить скобку динамического массива, как я показал, потому что до сих пор я мог делать это нормально со статическими массивами, а затем передавая функции ссылки на них. Я бы предпочел это, поскольку на данном этапе моего кода он был бы более однородным, а также потому, что некоторые функции действительно требуют наличия такого массива. Пример: у меня есть функция для проверки заголовка NT / DOS.
Вы уверены, что ваш первый пример заканчивается вторым персонажем? Ваш отладчик может предполагать, что это строка при ее отображении. Что там говорится о содержимом arr [2]?
Вы действительно спрашиваете, как настроить отображение отладчика?





Во-первых, отладчик по умолчанию предполагает, что char представляет собой символ ascii, а не число. Он будет отображать char как таковой.
arr2 имеет тип const char[3], поэтому отладчик знает, что нужно отобразить 3 элемента.
arr имеет тип const char*. Отладчик не может знать, только ли это один элемент или массив с определенным количеством элементов.
Если вы, например, используете Visual Studio, вы можете указать отладчику, чтобы он отображал три символа, добавив «часы переменных» с синтаксисом arr,3 в меню часов.
Я не уверен, что это то, что вы ищете, но пробовали ли вы использовать std :: vector? Он может обрабатывать как минимум динамическое присваивание, которое вы ищете, и не должен рассматривать символ NULL как конец строки.
#include <vector>
std::vector<char> arr = { 0x5A, 0x00, 0x2B };
На самом деле я пробовал использовать std :: vector, когда начинал создавать свою программу, но с такими огромными массивами exe он вел себя забавно. Как будто он никогда не компилируется. Однажды я оставил его на ночь, но этого не произошло. Итак, я изменил его на массивы символов, затем во время компиляции он вышел из "CL.exe" с кодом 2, поэтому я попытался сделать массивы символов статическими, и тогда это сработало. Что касается вопроса, я не стал делать их статичными, но вы поняли. В любом случае, спасибо, это отлично подойдет для массивов, размер которых не превышает 10 МБ.
Если вам нужен динамически растущий список символов (массив), вам нужен список указателей, в котором список каждого сегмента представляет собой большое число, скажем 1000. Класс векторного контейнера жертвует использованием памяти ради возможности роста.
векторный контейнерный класс допускает динамический рост, но использует много памяти
Кроме того, динамическое увеличение одного элемента данных за раз не рекомендуется для большого списка данных. Если вам нужен динамический рост для большого списка, создайте список по частям, например следующим. Используйте большой сегмент списка - скажем, 1000 единиц. В следующем примере я создал 1000 списков. Я делаю это, создавая массив из 1000 указателей. Это создаст 1 миллион искомых символов и может динамически расти. В следующем примере показано, как это сделать.
.
void main() {
unsigned char* listsegment[1000];
int chrn=0;
int x, y = 0;
for (int x = 0; x < 1000; x++) {
listsegment[x] = new unsigned char[1000];
for (y = 0; y < 1000; y++) {
*(listsegment[x] + y) = chrn;
if (chrn >=255) chrn=0;
else chrn++;
}
}
}
Завершение программы - Что делать, если необходимо динамически выделить более 1000 сегментов?
Затем создайте список наборов сегментов. Он может быть либо в связанном списке, либо в классе контейнера.
Поскольку один набор создает 1000 сегментов по 1000 символов, набор этих наборов, вероятно, не должен превышать 1000. Наборы из тысяч будут равны (1000 * 1000) * 1000, что будет равно одному миллиарду. Следовательно, коллекция должна быть только 1000 или меньше, что может быть быстро повторено, что делает случайный доступ к коллекции ненужным.
Вот программа, переделанная для поддержки бесконечного количества наборов через бесконечно большой набор наборов. Это также хороший пример сегментированного распределения динамической памяти в целом.
#include <iostream>
#include<queue>
using namespace std;
struct listSegmentSetType {
unsigned char* listSegment[1000];
int count=0;
};
void main() {
listSegmentSetType listSegmentSet;
queue<listSegmentSetType> listSegmentSetCollection;
int numberOfListSegmentSets = 0;
int chrn = 0;
int x, y = 0;
listSegmentSet.count = 0;
for (int x = 0; x < 1000; x++) {
listSegmentSet.listSegment[x] = new unsigned char[1000];
for (y = 0; y < 1000; y++) {
*(listSegmentSet.listSegment[x] + y) = chrn;
if (chrn >= 255) chrn = 0;
else chrn++;
}
listSegmentSet.count++;
}
// add just completely filled out first list segment set to que
listSegmentSetCollection.push(listSegmentSet);
numberOfListSegmentSets++;
// now fill in second set of list segments-
listSegmentSet.count = 0;
for (int x = 0; x < 1000; x++) {
listSegmentSet.listSegment[x] = new unsigned char[1000];
for (y = 0; y < 1000; y++) {
*(listSegmentSet.listSegment[x] + y) = chrn;
if (chrn >= 255) chrn = 0;
else chrn++;
}
listSegmentSet.count++;
}
listSegmentSetCollection.push(listSegmentSet);
numberOfListSegmentSets++;
// now fill out any more sets of list segments and add to collection
// only when count listSegmentSet.count is no
// longer less than 1000.
}
-1 Этот ответ никак не затрагивает вопрос. Взгляните на std::deque, чтобы найти аналогичные блоки контейнера библиотеки данных.
Ага. Я знаю, что есть класс контейнера, который является классом списка. Также собирался упомянуть сделать двусвязный список. Таким образом, он дает достаточно содержательный ответ на вопрос, но просто не включает двусвязный список, потому что я думал, что это займет у меня слишком много времени и слишком много времени, чтобы ответить на вопрос.
В чем проблема ?