LINUX.ORG.RU

if - не цикл, а оператор ветвления. В нем в данном случае проверяется равенство друг другу двух значений, в каком порядке они стояит - оператору сравнения, как известно, пофиг.

Преинкремент, насколько я понимаю, увеличивает значение переменной цикла до выполнения тела, а не после.

pianolender ★★★
()

if(10 == blablalba)

если вы вместо == по ошибке напишете =, то компилятор в этом случае выдаст ошибку.

ymn ★★★★★
()

Про if уже был правильный ответ, а ++i раньше был быстрее i++, наследие. В C++, если i - какой-нибудь объект, ++i и правда будет ьыстрее.

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

Преинкремент, насколько я понимаю, увеличивает значение переменной цикла до выполнения тела, а не после

Нет.

encyrtid ★★★★★
()

if(10 == blah) {} - называет Yoda conditions и используется для предотвращения ошибок (blah = 10), как написал ymn

Преинкремент сначала увеличивает переменную, потом возвращает её (увеличенное) значение. Пост-инкремент сначала возвращает исходное значение, потом увеличивает. Очевидно, при пост-инкременте исходное значение копируется во вспомогательную, временную переменную, которая и возвращается после того, как вся операция (включительно с инкрементом) будет выполнена. Налицо лишний (хотя небольшой) расход памяти/времени.

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

Достаточно компилировать с -Wall -Werror, чтобы таких ошибок не было.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от ymn

если вы вместо == по ошибке напишете =, то компилятор в этом случае выдаст ошибку.

В такой варианте, как у ТС, да, если if(blablabla = 10), то не выдаст.

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

Налицо лишний (хотя небольшой) расход памяти/времени.

В данном цикле(int) разницы не будет

hired777
()

в продолжении темы

Видел такой код:

  char temp[SIZE];
  memset(&temp[0], 0, SIZE);
почему пишут именно так «&temp[0]», разве это не эквивалентно «temp» ? или тут тоже защита от какой-то опечатки?

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

Налицо лишний (хотя небольшой) расход памяти/времени.

Какой-нибудь аудиоплеер нынче загрузит свой xml-конфиг, выжрав пару десятков метров памяти только на хранение этой структуры. Так что это просто понт, не более.

Igron ★★★★★
()

Подскажите зачем писать так

А зачем наоборот? Потому что ты так привык?

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

4.2

конечно, в варианте if(blablabla = 10) даже ворнигн не выдает

Выдает, еще как:

cat 1.c
#include <stdio.h>
int main(){
	int blah = 12;
	if(blah = 5) printf("5\n");
}

gcc -Wall -Werror 1.c 
1.c: В функции <<main>>:
1.c:4:2: ошибка: присваивание, используемое как логическое выражение, рекомендуется  [-Werror=parentheses]
1.c:5:1: ошибка: control reaches end of non-void function [-Werror=return-type]
cc1: все предупреждения считать ошибками
А кто компилит без -Wall -Werror - тот ССЗБ!!!

Eddy_Em ☆☆☆☆☆
()
Ответ на: 4.2 от Eddy_Em

А кто компилит без -Wall -Werror - тот ССЗБ!!!

Я с -Wextra компилю :)

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

Налицо лишний (хотя небольшой) расход памяти/времени.

В случае с for никакой разницы между пре- и постинкрементом нет.

Relan ★★★★★
()

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

Первый вариант только в Java и для equals пишут чтобы не проверять на null лишний раз.

vertexua ★★★★★
()
Ответ на: 4.2 от Eddy_Em

И как вы прикажете компилить вот такое:

if( !( file = fopen("...","r") ) )
 return;

segfault ★★★★★
()

зачем в цикле for преинкремент?

Как-то писал я длинную арифметику в полях вычетов, для чего создал объект «элемент поля» и перегрузил для него основные математические операторы. Преинкремент инкрементировал значение и возвращал ссылку на *this. Постинкремент же создавал копию текущего объекта (с выделением и копированием пары килобайт), инкрементировал текущий объект и возвращал ту самую копию. Так вот, если возвращаемое значение не имеет значения, лучше использовать преинкремент.

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

Любопытная у этого ворнинга спецификация...

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

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

Xellos ★★★★★
()
Ответ на: в продолжении темы от yax123

Нисколько не эквивалентно. & - оператор взятия адреса. memset() принимает указатель (char*). Указатель - переменная, содержащая адрес в памяти. Соответственно char temp[SIZE] будет иметь тип char[SIZE]. На этот тип указатель взять нельзя, потому что непонятно куда он будет указывать. Можно сначала выбрать любой элемент массива, например так: temp[0] для нулевого элемента, ну или, допустим, temp[2] для второго. А потом уже брать адрес от этого чтобы получить указатель.

com
()
Ответ на: комментарий от Vovka-Korovka

Имя массива вернет адрес на его первый элемент. Это в стандарте прописано.


+ 1.

А написано изначально криво довольно, ни то, ни се:

char temp[SIZE];
memset(&temp[0], 0, SIZE);
Имхо, если бы нужно было первый элемент занулить, то лучше написать:
char temp[SIZE];
memset(&temp[0], 0, sizeof(temp[0]));
Если весь массив, то:
char temp[SIZE];
memset(temp, 0, sizeof(temp));
Чтобы по коду было ясно, что программист хотел.

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

Имхо, если бы нужно было первый элемент занулить, то лучше написать:

char temp[SIZE];
memset(&temp[0], 0, sizeof(temp[0]));

А можно не выпендриваться и написать

temp[0] = 0;

Да и для char использовать sizeof нет смысла, всегда будет 1(тоже прописано в стандарте).

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

А можно не выпендриваться и написать
temp[0] = 0;
Да и для char использовать sizeof нет смысла,
всегда будет 1(тоже прописано в стандарте).

Вестимо можно. Вообще не думал про char, когда писал.
Это ж гипотетический пример, в нем мог бы быть и массив структур или массив неизвестных элементов (typedef).

Tayler ★★
()

Преинкремент иногда работает быстрее (хотя в современных компиляторах пофиг). Но хорошо тем, что читается лучше (не важно, в цикле ли, или просто где-то в коде) т.е. ++ сразу бросается в глаза.

В if константа впереди, чтобы минимизировать риск на ошибку (с указанием = вместо ==), то с современными компиляторами это опять же не важно, т.к. на такое они ругаться будут.

Obey-Kun ★★★★★
()
Ответ на: комментарий от Tayler

Вообще хотели занулить весь массив (это точно).
Я сам обычно пишу так: memset(temp, 0, sizeof(temp));
так же я знаю что temp = &temp[0], то есть все будет работать и так.
Но встретив такой код в чужих исходниках (при этом зная авторов как прогеров уровня точно не ниже моего быдлоуровня), был слегка озадачен (нафига лишних 4 символа).
Можно конечно согласиться с тем что чуваки немного не секут в указателях, но это слишком просто. Поэтому предполагаю, что есть какое-то другое объяснение (с чем и пришел сюда).

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

нагляднее?
хм, я всегда знал (в книжке по С прочитал, когда еще был студентом) что по имени массива фактически вернется указатель на нулевой элемент. Без этого адресная арифметика и другие кошерные вещи не более чем пустая вредная болтовня.
Нагляднее это может стать только в том случае если человек не знает того, что такое массив в С и как с ним работать. Либо если это часть обобщающего правила (лично мне не известного), которое дает возможность аналогично работать не только с массивами, но еще с чем-то (хотя я не могу придумать пример для подтверждения этой гипотезы).

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

Тоже встречал, тоже задумывался. Ответа не нашел. Даже в стандарте в примечаниях оно упоминалось как «часто используемое». Только зачем - непонятно.

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

Мож просто потому, что в таком виде видно, что это массив. И если int temp[10]; поменять на int temp; то код не соберется.

Хотя аргументы не ахти.

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

Второе предположение весьма занятное. Как минимум если логика предполагает наличие массива, то изменение в объявлении это сразу выявит.
С другой стороны формулировка memset(temp, 0, sizeof(temp));
универсальна и будет работать с любым temp не важно скаляр или вектор.

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

Внезапно занулится не все. Но с другой стороны это все равно не объясняет &temp[0].

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

Арифметика та же, но такой вид порождает множество вопросов о целесообразности.
В случае передачи в функцию возможно это будет наглядным ( foo(&temp[2]) - вернуть байт в нужное место массива). А в других случаях я не уверен.

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

любую строчку кода можно написать кучей способов.
вопрос в том кто какой способ выбирает и почему?
A как занулить такой массив статически:
char temp[1000000];

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

С этим согласен.
Но в общем случае зануление необходимо не только в момент объявления.

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

Ну это вы уже начинаете троллить :))))
Любопытно было понять почему &temp[0] вместо temp.
А не инициализации при объявлении.

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

Любопытно было понять почему &temp[0] вместо temp.

Я вот вижу смысл в записях «&temp[0]» или «&temp[2]» только если функция, куда передается указатель, имеет дело с одним элементом, а не с массивом.
В остальных случаях я бы написал «temp» или «temp + 2».
Возможно есть еще логичные примеры исключений, пока здесь их никто не привел.

Tayler ★★
()
Ответ на: 4.2 от Eddy_Em

А кто компилит без -Wall -Werror - тот ССЗБ!!!

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

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

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

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