2017-01-11 4 views
-3

Я готовлюсь к предстоящему экзамену, когда я наткнулся на это:Значение * (& a - i) в цикле for. Это умножение?

char a = 'a'; 
char b = 'b'; 
int ai[] = { 1, 2 }; 
int i = 0; 

Предположим, что размер слова составляет 32 бита, что ИНТ составляет 32 бита, и что распределение памяти производятся в обратном порядке к декларации, начинающиеся с адреса. 68.

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

for (i = 0; i < 8; i++) 
    *(&a – i) = 'z'; 

Это может показаться странным, но я новичок в C, и это первый раз, когда я видел умножения для цикла. Объяснение этому для цикла и умножения, примененного к нему, было бы оценено.

+3

'* (& аи) '- ужасная идея, учитывая код. –

+8

Это не умножение, то есть разыменование указателя. –

+0

Нет умножения, это унарный оператор разыменования указателя префикса. Вам нужно изучить основы C. – unwind

ответ

1

Я думаю, мы можем предположить, что это теоретический вопрос, который, учитывая дополнительные предположения, не определенные в вопросе (т. Е. Порядок байтов, заполнение) - вопрос отвечает. Но, как указывает @chux, существуют стандарты против такого поведения. Ибо, если это разрешено, код приводит к повреждению памяти стека. В качестве вопроса экзамена на самом деле вы спрашиваете диаграмму, какая память повреждена.

Если я интерпретировать вопрос правильно, то возможно представление памяти (предполагая, что целые числа являются LSB, есть 1 байт заполнения, и в обратном порядке для объявлений):

| Addr | Value | Desc | | ---- | ----- | ------------------------------ | | 55 | 0x00 | // int i = 0; | | 56 | 0x00 | | | 57 | 0x00 | | | 58 | 0x00 | | | 59 | 0x01 | // int ai[] = { 1, 2 }; | | 60 | 0x00 | | | 61 | 0x00 | | | 62 | 0x00 | | | 63 | 0x02 | | | 64 | 0x00 | | | 65 | 0x00 | | | 66 | 0x00 | | | 67 | 0x62 | // char b = 'b'; | | 68 | 0x61 | // char a = 'a'; |

петля, раскатывают, имеет значение:

[68] = 0x7a; // 'z'; [67] = 0x7a; // 'z'; [66] = 0x7a; // 'z'; [65] = 0x7a; // 'z'; [64] = 0x7a; // 'z'; [63] = 0x7a; // 'z'; [62] = 0x7a; // 'z'; [61] = 0x7a; // 'z';

Так воспоминания представляют переменными, а, б и частей [] массива аи будет поврежден. (Инкорпорейтед @chux замечания о порядке байт. Кроме того, я скорректировал порядок, в котором элементы аи [] появляется как на @chux и комментарии @Peter A. Schneider.)

| Addr | Value | Desc | | ---- | ----- | ----------------------------------------- | | 55 | 0x08 | // int i = 8; | | 56 | 0x00 | | | 57 | 0x00 | | | 58 | 0x00 | | | 59 | 0x01 | // int ai[] = { 0x7a7a0001, 0x7a7a7a7a }; | | 60 | 0x00 | | | 61 | 0x7a | | | 62 | 0x7a | | | 63 | 0x7a | | | 64 | 0x7a | | | 65 | 0x7a | | | 66 | 0x7a | | | 67 | 0x7a | // char b = 'z'; | | 68 | 0x7a | // char a = 'z'; |

+0

Конечно, '59 | 0x02 | // int ai [] = {1, 2};' is amess. Я бы ожидал '59 | 0x01 ... 'Комментарий' // int ai [] = {0x02007a7a, 0x7a7a7a7a}; 'выглядит неправильно, несовместимо endian. Предложите« предполагать, что целые числа - это LSB »->« если целые числа малозначительны » – chux

+0

@chux прав: хотя вопрос определяет что распределение стека продолжается в сторону меньшего адреса s, в результате чего определенные объекты, находящиеся в памяти в обратном порядке объявления, * массивы являются составными, но единственными объектами *, члены которых расположены в порядке, указанном стандартом. В частности, адрес элементов массива может * всегда * вычисляться путем * добавления * индекса к адресу первого элемента, который численно равен адресу массива. Следовательно, элемент * first * (а не второй) 'ai' имеет в нем где-то 0x02 байт. Кстати, очень ясный ответ в противном случае. –

+1

Чтобы разработать, я думаю, что макет памяти, который вы указали в первой таблице для массива // int ai [] = {1, 2}; 'обращен: он должен быть * 0x01 * по адресу 59 для' ai [0] 'и 0x02 по адресу 63 для' ai [1] '. Во второй таблице, следовательно, комментарий неправильный: он должен быть '// int ai [] = {0x7a7a0002, 0x7a7a7a7a};' потому что 'ai [0]' находится на нижнем адресе, независимо от endianness. Здесь этот адрес равен 59 с (зависимым от него) содержимым 0x02, –

3

Это не умножение, это разыменование указателя. Однако *(&a – i) - это уже неопределенное поведение в момент i > 0. В вашем конкретном вопросе, однако, где есть единороги, а UB ушел в прошлое, и где вы должны предположить, что распределения переменных выполняются в обратном порядке, они объявлены и нет дополнения, что бы перезаписать переменные b и ai.

+1

Ну, это неопределенное поведение * при любых обстоятельствах *. Конечно, поведение, охватываемое под этим термином, включает переписывание значений, которые происходят чтобы компиляторы могли просто игнорировать весь код после этого выражения и т. д., и сделали это, например, когда было нарушено строгое сглаживание (и намерение программиста было намного яснее). –

+1

@ PeterA.Schneider Very true, я просто отвечаю на вопрос бессмысленного экзаменационного вопроса. –

Смежные вопросы