LINUX.ORG.RU

Ответ на: комментарий от sambist

++i: Префиксный инкремент(декремент) возвращает увеличенное значение как результат операции. Является l-value.

i++: Постфиксный инкремент(декремент) возвращает старое значение как результат операции. Является r-value.

Почитай какого-нибудь Липпмана, там всего-то полтора абзаца проэто написано.

grondek
()
Ответ на: комментарий от sambist

++а разворачивается в (а = а+1)

Нет, ++ это вполне себе оператор. Правда унарный.
Нельзя говорить, что тут что-то «разворачивается». Это оператор, а не пища для препроцессора.

Stahl ★★☆
()
Ответ на: комментарий от grondek

i++: Постфиксный инкремент(декремент) возвращает старое значение как результат операции. Является r-value.

Ну ок, вернул он а, получилось а = а. Почему после всего этого он а не увеличит на единицу?

sambist ★★
() автор топика
Ответ на: комментарий от sambist

Нет, здесь не a=a, здесь такой порядок:

- выполняем a++ => создаем временный объект, в который записываем старое значение (10), потом увеличиваем a, в a теперь 11.

- возвращаем значение во временном объекте из операции a++. Это значение 10.

- выполняем операцию =. Значение из временного объекта (а у нас там записано 10) копируем в a.

- Вуаля! a = 10

grondek
()
Последнее исправление: grondek (всего исправлений: 2)
Ответ на: комментарий от sambist

Часто, кстати, предпочтительнее использовать префиксную форму из-за того, что в ее случае не создается временный объект.

grondek
()

В Си кстати тоже самое)

Потому как это есть постфиксная форма.

То есть, a сначала присваивается, а потом инкрементируется.

Так что никакого UB)

И a += 1 тебе в помощь, если что ;-)

Twissel ★★★★★
()
Последнее исправление: Twissel (всего исправлений: 1)
Ответ на: комментарий от sambist

Жесть

Почему? Вроде ж никто не обещал, что инкремент/декремент выполняется гарантированно до или после присваивания?

А так-то на самом деле всё логично, потому что a = a++ по своей сути — бессмысленная операция, не? Если бы ты хотел увеличить a, написал бы просто a++. Но ты написал a = a++, и что должен был делать компилятор?

А еще, по-моему, тут замешаны т. н. "точки следования", и тогда это похоже на UB. Но могу ошибаться.

Kiborg ★★★
()
Ответ на: комментарий от Shadow1251

Это почему вдруг? Согласился бы если бы было а++, но тут значение дальше не вернется, пока ++ не вычислится.

sambist ★★
() автор топика
Ответ на: комментарий от Kiborg

Пример 3. Неопределённое поведение.

i = i++ Указанное выражение не содержит ни одной точки следования, поэтому компилятор не может определить порядок вычисления операторов, соответствующий стандартам. Поведение зависит от реализации компилятора.

Так что это убэ походу.

sambist ★★
() автор топика
Ответ на: комментарий от sambist

Мне уже страшно использовать эту библиотеку.

warehouse.elem = realloc(warehouse.elem

cppcheck не зря на эту конструкцию ругается.

i-rinat ★★★★★
()
Ответ на: комментарий от sambist

Стандарт не гарантирует порядок вычисления аргументов, он implementation defined. Когда ты делаешь

int a = 1;
foo(a, ++a);

, то возможны два варианта:

1. сначала вычислится ++a и на фрэйм стэка вызванной функции ляжет 2 и 2

2. сначала будет вычислен и передан первый аргумент a(=1), а потом ++a(=2)

ISO International Standard ISO/IEC 14882:2014
1.9.15
If a side effect on a scalar
object is unsequenced relative to either another side effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.
Shadow1251
()
Последнее исправление: Shadow1251 (всего исправлений: 1)
Ответ на: комментарий от sambist

Что на практике:

#include <iostream>

void foo(int a, int b)
{
    std::cout << "a = " << a
	      << ", b = " << b
	      << std::endl;
}

int main(int argc, char* argv[])
{
    int n = 1;
    foo(n, ++n);

    return 0;
}
alex@localhost tmp % g++ --version
g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
alex@localhost tmp % g++ -Wall c.cc
c.cc: In function ‘int main(int, char**)’:
c.cc:19:16: warning: operation on ‘n’ may be undefined [-Wsequence-point]
     foo(n, ++n);
                ^
alex@localhost tmp % ./a.out 
a = 2, b = 2
alex@localhost tmp % clang++ --version                     
clang version 3.5.0 (tags/RELEASE_350/final)
alex@localhost tmp % clang++ -Wall c.cc 
c.cc:19:12: warning: unsequenced modification and access to 'n' [-Wunsequenced]
    foo(n, ++n);
        ~  ^
1 warning generated.
alex@localhost tmp % ./a.out 
a = 1, b = 2

Shadow1251
()
Ответ на: комментарий от i-rinat

Раньше не ругался, сейчас отказывается работать, ссылаясь на неустановленную --data-dir, устанавливать оную отказывается.

sambist ★★
() автор топика
Ответ на: комментарий от Shadow1251

Damn... Просмотрел :)

Это, кстати, тоже показатель. Код должен быть по возможности простой, без ненужных вывертов, чтобы его можно было легко читать и понимать.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

