Оба синтаксически верны C, и компилятор должен справиться с этим. Но компилятор может, в зависимости от конфигурации, выдавать предупреждение или даже ошибку (например, - ошибка в gcc), потому что один из них настолько подозрительн, что вы никогда не ожидаете, что он будет преднамеренным. Когда вы используете что-то вроде if (x = 0) { ... }
(присвойте ноль x
и запустите блок, если ноль отличен от нуля), вы почти всегда имеете в виду if (x == 0) { ... }
(запустите блок, если x
равен нулю).
Теперь давайте перейдем к тому, почему if ((x = 0)) { ... }
не считается достаточно подозрительным, чтобы оправдывать предупреждение того же типа (этот конкретный код все еще подозрительный, потому что условие всегда оценивается как ноль, а тело никогда не запускается) ...
Существует некоторая идиома, используемая некоторыми разработчиками C (я один из них), когда вы помещаете назначение в скобки и используете функцию, заключающуюся в том, что даже назначение имеет само значение, и это назначенное значение.
Пример:
#include <stdio.h>
int main(int argc, char **argv)
{
int c;
while ((c = getchar()) != '\n')
printf("Character: '%c' (0x%02x)\n", c, c);
return 0;
}
Проверьте пример:
$ ./test
Hello!
Character: 'H' (0x48)
Character: 'e' (0x65)
Character: 'l' (0x6c)
Character: 'l' (0x6c)
Character: 'o' (0x6f)
Character: '!' (0x21)
Важной частью было условие (c = getchar()) != '\n'
, в котором вы сначала присваиваете результат getchar()
для c
и затем проверьте это для определенного значения. В этом самом случае мы читаем символы один за другим из стандартного ввода до строки и (технически, пока мы не прочитаем символ \n
). Основным преимуществом этого способа является то, что он позволяет вам вставить getchar()
в тест. В противном случае вам пришлось бы использовать запятую, бесконечный цикл с разрывом или поставить его как перед циклом, так и в конце цикла.
Иногда вы сравниваете с ненулевыми значениями, такими как \n
, -1
и аналогичными, но иногда вы сравниваете с нулем или, при работе с указателями, с NULL
. Давайте найдем пример для NULL
, который довольно распространен при распределении памяти.
char *p;
if ((p = malloc(50)) == NULL) {
...handle error...
}
Конечно, вы могли бы написать это как:
char *p;
p = malloc(50);
if (p == NULL) {
...handle error...
}
Но в зависимости от вашего вкуса вы также можете использовать:
char *p;
if (!(p = malloc(50))) {
...handle error...
}
Или даже повернуть его наоборот (что, между прочим, противоречит моему предпочтению всегда сначала обрабатывать ошибку):
char *p;
if ((p = malloc(50))) {
...do stuff...
} else {
...handle error...
}
В последнем случае условие (p = malloc(50))
, что в точности эквивалентно p = malloc(50)
но последнее крайне подозрительно из-за уже упоминавшейся распространенной ошибки при выполнении присваивания вместо сравнения на C и производных языках. Обратите внимание, что речь идет не только о подозрительных компиляторах, но и о людях, читающих код и просматривающих потенциальную ошибку.
Избыточные скобки - это просто средство сообщить читателям и компилятору, что это назначение определенно намеренное и что это не является причиной такой распространенной ошибки.
Если вы хотите автоматически взламывать main без установки точки останова можно также использовать команду start
.
Если вам нужно предоставить программе какие-либо аргументы, вы можете использовать:
начальный аргумент1 аргумент2
Не используйте команду gdb файл-символов
для загрузки внешних символов. Адреса точки останова будут неправильными, поскольку они не перемещены.
Вместо этого установите точку останова в main
, запустите программу и затем установите свою точку останова:
gdb ./program
GNU gdb 6.8-debian blah blah blah
(gdb) br main
Breakpoint 1 at 0x80489c1
(gdb) run
Starting program: ./program
Breakpoint 1, 0x080489c1 in main ()
(gdb) br 'QAbstractItemView::clicked(QModelIndex const&)'
Breakpoint 2 at 0xb7d24664
(gdb) continue
Continuing.
Затем сделайте свою точку останова.
Обязательно укажите список параметров в функции, в которой вы хотите установить точку останова, без имен этих параметров, только их типов.