Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.91/46: Рейтинг темы: голосов - 46, средняя оценка - 4.91
ertyuo
0 / 0 / 0
Регистрация: 05.01.2010
Сообщений: 9
#1

Чем же макрос define так плох?

08.01.2010, 03:29. Просмотров 8377. Ответов 115

После прочтения про директиву препроцессора define возник вопрос по поводу применения define, как функции:
C++
1
#define QQ (q) (q^q)
Можно же улучшить читаемость кода, используя вместо функций именно директиву define. Или у данного использования макроса есть подводные камки какие-то? Да и объем кода в разы сократиться, так как для define будет достаточно всего-навсего одной строчки.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.01.2010, 03:29
Ответы с готовыми решениями:

Чем плох make?
Дали написать реферат по make файлам и соответственно указать его минусы, а...

Чем плох std::map?
std::map ?

Чем плох void main?
Встретил мнение, что void main() - не канон и даже плохо. Но статья древняя,...

Чем плох управляемый С++?
Я дико извиняюсь за подобную тему... но дело в том, что мне сегодня задали этот...

Перевести макрос define в функцию
Доброго времени суток. Я тут на днях набросал вот такие макросы для удобства:...

115
Tulosba
:)
Эксперт С++
4747 / 3241 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
24.10.2015, 17:21 #61
hoggy, вот тебе альтернативные ссылки с тем же кодом (раз уж у тебя эта не открывается): Раз, Два, Три.

Теперь про место для значения. Код:
C++
1
2
3
4
5
#include <cstdio>
 
int main() {
    printf( "%d\n", 42 );
}
Ассемблерный выхлоп:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
main:                                   # @main
    push    rbp
    mov rbp, rsp
    sub rsp, 16
    lea rdi, qword ptr [.L.str]
    mov esi, 42
    mov al, 0
    call    printf
    mov esi, 0
    mov dword ptr [rbp - 4], eax # 4-byte Spill
    mov eax, esi
    add rsp, 16
    pop rbp
    ret
 
.L.str:
    .asciz  "%d\n"
Убираем константу:
C++
1
2
3
4
5
#include <cstdio>
 
int main() {
    printf( "\n" );
}
Асм:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
main:                                   # @main
    push    rbp
    mov rbp, rsp
    sub rsp, 16
    lea rdi, qword ptr [.L.str]
    mov al, 0
    call    printf
    mov ecx, 0
    mov dword ptr [rbp - 4], eax # 4-byte Spill
    mov eax, ecx
    add rsp, 16
    pop rbp
    ret
 
.L.str:
    .asciz  "\n"
Как видишь, строки mov esi, 42 уже нет. Т.е. размер кода стал меньше.

Как вообще можно было предположить, что значение явно присутствующее в исходном файле, может выводиться на консоль и при этом НИГДЕ не храниться? Оно что из космоса прилетает?

Заметь, никаких адресов, о которых ты говорил, тут не используется, сугубо значение константы.
1
Evg
Эксперт CАвтор FAQ
19280 / 7136 / 529
Регистрация: 30.03.2009
Сообщений: 19,983
Записей в блоге: 30
24.10.2015, 17:52 #62
Цитата Сообщение от hoggy Посмотреть сообщение
мой пример кода выше написан согласно стандатру.
а из этого следует, что любой копилятор обязан уметь делать inline подстановку
по месту использования фундаментальной константы
"Пример выше" это который?

Цитата Сообщение от hoggy Посмотреть сообщение
все топовые компиляторы умеют оптимизировать промежуточные значение
Из этого никак не следует, что const-переменная является константой

Добавлено через 29 секунд
Цитата Сообщение от Tulosba Посмотреть сообщение
Заметь, никаких адресов, о которых ты говорил, тут не используется, сугубо значение константы
Да тут же вопрос терминологии. Он веник называет пряником, а потому и сложно понять, чего он говорит
0
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
24.10.2015, 17:55 #63
Цитата Сообщение от Evg Посмотреть сообщение
const-переменная
const-переменная? Я не ослышался?
0
Croessmah
++Ͻ
14527 / 8289 / 1556
Регистрация: 27.09.2012
Сообщений: 20,352
Записей в блоге: 3
Завершенные тесты: 1
24.10.2015, 18:16 #64
Цитата Сообщение от castaway Посмотреть сообщение
const-переменная? Я не ослышался?
const не дает гарантия константности. Так что да, это может быть переменная с квалификатором const
1
Tulosba
:)
Эксперт С++
4747 / 3241 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
24.10.2015, 18:17 #65
Цитата Сообщение от castaway Посмотреть сообщение
const-переменная? Я не ослышался?
Ну, это нормально. Даже в Стандарте есть упоминание (3.5/3):
a variable that is explicitly declared const or constexpr and neither explicitly declared extern nor
previously declared to have external linkage;
1
Voivoid
708 / 280 / 16
Регистрация: 31.03.2013
Сообщений: 1,339
24.10.2015, 18:29 #66
* * lea rdi, qword ptr [.L.str]
* * mov esi, 42
* * mov al, 0
* * call* * printf
Вместо того, чтобы спорить об очевиндных вещах лучше расскажите почему аргументы для printf не ложатся на стек?
0
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
24.10.2015, 18:30 #67
Цитата Сообщение от Croessmah Посмотреть сообщение
const не дает гарантия константности.
Я что-то туплю под вечер после работы.. Это как?

Цитата Сообщение от Tulosba Посмотреть сообщение
Даже в Стандарте есть упоминание (3.5/3):
n4527? Что-то не найду у себя такого... Поиск фразу "variable that is explicitly declared const" тоже не находит.
0
Croessmah
++Ͻ
14527 / 8289 / 1556
Регистрация: 27.09.2012
Сообщений: 20,352
Записей в блоге: 3
Завершенные тесты: 1
24.10.2015, 18:42 #68
Цитата Сообщение от castaway Посмотреть сообщение
Я что-то туплю под вечер после работы.. Это как?
я про константы времени компиляции. В теме же о них идет речь.
1
Tulosba
:)
Эксперт С++
4747 / 3241 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
24.10.2015, 18:51 #69
Цитата Сообщение от castaway Посмотреть сообщение
n4527?
Я в C++11 (ISO/IEC 14882 Third edition 2011-09-01) смотрел.
В драфте 3.5/(3.2):
a variable of non-volatile const-qualified type ...
Суть то же.

3/6:
A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable’s name, if any, denotes the reference or object.
Добавлено через 2 минуты
Цитата Сообщение от Voivoid Посмотреть сообщение
почему аргументы для printf не ложатся на стек?
Поясни мысль.

Добавлено через 1 минуту
Цитата Сообщение от Croessmah Посмотреть сообщение
я про константы времени компиляции.
Не важно, компиляции или выполнения. Всё равно это в том числе и "переменная", хотя и принимающая только одно значение в момент инициализации.
1
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
24.10.2015, 19:01 #70
Цитата Сообщение от Croessmah Посмотреть сообщение
я про константы времени компиляции.
Цитата Сообщение от Tulosba Посмотреть сообщение
Не важно, компиляции или выполнения. Всё равно это в том числе и "переменная", хотя и принимающая только одно значение в момент инициализации.
Блин.. Я, конечно, могу представить о чём идёт речь, но я категорически не хочу укладывать у себя в уме понятие "константная переменная", ведь это противоположные сущности
0
LynXzp
1 / 0 / 0
Регистрация: 22.10.2015
Сообщений: 6
24.10.2015, 21:24 #71
Цитата Сообщение от hoggy Посмотреть сообщение
а из этого следует, что любой копилятор обязан уметь делать inline подстановку
Ура! Прояснилось
Цитата Сообщение от Tulosba Посмотреть сообщение
Как видишь, строки mov esi, 42 уже нет. Т.е. размер кода стал меньше...
Заметь, никаких адресов, о которых ты говорил, тут не используется, сугубо значение константы.
Так все отлично, она inline подставлена точно так же как и #define бы сделал.

Цитата Сообщение от Voivoid Посмотреть сообщение
Вместо того, чтобы спорить об очевиндных вещах лучше расскажите почему аргументы для printf не ложатся на стек?
Не знаю как в Win, думаю зависит от компилятора, например: http://habrahabr.ru/company/intel/blog/246913/ освободился регистр...
А в микроконтроллерах много регистров (32 например), и при этом мало памяти и производительности, поэтому компилятор (gcc) может по выбору оптимизации пихать в стек все регистры или не все (что делать с остальными регистрами придумать не сложно, но как на самом деле не скажу). Может esi в данном бинарнике такой регистр... выступает верхним значением стека. (ну это я так, на кофейной гуще, но выглядит правдоподобно для меня)
0
Croessmah
24.10.2015, 21:30
  #72

Не по теме:

Цитата Сообщение от castaway Посмотреть сообщение
не хочу укладывать у себя в уме понятие "константная переменная", ведь это противоположные сущности
тогда "переменная, объявленная с квалификатором const" :)

0
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
24.10.2015, 21:37 #73
Цитата Сообщение от Croessmah Посмотреть сообщение
тогда "переменная, объявленная с квалификатором const"
Ты меня опять путаешь. Можешь прояснить мне, дураку, в каких случаях квалификатор const не делает константу константной?
0
ValeryS
Модератор
7219 / 5482 / 682
Регистрация: 14.02.2011
Сообщений: 18,542
24.10.2015, 21:46 #74
Цитата Сообщение от ertyuo Посмотреть сообщение
#define QQ (q) (q^q)
а никто не заметил, что это 0 в случае q целочисленной
ошибка в случае вещественной, и хрен знает что в случае выражения
0
rikimaru2013
C++ Game Dev
2472 / 1141 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
24.10.2015, 21:46 #75
Цитата Сообщение от castaway Посмотреть сообщение
дураку
кажись там речь о том, что
C++
1
const int a = 10;
не означает, что в конце "a" будет точно иметь значение 10, спустя какое-то время. Есть хитрости изменить значение, но будет UB так как некоторые компиляторы могут закешировать значение константы (они так думают - ведь им так сказали) и вместо бегать по адрессу брать значение, вставлять его с своей таблици закэшированых значений констант.
1
LynXzp
1 / 0 / 0
Регистрация: 22.10.2015
Сообщений: 6
24.10.2015, 21:47 #76
Цитата Сообщение от castaway Посмотреть сообщение
но я категорически не хочу укладывать у себя в уме понятие "константная переменная"
Если я правильно понимаю то
const int a=5;

1. может при дальнейшем использовании подставится значением и это будет константная константа дальше некуда
(printf("%d",a) превращается компилятором в printf("%d",5))

2. а может создастся переменная в памяти и получится "константная переменная"
(например foo(&a); как говорили выше)

(Я всегда думал что создается константая переменная, почему-то даже в мыслях не было что она может стать inline. Просто константы в макросе это явно inline, а const int больше похоже на запрет модификации переменной.)
0
castaway
Эксперт С++
4929 / 3036 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
24.10.2015, 21:52 #77
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
не означает, что в конце "a" будет точно иметь значение 10.
Не понял ход твоей мысли...
Что значит "в конце"? Почему/по какой причине оно может измениться?
0
rikimaru2013
C++ Game Dev
2472 / 1141 / 348
Регистрация: 30.11.2013
Сообщений: 3,709
24.10.2015, 22:01 #78
Цитата Сообщение от castaway Посмотреть сообщение
Почему/по какой причине оно может измениться?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using namespace std;
 
 
int main()
{
    const int a = 10;
    const int* ptr = &a;
    int* ptr2 = const_cast<int*>(ptr);
    *ptr2 = 14;                     // в Debug видно, что значение по адрессу &a изменилось на 14. 
    cout << a << endl;              // но выведет, к примеру в VS 2013, 10 - потому что закэшировал
    cout << *ptr << endl;
}
Код конечно не реалистичный так, как мало времени на придумывание было. Но факт, что рукожопов хватает и всё реально. И const не даёт 100% защиту, но без него - всеравно, что ездить на голой резине зимой с верой в бога!
1
LynXzp
1 / 0 / 0
Регистрация: 22.10.2015
Сообщений: 6
24.10.2015, 22:02 #79
Цитата Сообщение от castaway Посмотреть сообщение
Что значит "в конце"? Почему/по какой причине оно может измениться?
А если
foo(&a);
а foo - функция из подгруженной библиотеки черт его знает какого языка и компилятора. Вот возмет foo и запишет по адресу переменной a другое значение Если a не находится в защищенной области памяти и ОС это поддерживающей то пиши пропало.
0
ValeryS
Модератор
7219 / 5482 / 682
Регистрация: 14.02.2011
Сообщений: 18,542
24.10.2015, 22:02 #80
Цитата Сообщение от castaway Посмотреть сообщение
Почему/по какой причине оно может измениться?
ну например так
C++
1
2
3
const int a=5;
int b[1];
b[-1]=0;
но это грязный хак и UB в чистом виде
1
24.10.2015, 22:02
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.10.2015, 22:02

Чем оличается define от const
define A 5; и const a = 5; В первом случае идет замена в предпроцессоре......

#define работает не так, как ожидается
Здравствуйте. Подскажите, пожалуйста, почему в таком случае некорректно...

#define sqr(a) (a)*(a) - зачем так много скобок?
#define sqr(a) ((a)*(a)) такие вопросы: 1) Зачем ((a)*(a)) так много...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru