Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.72/18: Рейтинг темы: голосов - 18, средняя оценка - 4.72
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24

Const char* и нулевые биты

24.02.2015, 23:00. Показов 4341. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Столкнулась с такой проблемой: есть переменная типа string, например
string str = "A";
Мне требуется расширить ее до 16 бит, для этого делаю
str.resize(str.size() + 8);
Получаем размер 16
Мне нужно скопировать ее в переменную const char*:
const char *cstr = str.c_str();
При выводе размера, получаю 8 вместо 16, то есть нулевые биты никак не учитываются.
Более того, если после нулевых бит, я добавлю еще что-нибудь, например допишу единичку, то она так же не учитывается

Добавлено через 6 минут
Понагляднее пример:
C++
1
2
3
4
5
6
7
8
9
10
11
std::string s;
s.resize(5);
std::cout << "size of s = " << s.size() << "\n"; // выводит 5
const char *с = s.c_str();
size_t len = strlen(c); 
std::cout << "size of c = " << len << "\n"; // выводит 0
s+=0x80;
std::cout << "size of s with 1 = " << s.size() << "\n"; // выводит 6
const char сс = s.c_str();
len = strlen(cc); 
std::cout << "size of c with 1 = " << len << "\n"; // выводит 0
Подскажите пожалуйста, почему так происходит?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.02.2015, 23:00
Ответы с готовыми решениями:

Чем отличаются объявления const char* и const* char
Прошу объяснить мне, чем отличаются объявления const char* и const* char и как объявить: указатель на константный массив символов, ...

... В четных байтах числа в двоичной системе переместить нулевые биты в старшие биты, а в нечетных байтах – в младшие ...
Доброго времени суток всем, столкнулся с проблемой по С++,требуется написать программу: которая получает 1)случайное целое типа int,...

Error C2440: return: невозможно преобразовать "const char *" в "const char (&)[6]"
Вроде все правильно а все равно не работает. Подскажите в чем ошибка #include &lt;iostream&gt; template&lt;typename T&gt; inline...

