#define или void (С)

Модератор: Модераторы разделов

BratSinot
Сообщения: 812
ОС: Slackware64

#define или void

Сообщение BratSinot »

Здравствуйте! Что лучше использовать:

Код: Выделить всё

#define hello(); printf("Hello World");

Или:

Код: Выделить всё

void hello()
{
 printf("Hello World");
}
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: #define или void

Сообщение NickLion »

Вопрос мягко говоря без ответа. В каком случае? В одном случае удобнее макросы, в другом - функция.
Какие данные надо выводить? Не "хэллоу ворлд" же в самом деле ;)
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: #define или void

Сообщение BratSinot »

NickLion писал(а):
03.06.2010 07:59
Вопрос мягко говоря без ответа. В каком случае? В одном случае удобнее макросы, в другом - функция.
Какие данные надо выводить? Не "хэллоу ворлд" же в самом деле ;)

Ладно приведу пример пореальнее:

Код: Выделить всё

#define writexo(); printf("%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);
#define logbattle(); fprintf(fp, "%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);fflush(fp);
#define init(); for(unsigned short int i='1'; i<='9'; i++) sk[i-'1']=i;play=1;esh=1;
#define test(); if(sk[0]=='X'&&sk[0]==sk[1]&&sk[1]==sk[2]||sk[3]=='X'&&sk[3]==sk[4]&&sk[4]==sk[5]||sk[6]=='X'&&sk[6]==sk[7]&&sk[7]==sk[8]||sk[0]=='X'&&sk[0]==sk[3]&&sk[3]==sk[6]||sk[1]=='X'&&sk[1]==sk[4]&&sk[4]==sk[7]||sk[2]=='X'&&sk[2]==sk[5]&&sk[5]==sk[8]||sk[0]=='X'&&sk[0]==sk[4]&&sk[4]==sk[8]||sk[2]=='X'&&sk[2]==sk[4]&&sk[4]==sk[6]){printf("X WIN\n"); fprintf(fp, "X WIN\n"); esh=0;}  else if(sk[0]=='O'&&sk[0]==sk[1]&&sk[1]==sk[2]||sk[3]=='O'&&sk[3]==sk[4]&&sk[4]==sk[5]||sk[6]=='O'&&sk[6]==sk[7]&&sk[7]==sk[8]||sk[0]=='O'&&sk[0]==sk[3]&&sk[3]==sk[6]||sk[1]=='O'&&sk[1]==sk[4]&&sk[4]==sk[7]||sk[2]=='O'&&sk[2]==sk[5]&&sk[5]==sk[8]||sk[0]=='O'&&sk[0]==sk[4]&&sk[4]==sk[8]||sk[2]=='O'&&sk[2]==sk[4]&&sk[4]==sk[6]){printf("O WIN\n"); fprintf(fp, "O WIN\n"); esh=0;}
#define vysg(); while(ysg==0){scanf("%u", &ysg);if(ysg>4||ysg<1) {printf("Number wrong.\n"); ysg=0;}}

Код: Выделить всё