И где здесь выверты? Функция принимает 2 параметра, первый - указатель, второй - новый размер. ПРи вычислении нового размера сначала увеличивается размер в штуках, потом передается в функцию вычисленный в байтах. В чем проблема прочитать две строчки?

sambist ★★
() автор топика
Ответ на: комментарий от i-rinat

Переинсталлил свой цппчек:

alex@laptop:~$ cppcheck ~/Сервер/Dropbox/Projects/Smilodon/Smilo/local/smlwarehouse.c 
Checking /home/alex/Сервер/Dropbox/Projects/Smilodon/Smilo/local/smlwarehouse.c...
alex@laptop:~$ cppcheck ~/Сервер/Dropbox/Projects/Smilodon/Smilo/local/
Checking /home/alex/Сервер/Dropbox/Projects/Smilodon/Smilo/local/smlhandlers.c...
1/2 files checked 66% done
Checking /home/alex/Сервер/Dropbox/Projects/Smilodon/Smilo/local/smlwarehouse.c...
2/2 files checked 100% done
Показывай пруфы, что ругается.

sambist ★★
() автор топика
Ответ на: комментарий от i-rinat

warehouse.elem = realloc(warehouse.elem

cppcheck не зря на эту конструкцию ругается.
i-rinat ★★★★★ (19.04.2015 22:20:26)

Потому что иначе это п*добольство.

sambist ★★
() автор топика
Ответ на: комментарий от sambist

И где здесь выверты?

Использование префиксного инкремента и есть выверт. Он заставляет думать над выражением не секунду, а пять.

i-rinat ★★★★★
()
Ответ на: комментарий от sambist

Потому что иначе это п*добольство.

Оспаде, да ради бога.

i-rinat ★★★★★
()

Всё правильно. Сначала он возвращает 10, потом увеличивает значение а на 1, но в а записывается 10.

Используй префиксный инкремент.

anonymous
()
Ответ на: комментарий от sambist
$ cppcheck test.c
Checking test.c...
[test.c:5]: (error) Memory leak: p
$ cat test.c
int main()
{
        int *p = NULL;
        p = realloc(p, 10);
}

Тут и без cppcheck'а видна классика утечек, тащемта.

anonymous
()
Ответ на: комментарий от anonymous

Используй префиксный инкремент.

анонимус совсем больной стал. ЗАЧЕМ? Что-бы записать в a то, что было ДО операции над a?! Это идиотизм ИМХО.

emulek
()
Ответ на: комментарий от SliFly

Вообще C++ позволяет решать одну и туже задачу разными способами.

да, но выбирать необходимо самый читаемый. Лично я считаю, что конструкция a++ нужна ТОЛЬКО для

x = array[index++];
и не для чего более.

emulek
()
Ответ на: комментарий от SliFly

а как же for ?

это частный случай перечисления. Для того и придумано. А вот просто так «прибавить единицу», дык возьми и прибавь. На кой ляд выёживаться?

emulek
()
Ответ на: комментарий от anonymous

Тебе в голову не приходило, что это не весь код?

    SmlElement * ptrold = warehouse.elem;
 
    warehouse.elem      = realloc(warehouse.elem,
                                  ++warehouse.elemcount * sizeof(SmlElement));
    if (!(warehouse.elem))
    {
        warehouse.elem = ptrold;
        *index         = 0;
        warehouse.elemcount--;
        return SML_ERR_BADALLOC;
    }

sambist ★★
() автор топика
Ответ на: комментарий от SliFly

а как со скоростью выполнения?

монопенисуально. Компилятор в курсе, можешь проверить, objdump в помощь.

ЗЫЖ да, речь о amd64 & IA-32. Для других не ручаюсь. Т.е. думаю также, но не проверял.

emulek
()
Последнее исправление: emulek (всего исправлений: 1)
Ответ на: комментарий от sambist

Ну ок, вернул он а, получилось а = а. Почему после всего этого он а не увеличит на единицу?

Так тоже имеет право, типичный UB.

anonymous
()
Ответ на: комментарий от grondek

a++ создает временный объект со старым значением

Это особенность реализации твоего компилятора. Если ты рассчитываешь на вызов какого-нибудь конструктора в такой ситуации - ССЗБ.

anonymous
()
Ответ на: комментарий от anonymous

Я не упоминал конструктор. Уж как он там его создаст - внутреннее дело компилятора.

grondek
()

Лурк море, Люке, таки UB. В новых плюсах, вроде, обещали избавиться от понятия точки следования (если я это сам только что не выдумал).

Upd: в педивикии прям явно твой вариант рассматривается, и назначается UB.

one_more_hokum ★★★
()
Последнее исправление: one_more_hokum (всего исправлений: 1)

UB в С++ — это не недостатки компилятора, а фича языка.

anonymous
()
Ответ на: комментарий от sambist

Тебе в голову не приходило, что это не весь код?

Молодец самбист, поставил на место быдлокодера неграмотного.

А теперь сдуй щеки и почитай нормальную документацию, вроде такого, начиная с

When using realloc(), be careful to avoid the following idiom:

size += 50; 
if ((p = realloc(p, size)) == NULL) 
	return (NULL);
anonymous
()
Ответ на: комментарий от anonymous

This can cause aberrant program behavior if the incorrect size value is used.

Если внутренняя переменная, к которой у пользователя нет доступа «сломалась», неправильный реаллок, который выскочит с null - самое последнее, о чем нужно будет беспокоиться.

sambist ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.