23.02.2019 04:21, Mikhail Efremov пишет: > On Sat, 23 Feb 2019 01:48:30 +0300 Leonid Krivoshein wrote: >> 22.02.2019 23:51, Vladimir Didenko пишет: >>> пт, 22 февр. 2019 г. в 22:29, Leonid Krivoshein: >>>> Тут ко всему не очевидное поведение компилятора при работе с >>>> адресами, когда их складывают с целыми (много от чего зависит и в >>>> ряде случаев просто на ворнинги можно нарваться). Такой код в >>>> любом случае сразу переписывать на более безопасный, независимо от >>>> memcpy()/memmove(). Например, так: >>>> >>>> memmove(&_data.data[8], &data.data[9], _data.size - 9); /* если тип >>>> данных [unsigned] char */ >>>> >>> Вы глупость написали. Арифметика указателей и целых чисел вполне >>> определена и безопасна, если не выходить за границы массива. И еще - >>> запись p + 8 и &p[8] равносильны согласно стандарту языка C. > Более того, можно еще и &8[p] написать, совершенно корректная запись с > точки зрения синтаксиса языка :). Другое дело, что за такое в реальном > коде надо руки отрывать сразу. Согласен. Такого я не предлагал. >> И каково же её определение в разных стандартах языка C? А реализация >> в разных компиляторах? К примеру, согласно N1570 (6.5.6) над > В стандарте арифметика указателей описана вполне ясно. В актуальном, что я привёл? Или в каком-то другом? Раз возникают такие странные споры на почти пустом месте, значит, ясно не для всех одинаково. >> void-указателями такого не проделаешь, в отличие от gcc, который тоже >> ни один стандарт могёт. > Я не понял этой фразы и сравнения указателей с gcc. При чем тут > указатель на void? Размер объекта в этом случае не известен, разумеется > арифметика не работает. Моя фраза прозвучала вполне чётко: в этом месте gcc и действующий стандарт расходятся. gcc допускает сложение целого числа с указателем на void, принимая размер указываемого объекта равным одному байту. $ gcc -o v1 -DUSEVOID examle.c $ gcc -o v2 -DUSEVOID -DSAFEPTR examle.c examle.c: In function ‘main’: examle.c:21:12: warning: dereferencing ‘void *’ pointer   func(&base[6]);             ^ examle.c:21:7: warning: taking address of expression of type ‘void’   func(&base[6]);        ^ Пример во вложении. Теперь понятно, почему предлагаемая запись более безопасна? Вашу запись gcc проглотит, даже не поперхнувшись. В примере ещё и второе объяснение по объектам размером более одного байта: $ gcc -o i1 examle.c $ gcc -o i2 -DSAFEPTR examle.c ./i1 24 6 $ ./i2 24 6 Вы прибавляете к адресу целое число, которое является чем? Разницей в адресах или индексах? Я вот стандарты не штудирую, в голове их не держу, и в моей привычке такой записи никаких неоднозначных толкований быть не может. Просто пишите так, и не ошибётесь никогда. >> Кстати, именно с такой арифметикой на более >> старом gcc на ворнинги нарывался и всегда их сразу выправлял. Нет, >> лучше об этом не думать, а писать сразу так, чтобы работало везде. > Полагаю, что предупреждения были о чем-то другом. Может быть, не помню уже. Попробуйте откатить этот commit: http://git.altlinux.org/gears/p/propagator.git?p=propagator.git;a=commitdiff;h=d2866d5d21fd1fe31ebcbbf82490fbbb25de834b Более подходящего примера сходу не нахожу. -- Best regards, Leonid Krivoshein.