void writexo()
{
 printf("%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);
}
void logbattle()
{
 fprintf(fp, "%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);
 fflush(fp);
}
void init()
{
 for(unsigned short int i='1'; i<='9'; i++) sk[i-'1']=i;
 play=1;
 esh=1;
}
void test()
{
 if(sk[0]=='X'&&sk[0]==sk[1]&&sk[1]==sk[2]||sk[3]=='X'&&sk[3]==sk[4]&&sk[4]==sk[5]||sk[6]=='X'&&sk[6]==sk[7]&&sk[7]==sk[8]||sk[0]=='X'&&sk[0]==sk[3]&&sk[3]==sk[6]||sk[1]=='X'&&sk[1]==sk[4]&&sk[4]==sk[7]||sk[2]=='X'&&sk[2]==sk[5]&&sk[5]==sk[8]||sk[0]=='X'&&sk[0]==sk[4]&&sk[4]==sk[8]||sk[2]=='X'&&sk[2]==sk[4]&&sk[4]==sk[6]){printf("X WIN\n"); fprintf(fp, "X WIN\n"); esh=0;}  else if(sk[0]=='O'&&sk[0]==sk[1]&&sk[1]==sk[2]||sk[3]=='O'&&sk[3]==sk[4]&&sk[4]==sk[5]||sk[6]=='O'&&sk[6]==sk[7]&&sk[7]==sk[8]||sk[0]=='O'&&sk[0]==sk[3]&&sk[3]==sk[6]||sk[1]=='O'&&sk[1]==sk[4]&&sk[4]==sk[7]||sk[2]=='O'&&sk[2]==sk[5]&&sk[5]==sk[8]||sk[0]=='O'&&sk[0]==sk[4]&&sk[4]==sk[8]||sk[2]=='O'&&sk[2]==sk[4]&&sk[4]==sk[6]){printf("O WIN\n");
 fprintf(fp, "O WIN\n"); esh=0;}
}
void vysg()
{
 while(ysg==0){scanf("%u", &ysg);if(ysg>4||ysg<1) {printf("Number wrong.\n"); ysg=0;}}
}

Мне не удобность нужно. Просто процедура все равно оставляет свои отпечатки, а так будет как будто вставлено.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

Объявление функции через define - все равно, что объявление ее inline - тело функции будет каждый раз подставляться вместо ее вызова. Если вам не нужны частые джампы (т.е. нужно быстродействие в ущерб объему кода), лучше пользоваться define или inline. Если же ваша функция достаточно объемна, или же нужно, чтобы объем занимаемой программой памяти был как можно меньше - используйте функцию.
Мне, например, удобнее короткие функции объявлять через #define. Пример:

Код: Выделить всё

#ifdef __TEST__
#define WARN(...)  do{int n = 0; fprintf(stderr,__VA_ARGS__); \
    if(mq_out > 0 && out_buf){n = snprintf(out_buf, mq_size, __VA_ARGS__); \
        mq_send(mq_out, out_buf, n, 1);}}while(0)
#define ERR(...) do{fprintf(stderr, __VA_ARGS__);}while(0)
#else
#define WARN(...)  do{if(mq_out > 0 && out_buf){n = snprintf(out_buf, mq_size, __VA_ARGS__); \
        mq_send(mq_out, out_buf, n, 1);}}while(0)
#define ERR(...) do{}while(0)
#endif
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: #define или void

Сообщение NickLion »

Только вот зачем ";" после define ставите?
представьте, что будет:

Код: Выделить всё

#define writexo(); printf("%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);
for( int i = 0; i <30; i++ )
  writexo();

Получится:

Код: Выделить всё

for( int i = 0; i <30; i++ )
; printf("%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);

Т.е. пустой цикл, а после 1 раз вывод.

init - это часто используемая вещь? Имеет ли смысл её выносить макросом? К тому же несколько операторов в один дефайн без фигурных скобок - это нехорошо. Причину смотрите ранее.

Следующее, что нехорошо - использование в макросе переменных, не передаваемых через параметры. Конечно, они могут быть глобальными, так ли это?

Вообще я бы советовал всё это сделать inline функциями.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

NickLion писал(а):
03.06.2010 09:09
представьте, что будет:

Вот поэтому лучше всего оформлять такие функции в скобки do{}while(0). Внутри них можно и какие-нибудь временные переменные обявить, и быть уверенным, что не произойдет конфликта с внешними переменными.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: #define или void

Сообщение NickLion »

eddy писал(а):
03.06.2010 09:21
NickLion писал(а):
03.06.2010 09:09
представьте, что будет:

Вот поэтому лучше всего оформлять такие функции в скобки do{}while(0). Внутри них можно и какие-нибудь временные переменные обявить, и быть уверенным, что не произойдет конфликта с внешними переменными.

А почему не просто блок?

#define SOME_BYAKA(...) { int byaka_var = 0; SOME_ANOTHER_BYAKA(); AND_SOME_ELSE(); }

Хотя уже не помню, в C (не C++) можно переменные в блоке объявлять? Вроде были с этим проблемы.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

NickLion писал(а):
03.06.2010 10:59
C (не C++) можно переменные в блоке объявлять?

Можно. Если вне блока была переменная i, внутри блока ее объявление создаст новую автоматическую переменную.
Точно не припомню, но был у меня однажды "облом" при объявлении define'а просто блоком, без do..while(0). Но это очень редкий случай.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: #define или void

Сообщение BratSinot »

Только вот зачем ";" после define ставите?
представьте, что будет:

Код: Выделить всё

#define writexo(); printf("%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);
for( int i = 0; i <30; i++ )
  writexo();

Это просто не влезло.

Точно, про inline я и забыл. Просто книгу по C89 читал, а по C99 нет. Спасибо.

Хотя стоять, если будет:

Код: Выделить всё

void writexo()
{
 printf("%c|%c|%c\n-----\n%c|%c|%c\n-----\n%c|%c|%c\n", sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], sk[6], sk[7], sk[8]);
}

