Представление массива Char в памяти - PullRequest
0 голосов
/ 04 января 2019

Я пытался выполнять побитовые операции над массивом символов, как если бы он был целым числом, по существу обрабатывая байты как непрерывную область в памяти.Приведенный ниже код иллюстрирует мою проблему.

char *cstr = new char[5];
std::strcpy(cstr, "abcd");  

int *p = (int *)(void *)cstr;
std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n";
std::cout << sizeof(*p) << "\n";

(*p)++;
std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n";

Получается следующий вывод:

1684234849 0x55f046e7de70
abcd 0x55f046e7de70
4
1684234850 0x55f046e7de70
bbcd 0x55f046e7de70

Краткое объяснение кода и его работы (на мой взгляд):

Я инициализирую cstr с помощью "abcd"

char *cstr = new char[5];
std::strcpy(cstr, "abcd");  

Я указываю p на адрес cstr и указываю, что хочу, чтобы он был int

int *p = (int *)(void *)cstr;

Я проверяю, что pуказывая, где он должен и что он занимает 4 байта

std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n";
std::cout << sizeof(*p) << "\n";

Затем я увеличиваю целое число по адресу p, указывающему на

(*p)++;

Так что теперь, так как "abcd" является смежнымблок из 32 битов в памяти, увеличение на 1 должно привести к появлению "abce".Вместо этого код успешно увеличивает целое число, но оставляет массив char как «bbce».Эта последняя часть проверяет новые значения целых чисел и cstr

std::cout << *p << " " << p << "\n";
std::cout << cstr << " " << (void *)cstr << "\n"

Это ожидаемое поведение?

PS: я скомпилировал код на машине linux с помощью этой команды: g ++ main.cpp-o main.

file main

выдает следующий вывод: "1: 64-битный общий объект LSB ELF, x86-64, версия 1 (SYSV), динамически связанный, интерпретатор / lib64 / ld-linux-x86-64.so.2, для GNU / Linux 3.2.0 "

1 Ответ

0 голосов
/ 04 января 2019

x86-64 ЦП (как и ваш) хранят младший байт многобайтовых целых чисел с самым низким адресом памяти.Таким образом, увеличение целого числа, которое соответствует «abcd», приводит к увеличению его младшего байта, который сначала сохраняется в памяти.Это преобразовало символ «а» в «б».То, как этот код ведет себя, очень зависит от того, как процессор кодирует целые числа и строки, и ваши ожидания того, что этот код будет делать, должны учитывать эти детали.

Чтобы ожидать строку "abce", вы должнысделайте много предположений:

  1. Вы должны ожидать, что целые числа займут 4 байта.
  2. Вы должны ожидать, что младший байт будет храниться последним.
  3. Вынужно ожидать, что кодировка символа «e» будет на единицу больше, чем кодировка символа «d».
  4. Вы должны ожидать, что увеличение «d» до «e» не будет переполненоесли рассматривать его как целочисленное увеличение со знаком.

Некоторые из них являются разумными предположениями, а некоторые нет, но если у вас нет разумных оснований для всех этих предположений, ваши ожидания не оправдаются.

Это ожидаемое поведение?

Это то, чего ожидают люди, знакомые с вашей платформой.Но, как правило, легко избежать таких предположений, поэтому лучший совет - не полагаться на них.Предположение 3 часто неизбежно и разумно на всех современных платформах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...