Вопрос вызвал некоторую путаницу, поскольку блоки (в смысле вопроса) не являются функцией стандарта C. Apple добавила их в качестве расширения к своим компиляторам C и C ++, когда добавила их в Objective C, но они не являются вещь C вне экосистемы Apple. Признаюсь, у меня нет опыта их использования, но, насколько я могу судить по документам, таким как this , синтаксис был выбран так, чтобы он был одинаковым для C, C ++ и Objective. C. Действительно, некоторые источники утверждают, что детали синтаксиса были выбраны специально, чтобы избежать возможности конфликта с C ++.
С точки зрения C принятие блока в качестве параметра и вызов полученного таким образом блока полностью аналогичны принятию указателя на функцию и вызову функции, на которую указывает указатель, соответственно. Ваш пример функции C выглядит правильно.
Аналогичное относится к объявлению и работе с блоками на всех трех языках - это аналогично объявлению и работе с указателями на функции. Я уверен, что это было намеренное рассмотрение проекта. Таким образом
void (^myBlock1)(void) ;
действительно объявляет myBlock1
как блок, не имеющий параметров и ничего не возвращающий, но не определяющий его значение. Установив в другом месте действительное значение, как показано в вопросе, OP наблюдает
Попытка вызвать блок напрямую, без скобок. это
не работает Xcode предупреждает результат не используется . Сообщение блока: НЕ
вошел в консоль.
myBlock1;
, как и следовало ожидать. Это выражение оператора, оценивающее значение блока, а не результат выполнения блока. Это аналог
int myInt = 1;
myInt; // specifically, analogous to this
Чтобы выполнить блок, в скобках указывается список аргументов постфикса (даже если список пуст), как при вызове функции через указатель функции:
Теперь попытайтесь вызвать блок напрямую, на этот раз в скобках.
Это работает как задумано. Нет предупреждений XCode, и сообщение блока IS
вошел в консоль.
myBlock1();
Наличие или отсутствие списка аргументов - это то, что однозначно определяет, получает ли кто-то доступ к значению блока или вызывает его.
Путаница заключается в передаче блока функции (или методу):
Теперь вызываем функцию, передавая блок в качестве параметра, БЕЗ
скобки. Это работает как задумано, но синтаксис не соответствует
с предыдущим вызовом блока.
double someNumber;
someNumber= pureCfunctionWithABlockParameter(0, 1, myBlock1 );
Тем не менее, вопреки утверждению в вопросе, этот синтаксис является полностью согласованным, как внутренне совместимым с другими аспектами синтаксиса и использования блока, так и совместимым с синтаксисом и использованием аналогичного указателя на функцию. Это передает блок в функцию, идентифицируя блок по его имени. Сам блок передается, а не результат его выполнения, потому что для него не предоставлен список аргументов.
В конце концов, я действительно хочу определить блок
который получает параметр типа int, например:
void (^block)(int)
Но я не могу достичь этого из-за того, что я считаю синтаксисом
выпуск.
Функция C, принимающая и использующая такой блок, может выглядеть следующим образом
void pass_2(void (^do_something)(int)) {
do_something(2);
}
Учитывая переменную block
, объявленную, как показано выше, и назначенную в качестве значения действительный блок, эта функция может быть вызвана так:
pass_2(block);
Точно так же, как мы узнаем, что функция pass_2
вызывается при наличии списка аргументов, мы признаем, что значение переменной block
передается как аргумент - не вызывается - при отсутствии 1064 * списка аргументов.