Большие макросы C. Каково преимущество?

Вот to-from для Римских цифр. Не часто используемый, но могло быть удобным. Использование:

if ("IV".IsValidRomanNumeral())
{
   // Do useful stuff with the number 4.
}

Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral());
Console.WriteLine(3888.ToRomanNumeralString());

источник:

    public static class RomanNumeralExtensions
    {
        private const int NumberOfRomanNumeralMaps = 13;

        private static readonly Dictionary<string, int> romanNumerals =
            new Dictionary<string, int>(NumberOfRomanNumeralMaps)
            {
                { "M", 1000 }, 
                { "CM", 900 }, 
                { "D", 500 }, 
                { "CD", 400 }, 
                { "C", 100 }, 
                { "XC", 90 }, 
                { "L", 50 }, 
                { "XL", 40 }, 
                { "X", 10 }, 
                { "IX", 9 }, 
                { "V", 5 }, 
                { "IV", 4 }, 
                { "I", 1 }
            };

        private static readonly Regex validRomanNumeral = new Regex(
            "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
            + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
            RegexOptions.Compiled);

        public static bool IsValidRomanNumeral(this string value)
        {
            return validRomanNumeral.IsMatch(value);
        }

        public static int ParseRomanNumeral(this string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.ToUpperInvariant().Trim();

            var length = value.Length;

            if ((length == 0) || !value.IsValidRomanNumeral())
            {
                throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
            }

            var total = 0;
            var i = length;

            while (i > 0)
            {
                var digit = romanNumerals[value[--i].ToString()];

                if (i > 0)
                {
                    var previousDigit = romanNumerals[value[i - 1].ToString()];

                    if (previousDigit < digit)
                    {
                        digit -= previousDigit;
                        i--;
                    }
                }

                total += digit;
            }

            return total;
        }

        public static string ToRomanNumeralString(this int value)
        {
            const int MinValue = 1;
            const int MaxValue = 3999;

            if ((value < MinValue) || (value > MaxValue))
            {
                throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
            }

            const int MaxRomanNumeralLength = 15;
            var sb = new StringBuilder(MaxRomanNumeralLength);

            foreach (var pair in romanNumerals)
            {
                while (value / pair.Value > 0)
                {
                    sb.Append(pair.Key);
                    value -= pair.Value;
                }
            }

            return sb.ToString();
        }
    }
5
задан jdizzle 13 July 2009 в 18:21
поделиться

7 ответов

Если макросы слишком длинные, они, вероятно, делают код коротким, но эффективным. Фактически, он мог использовать макросы для явного встраивания кода или удаления точек принятия решения из пути кода времени выполнения.

Возможно, важно понимать, что в прошлом такая оптимизация не выполнялась многими компиляторами, и некоторые вещи, которые мы считаем само собой разумеющимися сегодня, например быстрые вызовы функций, тогда были недействительными.

4
ответ дан 18 December 2019 в 07:10
поделиться

На мой взгляд, лучшее использование макросов - это сжатие кода и уменьшение количества ошибок. Обратной стороной является отладка, поэтому их нужно использовать с осторожностью.

Я склонен думать, что если результирующий код не будет на порядок меньше и менее подвержен ошибкам (то есть макросы позаботятся о некоторой бухгалтерской отчетности) подробности), то оно того не стоило.

В C ++ многие подобные применения можно заменить шаблонами, но не все. Простой пример полезных макросов - это макросы обработчика событий MFC - без них создание таблиц событий было бы намного сложнее, а код, который вам пришлось бы писать (и читать), был бы намного сложнее.

8
ответ дан 18 December 2019 в 07:10
поделиться

Я знаю только из двух причин делать то, что вы описываете.

Во-первых, заставить функции быть встроенными. Это в значительной степени бессмысленно, поскольку ключевое слово inline обычно делает то же самое, а встраивание функций в любом случае часто является преждевременной микрооптимизацией.

Во-вторых, имитировать вложенные функции на C или C ++. Это связано с тем, что вы «пишете функции, которые не нужно передавать во всех своих параметрах», но на самом деле могут быть немного более мощными, чем это.

3
ответ дан 18 December 2019 в 07:10
поделиться

Частью преимущества является репликация кода без конечных затрат на обслуживание - то есть вместо копирования кода в другое место вы создаете из него макрос и редактируете его только один раз ...

Конечно, вы также можете просто создать метод, который будет вызываться, но это своего рода дополнительная работа ... Я сам против частого использования макросов, просто пытаюсь представить потенциальное обоснование.

1
ответ дан 18 December 2019 в 07:10
поделиться

Для меня макросы - зло. С их таким количеством побочных эффектов и тем фактом, что в C ++ вы можете получить такой же прирост производительности с встроенным, они не стоят риска.

Например. посмотрите этот короткий макрос:

#define max(a, b) ((a)>(b)?(a):(b))

, затем попробуйте этот вызов:

max(i++, j++)

More. Допустим, у вас есть

#define PLANETS 8
#define SOCCER_MIDDLE_RIGHT 8

, если выдается ошибка, она будет относиться к «8», но не к любому из ее значимых представлений.

3
ответ дан 18 December 2019 в 07:10
поделиться

Очень длинные макросы будут иметь недостатки в производительности, такие как увеличенный размер скомпилированного двоичного файла, и, безусловно, есть и другие причины, по которым их не использовать.

Для наиболее проблемных макросов я бы подумал о запуске кода через препроцессор и заменяя вывод макроса вызовами функций (встроенными, если возможно) или прямым LOC. Если макросы существуют для совместимости с другими архитектурами / ОС, вы можете застрять.

2
ответ дан 18 December 2019 в 07:10
поделиться

Я вообще не использую макросы. Встроенные функции служат всем полезным целям, которые может выполнять макрос. Макрос позволяет делать очень странные и нелогичные вещи, например, разделять идентификаторы (как тогда кто-то ищет идентификатор?).

0
ответ дан 18 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: