LINUX.ORG.RU

История изменений

Исправление aureliano15, (текущая версия) :

И где здесь про генерацию бреда? По-моему, в стандарте чётко прописаны 3 действия, из которых разработчики компиляторов могут выбрать любое

То, где можно «ignore the situation with unpredictable results».

См. мой UPD к верхнему посту:

И всё. Ни о каком «что хочешь» в стандарте речи не идёт. Вот тут мне в каментах подсказали, что «with unpredictable results» обозначает «что хочешь». Но на самом деле это обозначает лишь то, что результаты могут быть непредсказуемыми, а совсем не то, что компилятор может делать всё, что угодно (хотя разработчикам таких компиляторов подобная трактовка очень удобна).

Ну и тот же человек считает, что «это notes», а значит неважно, что там написано. Но т. н. неопределённое поведение при переполнении целого — вообще example из того же пункта:

EXAMPLE An example of undefined behavior is the behavior on integer overflow.

И больше я нигде никаких упоминаний об ub при арифметическом переполнении не нашёл. Про переполнение при сдвигах — нашёл. А в других случаях — нет. Но все почему-то на этот example ссылаются.

Например, если указатель где-либо разыменовывается, ситуацию, что он будет равен NULL, можно проигнорировать и все дальнейшие провери на неё выбросить.

Стоп. Проверка неопределённым поведением не является. Неопределённым поведением является разыменование. Если компилятор учитывает это разыменование, чтобы удалить проверку, то это никак не игнор, а наоборот учёт такого поведения. А значит этот вариант отпадает. А то так можно договориться до того, что обматюгать кого-то на форуме — это то же самое, что и проигнорировать его. Типа я тебя игнорирую, поэтому могу обматюгать, но т. к. на самом деле это был игнор, то можешь считать, что я никого не обматюгал.

Он утверждает, что A[B] — это то же, что *((A + B)) Но где он утверждает обратное, про приведение арифметики указателей, наоборот, к массивам?

Он утверждает, что если 2 указателя указывают на элементы 1 массива или на элемент, находящийся сразу после массива, то они могут быть приведены к массиву. Иначе поведение не определено, т. е. ничем не лучше 0. См. п. 6.5.6 (8-9):

8 When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

9 When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. If the result is not representable in an object of that type, the behavior is undefined. In other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of an array object, the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t. Moreover, if the expression P points either to an element of an array object or one past the last element of an array object, and the expression Q points to the last element of the same array object, the expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the expression P points one past the last element of the array object, even though the expression (Q)+1 does not point to an element of the array object. 106)

Кроме того, даже без вычитания, любое разыменование недействительного указателя (даже не 0) — ub, как я уже говорил.

Исходная версия aureliano15, :

И где здесь про генерацию бреда? По-моему, в стандарте чётко прописаны 3 действия, из которых разработчики компиляторов могут выбрать любое

То, где можно «ignore the situation with unpredictable results».

См. мой UPD к верхнему посту:

И всё. Ни о каком «что хочешь» в стандарте речи не идёт. Вот тут мне в каментах подсказали, что «with unpredictable results» обозначает «что хочешь». Но на самом деле это обозначает лишь то, что результаты могут быть непредсказуемыми, а совсем не то, что компилятор может делать всё, что угодно (хотя разработчикам таких компиляторов подобная трактовка очень удобна).

Ну и тот же человек считает, что «это notes», а значит неважно, что там написано. Но т. н. неопределённое поведение при переполнении целого — вообще example из того же пункта:

EXAMPLE An example of undefined behavior is the behavior on integer overflow.

И больше я нигде никаких упоминаний об ub при арифметическом переполнении не нашёл. Про переполнение при сдвигах — нашёл. А в других случаях — нет. Но все почему-то на этот example ссылаются.

Например, если указатель где-либо разыменовывается, ситуацию, что он будет равен NULL, можно проигнорировать и все дальнейшие провери на неё выбросить.

Стоп. Проверка неопределённым поведением не является. Неопределённым поведением является разыменование. Если компилятор учитывает это разыменование, чтобы удалить проверку, то это никак не игнор, а наоборот учёт такого поведения. А значит этот вариант отпадает. А то так можно договориться до того, что обматюгать кого-то на форуме — это то же самое, что и проигнорировать его. Типа я тебя игнорирую, поэтому могу обматюгать, но т. к. на самом деле это был игнор, то можешь считать, что я никого не обматюгал.

Он утверждает, что A — это то же, что *((A + B)) Но где он утверждает обратное, про приведение арифметики указателей, наоборот, к массивам?

Он утверждает, что если 2 указателя указывают на элементы 1 массива или на элемент, находящийся сразу после массива, то они могут быть приведены к массиву. Иначе поведение не определено, т. е. ничем не лучше 0. См. п. 6.5.6 (8-9):

8 When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

9 When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header. If the result is not representable in an object of that type, the behavior is undefined. In other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of an array object, the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t. Moreover, if the expression P points either to an element of an array object or one past the last element of an array object, and the expression Q points to the last element of the same array object, the expression ((Q)+1)-(P) has the same value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the expression P points one past the last element of the array object, even though the expression (Q)+1 does not point to an element of the array object. 106)

Кроме того, даже без вычитания, любое разыменование недействительного указателя (даже не 0) — ub, как я уже говорил.