То он подставит? Просто GCC подсказывает что inline только с не статическими данными.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

BratSinot писал(а):
03.06.2010 11:17
Просто книгу по C89 читал, а по C99 нет.

Советую K&R почитать. Я, к стыду своему, только неделю назад взял ее в библиотеке :blush:
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: #define или void

Сообщение BratSinot »

eddy писал(а):
03.06.2010 11:24
Советую K&R почитать. Я, к стыду своему, только неделю назад взял ее в библиотеке :blush:

Да у нас в России напряг с иностранной литературой. Так что пока Шилдта читаю.
Спасибо сказали:
watashiwa_daredeska
Бывший модератор
Сообщения: 4038
Статус: Искусственный интеллект (pre-alpha)
ОС: Debian GNU/Linux

Re: #define или void

Сообщение watashiwa_daredeska »

NickLion писал(а):
03.06.2010 10:59
А почему не просто блок?
Прелести с «;».

Код: Выделить всё

if (b)
  SOME_BYAKA();
else
  ANOTHER_BYAKA();
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: #define или void

Сообщение t.t »

BratSinot писал(а):
03.06.2010 11:26
eddy писал(а):
03.06.2010 11:24
Советую K&R почитать. Я, к стыду своему, только неделю назад взял ее в библиотеке :blush:
Да у нас в России напряг с иностранной литературой. Так что пока Шилдта читаю.
Перевод K&R есть в сети.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

t.t писал(а):
03.06.2010 12:04
Перевод K&R есть в сети.

Я в сети и английский, и русский нашел. А вот в библиотеке был только английский, его и читаю (не люблю с экрана читать - пока домашний принтер нормально работал, я себе книжки распечатывал и сшивал).
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: #define или void

Сообщение BratSinot »

Перевод K&R есть в сети.

Так мне все равно что читать, главное не на мониторе.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

BratSinot писал(а):
03.06.2010 12:41
Так мне все равно что читать, главное не на мониторе.

На urss.ru стоит 500р, на "озоне" - 336, на www.goodreads.ru - 285.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: #define или void

Сообщение serzh-z »

BratSinot писал(а):
03.06.2010 07:53
Здравствуйте! Что лучше использовать:
/me упал...

По-правде говоря - лучше вообще минимизировать использование макросов. Если возможно - обойтись константами. Макросы: 1. при бездумном применении затрудняют понимание кода; 2. очень сильно затрудняют отладку.

Ну а "#define hello();" - это вообще однозначный победитель на конкурсе индусского кода. =)
Спасибо сказали:
Аватара пользователя
korvin
Сообщения: 39
ОС: >_<

Re: #define или void

Сообщение korvin »

eddy писал(а):
03.06.2010 08:47
Объявление функции через define - все равно, что объявление ее inline

не тоже самое.
(© '(define LISP (такой язык-программирования (состоящий-из смайликов (чуть более) (чем целиком)))) lurkmore)
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: #define или void

Сообщение eddy »

korvin писал(а):
03.06.2010 19:35
не тоже самое.

За исключением того, что define не контролирует типы возвращаемого значения и аргументов - то же самое.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: #define или void

Сообщение serzh-z »

eddy писал(а):
03.06.2010 19:44
За исключением того, что define не контролирует типы возвращаемого значения и аргументов - то же самое.
Будем спорить или читать документацию на компилятор и стандарты? См. ISO 14882:1998(E), 7.1.2 и ISO 9899:1999(E), 6.7.4. inline - это лишь рекомендация программиста компилятору.
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: #define или void

Сообщение sash-kan »

BratSinot писал(а):
03.06.2010 12:41
Так мне все равно что читать, главное не на мониторе.
* в сторону
вот бы интернет распечатать и подшить. главное, чтоб не на мониторе.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: #define или void

Сообщение BratSinot »

sash-kan писал(а):
03.06.2010 20:55
вот бы интернет распечатать и подшить. главное, чтоб не на мониторе.

Я обычно использую либо литературу которая у меня накопилась от родных, либо покупаю новую.
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: #define или void

Сообщение sash-kan »

BratSinot писал(а):
03.06.2010 21:42
накопилась от родных
там, наверно, очень старые версии web-страничек.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: #define или void

Сообщение BratSinot »

sash-kan писал(а):
03.06.2010 23:53
там, наверно, очень старые версии web-страничек.

Слушай, не смешно. Там Начиная от спецификаций процессоров Intel 8080 заканчивая книгами от C к C++.
Спасибо сказали: