Они не одно и то же. Функция в C или Objective-C - это организация некоторого процедурного кода в единое целое. У него очень специфическая семантика, и вы можете прочитать о них в любой простой книге по Си с гораздо более подробной информацией в более продвинутых книгах.
С другой стороны, макрос создается на этапе предварительной обработки компиляции и не является отдельной частью фактического двоичного файла. С макросом макрос фактически заменяется в коде до того, как возникают сложности, поэтому копии внедряются везде, где используется макрос. Вот почему побочные эффекты важно учитывать при использовании макросов (потому что если макрос использует один и тот же аргумент более одного раза, побочные эффекты будут возникать более одного раза).
Вот краткий пример для иллюстрации макроса:
#define SHOW_STRING_TWICE(string) printf("%s\n%s\n", string, string)
// ...
SHOW_STRING_TWICE("Hello, macro!");
Во время предварительной обработки макрос расширяется до следующего кода:
printf("%s\n%s\n", "Hello, macro!", "Hello, macro!");
Вы можете увидеть, как побочные эффекты являются проблемой в этом коде:
#define DOUBLE_NUMBER(number) ((number) + (number))
// ...
int doubleRandom = DOUBLE_NUMBER(generate_random_number());
В этом случае, когда макрос раскрывается, generate_random_number () фактически вызывается дважды, когда вы ожидали, что он будет вызван только один раз.