5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
|
||||||||||||||||
1 | ||||||||||||||||
Как сдвинуть указатель на double на 4 байта?17.08.2012, 00:38. Показов 7765. Ответов 15
Метки нет (Все метки)
Есть конструкция:
0
|
17.08.2012, 00:38 | |
Ответы с готовыми решениями:
15
как сдвинуть указатель Как сдвинуть указатель на несколько байт? Как сдвинуть указатель на следующую ячейку в массиве? Как внутри foreach сдвинуть указатель массива вперед? |
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
|
|
17.08.2012, 00:47 | 2 |
(double*)((char*)(*p) + 4)
И никому это не показывайте.
2
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
||||||
17.08.2012, 01:01 | 3 | |||||
0
|
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
|
|
17.08.2012, 01:14 | 7 |
Эм, ну можно сделать (int*)(*p)++; тогда *p, он же p[0], сдвинется на размер одного int.
Проблема в том, что у вас int четыре байта, а у кого-то другого он может быть равен двум. Или восьми. Потому-то и говорю, что с этим шаманством надо поаккуратнее. (Прокатило, таки lvalue.)
0
|
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
|
||||||
17.08.2012, 01:47 [ТС] | 8 | |||||
Дают вот такие примеры к заданию:
Код
Добавлено через 1 минуту По заданию, нужно именно на int сдвинуть. Это я вопрос так задал. Добавлено через 8 минут Там идея такая (упрощая), что создаётся динамический массив размером на несколько double и один int. В начало массива записывается int, потом указатель сдвигается на величину int и записываются значения double. Добавлено через 8 минут Вот так проходит: (double*)((int*)(*p) + 1); Через инкремент - никак.
0
|
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
|
|
17.08.2012, 01:49 | 9 |
Не по теме: Дично я считаю, что такие "оптимизации" до добра не доводят. Там больше времени потратится на эти преобразования для вытягивания длин и т. п.; я уж молчу про то, что этот массив надо потом как-то удалять (не забыв при этом всё посдвигать обратно). В общем это. Небольшой ликбез. Есть lvalue, есть rvalue. lvalue — это нечто, что объективно существует в памяти и сохраняется между вычислениями различных выражений. Например, это любая переменная. rvalue — это нечто, что сущестует только на время вычисления выражения (но оно тоже хранится в памяти, временно). В выражении x = x + 5; оба икса это lvalue, но само подвыражение (x + 5) — это rvalue. Его значение временно хранится в памяти, пока оно не будет записано в x. Но это не переменная. Инкремент увеличивает значение переменной. Он не может увеличить значение rvalue-величины, так как её формально нет в памяти, она умрёт как только закончится вычисление выражения. Приведение типов тоже даёт rvalue, поэтому инкремент не может его увеличить. В общем, к чему это я. Вместо ((int *)(p[i]))++; напишите p[i] = (int *)(p[i]) + 1; Должно помочь.
1
|
бжни
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
|
||||||
17.08.2012, 01:51 | 10 | |||||
1
|
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
|
|||||||||||
17.08.2012, 16:39 [ТС] | 11 | ||||||||||
Удаление там присутствует. Сложность только в правильном сдвиге была.
~OhMyGodSoLong~, если можно, ещё про это поясните. Компилятор не ругается на такое:
0
|
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
|
|
17.08.2012, 17:09 | 12 |
Дело в приоритетах. Приоритет у инкремента и приведения типов одинаковый, но есть ещё понятие ассоциативности. Есть левая ассоциативность и правая. От неё зависит, в каком порядке применяются операторы с одинаковым приоритетом.
Например, сложение левоассоциативно, так что выражение a + b + c + d + eтрактуется как ((((a + b) + c) + d) + e)то есть вычисляется слева направо. А вот присваивание правоассоциативно, так что выражение a = b = c = d = e = 2трактуется как a = (b = (c = (d = (e = 2))))то есть присваивания идут справа налево (выражение присваивания возвращает присвоенное значение). К правоассоциативным операторам относятся присваивания (и просто =, и всякие +=) и унарные операторы (среди них, в частности, и инкремент/декремент, а также приведение типов). Все остальные левоассоциативны. По этой причине (char*)p++;трактуется как (char*)(p++);То есть происходит инкремент p (на размер адресуемой величины, а не char), возвращается старое значение p и именно оно уже приводится к типу char*. Если же попробовать написать "правильные скобки": ((char*)p)++;то оно вообще не скомпилируется из-за рассказанных причин про lvalue: теперь приведение отрабатывает первым, но приведение типов возвращает rvalue-величину, которую инкремент не может увеличить.
1
|
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
|
|
17.08.2012, 19:00 | 14 |
Вот что происходит в этой строке: (char*)p++
1. Запоминается текущее значение переменной p типа double**. 2. p увеличивается на размер адресуемой величины (то есть double*, на 4/8 байт в зависимости от разрядности компьютера). 3. Постинкремент возвращает старое (теперь) значение переменной p. Это то значение типа double**, которое было сохранено на первом шаге. 4. Это значение приводится к типу char* и становится значением всего выражения «(char*)p++».
1
|
~ Эврика! ~
1256 / 1005 / 74
Регистрация: 24.07.2012
Сообщений: 2,002
|
|
17.08.2012, 19:45 | 16 |
Правила приоритетов остаются теми же самыми.
1. p увеличивается на размер адресуемой величины (то есть double*, на 4/8 байт в зависимости от разрядности компьютера). 2. Преинкремент возвращает новое? увеличенное значение переменной p (типа double**). 4. Это значение приводится к типу char* и становится значением всего выражения «(char*)++p».
1
|
17.08.2012, 19:45 | |
17.08.2012, 19:45 | |
Помогаю со студенческими работами здесь
16
Как сдвинуть указатель файла НА НАЧАЛО уже считанной строки? Сдвинуть биты в каждом байте циклически на число, содержащееся в двух старших битах байта Поменять местами 4 старших байта и 4 младших в числе double (указатели) как изменить этот код так , чтоб в нём появился Указатель типа double ? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |