Ніколи не пишіть такий код.
Для j<1000
, j/1000
дорівнює нулю (ціле ділення). Так:
(&main + (&exit - &main)*(j/1000))(j+1);
еквівалентно:
(&main + (&exit - &main)*0)(j+1);
Який є:
(&main)(j+1);
Які дзвінки main
з j+1
.
Якщо j == 1000
, тоді виходять ті самі рядки, що й:
(&main + (&exit - &main)*1)(j+1);
Який зводиться до
(&exit)(j+1);
Що є exit(j+1)
і залишає програму.
(&exit)(j+1)
і exit(j+1)
по суті те саме - цитуючи C99 §6.3.2.1 / 4:
Позначення функції - це вираз, який має тип функції. За винятком випадків, коли це операнд оператора sizeof або unary & operator , позначення функції з типом " функція, що повертає тип " перетворюється у вираз, що має тип " покажчик на тип повернення функції ".
exit
є позначенням функції. Навіть без одинарної &
адреси оператора, це трактується як вказівник на функціонування. ( &
Просто робить це явним.)
А виклики функцій описані в §6.5.2.2 / 1 і наступні:
Вираз, що позначає викликану функцію, повинен мати вказівник типу на функцію повернення void або повернення типу об'єкта, відмінного від типу масиву.
Так exit(j+1)
працює через автоматичне перетворення типу функції в тип вказівника на функцію, а також (&exit)(j+1)
працює з явним перетворенням у тип вказівника на функцію.
Зважаючи на це, наведений вище код не відповідає ( main
приймає або два аргументи, або взагалі жодного), і &exit - &main
, я вважаю, не визначений відповідно до §6.5.6 / 9:
Коли віднімаються два покажчики, обидва повинні вказувати на елементи одного і того ж об’єкта масиву або один минулий останній елемент об’єкта масиву; ...
Додавання (&main + ...)
було б дійсним саме по собі, і його можна було б використати, якщо додана кількість дорівнювала нулю, оскільки §6.5.6 / 7 говорить:
Для цілей цих операторів вказівник на об’єкт, який не є елементом масиву, поводиться так само, як вказівник на перший елемент масиву довжини один із типом об'єкта як його тип елемента.
Тому додавання нуля &main
було б нормальним (але не дуже корисним).
main
на C ++.