32
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 15:13
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Sandra357 Посмотреть сообщение
Размер передаваемого функцией сообщения всегда одинаковый - 512 бит,
Вот оно что Все ясно.
Тут нет вообще никаких проблем. Передавай результат data.c_str() обратно, если там действительно 64 байта и testbench тоже ждет 64 байта, то все будет хорошо. const char * - это же не копия данных из string, это указатель на начало последовательности, которую хранит std::string. Т.е. все нужные байты там есть, не смотря на то, что strlen выдает тебе размер меньше. Просто strlen не расчитан на работу с бинарными данными, не нужно его использовать в этой ситуации и все.
0
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24
25.02.2015, 16:39  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Тут нет вообще никаких проблем.
В том то и суть, с чего я вообще этот сыр бор начала) Я в тестбенче проверяю сообщение, которое получила, и оно отличается. Если проверять на исходном сообщении "А", то
после расширения должно быть так (string)
4180000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000008000000 00000000
А у const char* получается
0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 00004180
То есть он букву А и единичный бит получил, дальше решил, что строка кончилась и вывел нули до конца 512 битной переменной...(в моем тестбенче она типа bit[511:0])
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 16:49
Цитата Сообщение от Sandra357 Посмотреть сообщение
В том то и суть, с чего я вообще этот сыр бор начала)
Ответь пожалуйста на вопрос. Вот код:
C++
1
2
3
const char* md5_align (const char* mes) { 
    //[?]
    std::string data = mes; //копируем его в стринг
mes, который пришел в функцию по размеру чему должен быть равен? 64 байта? И нули там могут быть?
0
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24
25.02.2015, 16:53  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
mes, который пришел в функцию по размеру чему должен быть равен? 64 байта?
Нет, входное mes может быть каким угодно, как правило 50-60 бит, а функция его расширяет по специальному алгоритму до 512 бит и выдает.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 19:09
/.. убрал не относящиеся к делу комментарии ../
Добавлено через 1 час 37 минут
Цитата Сообщение от Sandra357 Посмотреть сообщение
В том то и суть, с чего я вообще этот сыр бор начала) Я в тестбенче проверяю сообщение, которое получила, и оно отличается. Если проверять на исходном сообщении "А", то
после расширения должно быть так (string)
4180000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000008000000 00000000
А у const char* получается
0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 00004180
То есть он букву А и единичный бит получил, дальше решил, что строка кончилась и вывел нули до конца 512 битной переменной...(в моем тестбенче она типа bit[511:0])
В общем добрался я до компилятора, потестировал твой пример. Все получается у меня так, как нужно.
Можно предположить, что это не из-за алгоритма как такового (или const char * в частности), а из-за ошибки возвращения указателя на уничтоженные данные. Вот твоя функция:
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
//принимаем от testbench-а (программа на systemverilog) сообщение, кот. нужно расширить, возвращаем сообщение того же типа уже расширенное
const char* md5_align (const char* mes) { 
    std::string data = mes; //копируем его в стринг
 
    ui64 bitLen = data.size() * 8;
    data += 0x80; // добавляем единичный бит
 
    size_t len = data.size();
 
    int rest = len % 64;
    rest = 56 - rest;
 
    if (rest < 0)
        rest = 64 + rest;
 
    data.resize(data.size() + rest); // добавляем нули, чтобы размер был 448
 
    string lengthData;
    lengthData.resize(8); //здесь будет размер исходного сообщения, записанный в 64 битах 
    for (size_t i = 0; i < 8; ++i) {
        lengthData[i] = (ui8)(bitLen >> i * 8);
    }
    
    data += lengthData; //добавляем эти 64 бит размера, получилось расширенное сообщение 512 бит
    
 /*!!!! Вот здесь ты получаешь указатель на внутренний буфер объекта data, 
    НО сразу после return этот объект будет уничтожен, а обращение по этому 
    указателю станет некорректным !!!*/
    const char *cstr = data.c_str(); // приводим к нужному типу, чтобы передать обратно в testbench
    return cstr;
}
Проблему описал в комментарии. Очень важно, чтобы ты это осознала и старалась избегать таких ошибок впредь.
Что касается функции, для своего теста я переделал ее так (убрал лишнее выделение динамической памяти и вышеописанную ошибку):
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
std::string md5_align(const char * mes)
{
    std::string data = mes; //копируем его в стринг
 
    uint64_t bitLen = data.size() * 8;
    data += '\x80'; // добавляем единичный бит
 
    size_t len = data.size();
 
    int rest = len % 64;
    rest = 56 - rest;
 
    if (rest < 0)
        rest = 64 + rest;
 
    data.append(rest, 0); // добавляем нули, чтобы размер был 448
 
    char lengthData[8] = {}; //здесь будет размер исходного сообщения, записанный в 64 битах
    for(size_t i = 0; i < 8; ++i)
    {
        lengthData[i] = (uint8_t)(bitLen >> i * 8);
    }
    data.append(lengthData, 8); //добавляем эти 64 бит размера, получилось расширенное сообщение 512 бит
 
    return data;
}
Теперь, чтобы получить строку в стиле С и передать ее в твой testbench, нужно сделать следующее:
C++
1
2
3
4
5
6
7
// Тестовую функцию назову testbench, чтобы было на что опереться, она принимает const char *
// Вызов
testbench(md5_align("A").c_str());
 
//либо так:
std::string data = md5_align("A");
testbench(data.c_str());
на твоих тестовых данных я получил именно последовательность:
41 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00
Алгоритм твой я не менял, только чуть оптимизировал. Следовательно дело в неверном возврате данных из функции.
0
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24
25.02.2015, 22:12  [ТС]
Большое спасибо, что столько времени уделяется)
Смотрите, что получается. Я переделала, как вы сказали. И добавила вывод размера, чтобы проверять полностью копирует он или опять до нулей.
Добавочная функция (у вас она testbench названа):
C++
1
2
3
4
5
6
7
const char* md5_to_tb(const char *str) {
    std::string mes = md5_align(str);
    const char* s = mes.c_str();
    size_t size = strlen(s);
    std::cout << "size of mes.c_str = " << size << "\n"; // выводит 2, а должен 64
    return mes.c_str();
}
Добавлено через 6 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
на твоих тестовых данных я получил именно последовательность:
А такую последовательность Вы получили именно при выводе const char* или все-таки стринг?

Добавлено через 22 минуты
Возможно, вы скажете, что по размеру не стоит проверять, но вывод из тестового окружения моего показывает тоже, что передалось только 4180.
Если интересно, вызов тестбенча (systemverilog программа) выглядит так:
C++
1
2
3
4
5
6
7
8
...
string str, ext_str;
bit [511:0] ext_mes;
bit [7:0] dop = 01000001; // записали букву А в 2чном виде
str = string'(dop); // преобразовали в тип стринг для передачи в си-функцию
ext_str = md5_to_tb(str); // вызов си-функции
ext_mes = ext_str; // преобразовываем в тип bit
$display("Padder : ext_mes hex= %h", ext_mes); // выводим на экран в 16чном формате
Выведенное сообщение выглядит так:
# Padder : ext_mes hex= 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 00004180
1
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 22:23
Цитата Сообщение от Sandra357 Посмотреть сообщение
А такую последовательность Вы получили именно при выводе const char* или все-таки стринг?
Без разницы.
Цитата Сообщение от Sandra357 Посмотреть сообщение
size_t size = strlen(s);
std::cout << "size of mes.c_str = " << size << "\n"; // выводит 2, а должен 64
К сожалению ты не внимательно читала предыдущие сообщения. Не нужно пользоваться strlen на такой строке! Она считает размер до первого нуля в последовательности. Все байты там на месте, коль скоро наша функция гарантирует их наличие.

Добавлено через 4 минуты
Да и функцию эту так нельзя описывать. Тут повторяется та же ошибка. mes - локальная переменная. Она уничтожится после выхода из области видимости функции и буфер, который вернула c_str "повиснет".
C++
1
2
3
4
5
6
7
const char* md5_to_tb(const char *str) {
   std::string mes = md5_align(str); // mes уничтожится после выхода из функции
   const char* s = mes.c_str();
   size_t size = strlen(s);
   std::cout << "size of mes.c_str = " << size << "\n"; // выводит 2, а должен 64
   return mes.c_str();
}
Ты бы сразу сказала, что эта функция на экспорт в другое окружение. В таком случае ее надо по-другому оформить, чтобы получить корректное поведение (хотя у меня остались сомнения, что вообще получится, что есть string на той стороне?).

Добавлено через 5 минут
Цитата Сообщение от Sandra357 Посмотреть сообщение
но вывод из тестового окружения моего показывает тоже, что передалось только 4180.
Ну ясно. Это потому, что тестовое окружение тоже пользуется нулем, как маркером конца строки. Можно мне ссылочку на документацию по твоему окружению? Какие там типы вообще возможны, мне бы узнать. Здесь в лоб похоже не решить задачу (у меня же это работало потому что я проверял в рамках С++, обычным циклом по строке с ограничением в 64 итерации).
0
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24
25.02.2015, 22:28  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Ты бы сразу сказала, что эта функция на экспорт в другое окружение
Да я не думала, что придется вглубь истории лезть) Надеялась, что есть функции копирования, которых я не знаю)
Это соответствие типов: (см чуть ниже таблицу mapping data types)

http://www.testbench.in/DP_07_DATA_TYPES.html

В sv стринг это тот же стринг, что и в си, но передавать си-программа стринг не может, только те типы, что на картинке, а в sv они преобразуются уже в другие
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 22:46
Лучший ответ Сообщение было отмечено Sandra357 как решение

Решение

Цитата Сообщение от Sandra357 Посмотреть сообщение
// преобразовываем в тип bit
Вот. А нет возможности как-то сразу вернуть из С-функции тип bit? По идее должны там быть средства, чтобы это организовать.

Добавлено через 3 минуты
Цитата Сообщение от Sandra357 Посмотреть сообщение
В sv стринг это тот же стринг, что и в си, но передавать си-программа стринг не может, только те типы, что на картинке, а в sv они преобразуются уже в другие
Не, это я понимаю. Я имел в виду, что если на стороне sv строка - это именно строка, т.е. нуль-терминированная последовательность, то ничего у нас не выйдет с ней. Мы упираемся в проблемы получения истинного размера, о которых писалось выше по ветке. Проблему концептуально можно решить только сменив тип на другой, который поддерживает такое свойство, как размер. Массив какой-нибудь или еще что. Вот тип bit должен подойти. Теперь надо разобраться как написать С-функцию так, чтобы sv потом понял что она возвратила bit.

Добавлено через 5 минут
Sandra357, почитал немного твои ссылки. Похоже bit тоже не подойдет. А вот Unpacked array похоже то, что нужно.
0
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24
25.02.2015, 22:48  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Теперь надо разобраться как написать С-функцию так, чтобы sv потом понял что она возвратила bit.
bit соответствует unsigned char в си...боюсь, мы упремся в ту же проблему...
А что, если возвращать указатель на массив int из 64 элементов?
Сейчас посмотрю, что получается
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 22:53
Sandra357, вот что-то на эту тему. Найти бы теперь как там размер проверить, чтобы меньше 64 нельзя было передать
А, вот. Ключевое слово для поиска "svOpenArrayHandle". Находит ссылки на форум systemverilog, но по здешним правилам их нельзя постить. Надеюсь сама сможешь разобраться

Добавлено через 1 минуту
Цитата Сообщение от Sandra357 Посмотреть сообщение
А что, если возвращать указатель на массив int из 64 элементов?
Да, я к этому же склоняюсь. Смотри, я выше обновил немного пост. Просто дописываю по мере нахождения информации
1
3 / 3 / 0
Регистрация: 02.01.2015
Сообщений: 24
25.02.2015, 22:56  [ТС]
DrOffset, спасибо большое за наводку! Целый день на меня потратили)) Буду разбираться)
1
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
25.02.2015, 22:58
Цитата Сообщение от Sandra357 Посмотреть сообщение
Целый день на меня потратили)) Буду разбираться)
Да не, просто заглядывал одним глазком время от времени. Если бы я работал с systemverilog сам, то намного быстрее бы подсказал
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.02.2015, 22:58

char operator[](unsigned short offset) const; // что означает const?
Собстенно вопрос уже озвучен :).

Ошибка: Cannot convert 'char const[18]' to 'const wchar_t *'
Unit1.cpp(59): E2034 Cannot convert 'char const' to 'const wchar_t *' Full parser context Unit1.cpp(55): parsing: void _fastcall...

Ошибка "значение типа "const char [81]" нельзя использовать для инициализации сущности типа "const unsigned char [61]"
Прошу помощи, так как раньше прога работала, сейчас решил вернуться и выдает ошибку: #pragma once #include...

Cannot convert 'const wchar_t *' to 'const char *'
HMODULE hMod=GetModuleHandle(NULL); if(!hMod) { } HRSRC hRes=FindResource(hMod,&quot;acc.dll&quot;,RT_RCDATA); if(!hRes){ } HGLOBAL...

Нулевые биты указанного числа
Форумчане, выручайте, нужно написать функцию, которая для заданного целого числа x вычисляет количество нулевых битов в этом числе (в коде...


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

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru