2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1, 2, 3, 4  След.
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение31.08.2015, 07:04 
В stdint.h off_t не упоминаются. И ssize_t не упоминаются.
Пример записи в stdint.h
Используется синтаксис C
//<stdint.h>
/* Limit of `size_t' type.  */
# if __WORDSIZE == 64
#  define SIZE_MAX      (18446744073709551615UL)
# else
#  define SIZE_MAX      (4294967295U)
# endif
 

В limits.h off_t тоже не упоминаются.
Используется синтаксис C
//<limits.h>
/* Minimum and maximum values a `signed int' can hold.  */
#  define INT_MIN   (-INT_MAX - 1)
#  define INT_MAX   2147483647
 

В stdlib.h тоже нет подходящих.
Файлы сложные, многое я в них не понимаю.

Если в функцию из предыдущего моего сообщения вместо off_t всюду
подставить int, т. е. сделать преобразование в int-число, и
применить INT_MIN и INT_MAX, то да, работает. Может, соответствующих
констант для off_t не существует, может, про них забыли.

И в любом случае всё же прошу ответить на вопрос: нет ли в этом коде подвоха
Используется синтаксис C
    off_t MY_MIN_OFF_T, MY_MAX_OFF_T = 1;

    while((MY_MAX_OFF_T << 1) > 0){ MY_MAX_OFF_T = (MY_MAX_OFF_T << 1) + 1;}
    MY_MIN_OFF_T = -MY_MAX_OFF_T;
 

И можно ли последнюю строку заменить на эту, чтоб еще максимальное
отрицательное число взять?
Используется синтаксис C
    MY_MIN_OFF_T = -MY_MAX_OFF_T - 1;
 

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение31.08.2015, 07:37 
oleg_2 в сообщении #1049406 писал(а):
нет ли в этом коде подвоха


Да, здесь "внаглую" используется переполнение знакового числа - а стандарт как мы помним хочет попасть под все возможные реализации этого дела и объявляет такие вещи как UB.
Паниковать не стоит - во первых - вряд ли вы когда нибудь столкнётесь с аппаратной начинкой где сей код будет неверным - дополнение до двух плотно вошло в мир современных компьютеров. Однако, если охота прямо таки перестраховаться - просто выделите такой код в "платформенно-зависимые файлы" (чисто для красоты пока, т.к. сомневаюсь что когда либо потребуется действительно их в таком ключе использовать). Кроме того здесь сам этот код в рантайме вычисляющий что-то просто не нужен - идёте, смотрите что такое off_t и делаете на основании этого пару своих дефайнов.

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение31.08.2015, 08:06 
Используется синтаксис C
  После последнего прохода цикла:
    |0|1|1|1|1|1|   MY_MAX_OFF_T

    while((MY_MAX_OFF_T << 1) > 0) -условие цикла

    |0|1|1|1|1|1|  (MY_MAX_OFF_T << 1) -операция
    |1|1|1|1|1|0|  -результат операции < 0, цикл не выполняется.
 

Непонятно, почему простой сдвиг на 1 бит - UB?
Или после сдвига проверка на "больше нуля" - UB?

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение31.08.2015, 08:18 
oleg_2 в сообщении #1049409 писал(а):
Непонятно, почему простой сдвиг на 1 бит - UB?


Почитайте https://ru.wikipedia.org/wiki/%D0%94%D0 ... B%D0%B0%29
Обратите внимание, что возможны теоретически разные способы представления отрицательных чисел.

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение02.09.2015, 09:25 
aa_dav в сообщении #1049407 писал(а):
Да, здесь "внаглую" используется переполнение

Вот нашел.
http://www.viva64.com/en/d/0225/print/
This is how the C++11 standard describes shift operators' work:

2. The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are
zero-filled. If E1 has an unsigned type, the value of the result is E1 * 2^E2,
reduced modulo one more than the maximum value representable in the result type.
Otherwise, if E1 has a signed type and non-negative value, and E1*2^E2 is
representable in the result type, then that is the resulting value; otherwise,
the behavior is undefined.

Используется синтаксис C
    off_t max = 1;
    while((max << 1) > 0){ max = (max << 1) | 1;}
 

Как я понимаю, в данном случае E1*2^E2 не представимо типом результата, т. к.
становится отрицательным, и, стало быть, undefined behavior. Обложили со всех
сторон.
aa_dav в сообщении #1049407 писал(а):
идёте, смотрите что такое off_t и делаете на основании этого пару своих дефайнов

Я даже на своем компьютере не нашел, что такое off_t, сложно. Надо
чтоб само собой работало, без помощи человека.

Вы, venco, предложили использовать беззнаковый
тип того же размера. Но я же заранее не знаю этот тип, это может быть long int
или long long int. А для off_t нет сопряженного типа uoff_t.

А если через sizeof? Примерно так:
Используется синтаксис C
    int i, bits = sizeof(off_t) * 8;
    off_t max = 1;
    for(i=0; i < (bits - 2); i++){ max = (max << 1) | 1;}
 


Офтоп (а в настоящем офтопе код не отображается)
Я даже вспомнил случай с UB при переполнении, он заключается в том, что в
этом куске кода (ниже), при компиляции с -O3, если s переполняется
и становится отрицательным, то проверка if(s < 0) не работает. Без
оптимизации работает. Наверно, это и есть маленькое UB.
Используется синтаксис C
    s=0;
    while(*p1>='0' && *p1<='9'){
        s = (s * 10) + ((*p1++) - '0');
    }
    if(s < 0){}
 

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение02.09.2015, 14:08 
Аватара пользователя
oleg_2 в сообщении #1049885 писал(а):
А для off_t нет сопряженного типа uoff_t.

size_t?

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение12.09.2015, 15:20 
oleg_2 в сообщении #1049885 писал(а):
А если через sizeof? Примерно так:
Используется синтаксис C
int i, bits = sizeof(off_t) * 8;
off_t max = 1;
for(i=0; i < (bits - 2); i++){ max = (max << 1) | 1;}
 
В стандартных заголовках написали бы что-то вроде:
Используется синтаксис C
#define MAX_OFFSET ( ( ( off_t )1 << ( sizeof( off_t ) * 8 - 1 ) ) - 1 )

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение12.09.2015, 16:24 
Интересно, а поддерживает ли язык С числа с несколькими знаковыми битами? Например с двумя знаковыми битами числа могут возникать как результат умножения двух знаковых чисел в прямом коде, если не применять специальные меры (впрочем везде применяются). Для таких кодировок метод с sizeof напрямую не подойдёт. Ладно, это фантазия. :-)

А в заголовках думаю лучше использовать такое определение (не трогать знаковый бит вообще):
Используется синтаксис C
#define MAX_OFFSET ( ( ( ((off_t)1 << (sizeof(off_t) * 8 - 2)) - 1) << 1) | 1)

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение13.09.2015, 07:17 
В стандартных заголовках так и пишут:
Используется синтаксис C++
#define INT_MAX         2147483647
#define INT_MIN         (-INT_MAX-1)
 

Там где невозможно сделать platform independent code его просто не делают и всё.

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение14.11.2015, 15:14 
Аватара пользователя
oleg_2 в сообщении #1048844 писал(а):
Указатель p1 может на один байт выйти за край массива вправо, и при этом
еще и использоваться в адресных выражениях типа (p1 < p2).
случится, то плохо.

на практике проблем не будет, даже если выйдете на несколько байт. в теории указатель может вылезти не только за пределы массива, но и адресного пр-ва - т.е. переполниться и тогда неравенство не сработает. собственно это и есть unpredictable behavior, т.к. массивы не могут заканчиваться последним байтом адр. пр-ва и начинаться 0-вым.

oleg_2 в сообщении #1048844 писал(а):
А если, скажем, компилятор на операцию с указателем вставит
какую-нибудь защиту от переполнения регистра, и если такое переполнение

Не вставит. В С++ указатели - это целые числа, с ними можно свободно работать, не боясь выхода за пределы массивов, что на практике часто используется.

В частности, можно конвертировать указатель в число и назад примерно следующей конструкцией:

int i = (char *)p - (char *)NULL;
char *p = (char *)NULL + i;

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение14.11.2015, 18:04 
bondkim137, пожалуйста, перечитайте всё обсуждение. Тут было сказано больше, чем просто "будут проблемы или нет".
И не давайте откровенно вредных советов, типа сохранения указателя в int.

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение14.11.2015, 18:06 
Аватара пользователя
venco в сообщении #1073419 писал(а):
И не давайте откровенно вредных советов, типа сохранения указателя в int.

А что, не влезет?

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение14.11.2015, 18:47 
Munin в сообщении #1073421 писал(а):
venco в сообщении #1073419 писал(а):
И не давайте откровенно вредных советов, типа сохранения указателя в int.

А что, не влезет?
В современных условиях с большой вероятностью не влезет. На 64-битных платформах int часто имеет размер 32 бита.

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение14.11.2015, 21:08 
Аватара пользователя
venco в сообщении #1073419 писал(а):
И не давайте откровенно вредных советов, типа сохранения указателя в int.

Я Вас прошу не корючкотворствовать, понятно, что в 64-разрядных приложениях для подобных транзитивных операций необходимо применять 64-х разрядный int.

И я нисколько не поддержу Вас в том, что сериализация указателя в целое число - идея вредная. Указатели, как и целые числа, упорядочены и аддитивны (через целые числа) что позволяет работать с ними, как ключами различных структур - в частности, деревьев и хешей, расчитывать по указателям размеры частей массивов, экстрполировать эти данные для вычислений (в том числе нелинейных) указателей и т.д. и т.п.

-- 14.11.2015, 21:21 --

venco в сообщении #1049090 писал(а):
По стандарту переполнение в арифметике со знаковыми числами - undefined behavior. И тоже никто не парится. Хотя недавно оптимизатор GCC так улучшили, что он как раз и сделал то, про что я писал - выкинул кусок кода, в котором было переполнение с int.


Можно по-подробнее? Какой кусок кода выкинули? На моем веку в C++ знаковое представление целых чисел было всегда дополнением до двойки - другой экзотики никогда не встречал. Тогда сложение и вычитание знаковых и беззнаковых чисел без насыщения никак не отличаются. И на практике все этим пользуются.

-- 14.11.2015, 21:29 --

 
 
 
 Re: СИ. Указатели. Можно ли к указателю прибавить любое число?
Сообщение14.11.2015, 22:09 
bondkim137 в сообщении #1073461 писал(а):
venco в сообщении #1073419 писал(а):
И не давайте откровенно вредных советов, типа сохранения указателя в int.

Я Вас прошу не корючкотворствовать, понятно, что в 64-разрядных приложениях для подобных транзитивных операций необходимо применять 64-х разрядный int.

И я нисколько не поддержу Вас в том, что сериализация указателя в целое число - идея вредная. Указатели, как и целые числа, упорядочены и аддитивны (через целые числа) что позволяет работать с ними, как ключами различных структур - в частности, деревьев и хешей, расчитывать по указателям размеры частей массивов, экстрполировать эти данные для вычислений (в том числе нелинейных) указателей и т.д. и т.п.
Проблема в том, что выбранный вами метод преобразования в стандарте определён как "undefined behavior", а какие из этого могут последовать проблемы, в этой теме как раз и обсуждалось.
А правильный по стандарту метод -
Код:
uintptr_t address = reinterpret_cast<uintptr_t>(ptr)


bondkim137 в сообщении #1073461 писал(а):
venco в сообщении #1049090 писал(а):
По стандарту переполнение в арифметике со знаковыми числами - undefined behavior. И тоже никто не парится. Хотя недавно оптимизатор GCC так улучшили, что он как раз и сделал то, про что я писал - выкинул кусок кода, в котором было переполнение с int.


Можно по-подробнее? Какой кусок кода выкинули?
Например, в коде:
Используется синтаксис C++
#include <assert.h>

int foo(int a) {
  assert(a+100 > a);
  printf("%d %d\n",a+100,a);
  return a;
}

int main() {
  foo(100);
  foo(0x7fffffff);
}
 

Здесь на некоторых новых версиях gcc, которые слишком строго следуют букве стандарта языка, не срабатывал assert(). Т.к. по стандарту переполнениые знаковых целых - "undefined behavior", оптимизатор выкинул проверку и диагностику, которую проверка должна вызвать. Так вот многие операции с указателями на разные объекты или массивы по стандарту тоже - "undefined behavior", и то, что они сейчас работают - следствие доброты авторов компиляторов. Они пока прощают такое, но т.к. это мешает оптимизатору, могут и закрутить гайки в будущем.

 
 
 [ Сообщений: 60 ]  На страницу Пред.  1, 2, 3, 4  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group