Приведение типов массива int к указателю на символ и чтение промежуточных значений двух индексов - PullRequest
0 голосов
/ 31 марта 2019

Предположим, что в памяти есть целочисленный (по 4 байта каждый) массив

memory location:  10   14   18   22
value:          [ 1 ][ 2 ][ 3 ][ 4 ]

если я использую символьный указатель 'p', как показано

#include <iostream>
using namespace std;
int main()
{
    int a[] ={1,2,3,4};
    char *p = (char*)a; //character pointer
    cout<<(int)(*(p+0))<<endl;
    cout<<(int)(*(p+1))<<endl; //point A
    cout<<(int)(*(p+2))<<endl;
    cout<<(int)(*(p+4))<<endl;
    return 0;
}

вывод

1
0
0
2

Почему я получаю 0 вместо значения мусора (рассмотрим в пункте A, мы должны получить целочисленное значение, равное последним 3 байтам [i] + первого байта a [1]). Я только начинающий, извините, если я сделал какую-то глупую ошибку

что я хочу сделать, так это взять

a[0] = 2147483647
a[1] = 2147483646
then in bits 
a[0] = 11111111 11111111 11111111 11111111
a[1] = 11111111 11111111 11111111 11111110
taking a char pointer p = (int*)(&a[0] + 1)
should hold 11111111 11111111 11111111 (<-from a[0], from a[1]->) 11111111
hence (int) *p should be again 2147483647

Ответы [ 3 ]

1 голос
/ 31 марта 2019

Почему я получаю 0 вместо значения мусора

Почему вы думаете, что 0 не является значением мусора?Нет никакой гарантии, что значение мусора не равно 0. 0 является совершенно допустимым значением для мусора.

Тем не менее, вы не печатаете ничего, что имеет значение мусора.Между элементами массива нет заполнения, и сам int не содержит заполнения, и в массиве нет неинициализированных объектов.

int состоит из одного или нескольких байтов.В вашей системе это 4 байта.p+0 указывает на первый байт, p+1 указывает на второй байт, p+4 указывает на первый байт второго целого числа.Если ни первый, ни второй байт не имеют значения 0, тогда целое число не может представлять 1.

чтение значений между двумя индексами

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

(рассмотрим в точке A, мы должны получить целочисленное значение, равное последним 3 байтам первого байта [i] + первого [1]).

Вы можете добиться этого следующим образом:

int i;
std::memcpy(&i, p + 1, sizeof i);
std::cout << i;
1 голос
/ 31 марта 2019

Почему я получаю 0 вместо значения мусора (рассмотрим в пункте A, мы должны получить целочисленное значение, равное последним 3 байтам [i] + первого байта [1])

Потому что написанный вами код этого не делает.У вас есть массив int s, к которому вы обращаетесь с помощью указателя на символ.Итак, *(p+0) собирается дать вам первый байт.*(p+1) второй и тд.Вы приводите к int не нужно (оно только конвертирует полученное число в int), это происходит слишком поздно.Вам необходимо изменить значение указателя:

std::cout << *(int*)(p+1);

Обратите внимание, что это неопределенное поведение.

0 голосов
/ 31 марта 2019

Во-первых, 0 - это абсолютно правильное «значение мусора».

Но это спорный вопрос, потому что вы на самом деле не конвертируете 4 байта в целое число & mdash; Вы извлекаете один байт, а затем конвертируете его в целое число. Вам придется переосмыслить char* как int* (затем разыменовать его), чтобы сделать то, что вы говорите, что делаете, и тогда мы придем к:

Неопределенное поведение

Манипулирующая память, подобная этой, имеет неопределенное поведение . Все может произойти, если вы попытаетесь сделать вид, что не int является int.

Это не просто стандарт или пуританство, или педантизм. Это правда и имеет реальные практические результаты, такие как тот, который вы видели.

Процесс перевода абстрактной программы, которую вы описали с использованием слов C ++, в реальную практическую программу, понятную компьютеру, невероятно сложен . Компилятор не берет ваши строки по одной и просто наивно переписывает их в код, который одинаков, но на машинном языке. Он читает весь ваш исходный код, понимает, что вы хотите, чтобы программа, которую он описывает для вас, затем создает совершенно новую программу на совершенно другом, не связанном, отдельном языке, который дает тот же результат. Чтобы сделать это быстро, нужно также несколько ярлыков.

Когда вы пишете программу, поведение которой не определено, вы нарушаете этот процесс. Вы просто не можете предположить, что «мы должны получить целочисленное значение, равное 3 последним байтам первого байта [i] + a [1]». Вероятно, это было более вероятно в 70-е годы, но компьютеры действительно сложные, современные, а не старинные.

Короткая версия: не делайте этого.

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