Поведение, которое вы наблюдаете, явно указано стандартом.В
static const char pattern[] = "[SOME TEST PATTERN TO CALCULATE SUM FROM] ";
у вас есть объявление переменной pattern и инициализатор в виде строкового литерала. В параграфе 6.4.5 / 6 стандарта указано, что
На этапе 7 преобразования байт или код нулевого значения добавляются к каждой последовательности многобайтовых символов, которая получается из строкибуквальное или буквальное. Последовательность многобайтовых символов затем используется для инициализации массива статической длительности хранения и длины, достаточной только для размещения последовательности.
(выделение добавлено).То, что результирующий массив имеет статическую длительность хранения, означает, что, по крайней мере, в принципе, для него должна быть зарезервирована память в программе.Это то, что вы видите в форме str1.1
.Но вы также используете эту строку для инициализации массива, так что массив получает ту же последовательность символов, которая также занимает память в двоичном файле, потому что она также имеет статическую продолжительность хранения в результате объявления в области видимости файла.
В принципе, GCC должен иметь возможность оптимизировать дополнительный массив.В частности, опция -fmerge-constants
должна делать это, но она включена на всех уровнях оптимизации, кроме -O0
, поэтому удивительно, что вы не видите такого объединения, но возможно, что объединение будет выполнено во время соединения,так что то, что вы видите, является бессмысленным артефактом просмотра объектного файла перед компоновкой.
Вы также сможете избежать копирования, объявив pattern
указателем вместо массива:
static const char * const pattern = "[SOME TEST PATTERN TO CALCULATE SUM FROM] ";
, но NOTE WELL , что хотя результат может использоваться многими из тех же способов, что и версия массива, он не является семантически идентичным.Вы увидите разницу, если вы примените оператор sizeof
, *
, или &
, или _Alignof
к pattern
.
Обновление:
Другой,гораздо страшнее, обходным путем было бы вообще избежать строкового литерала, например так:
static const char pattern[] = {
'[', 'S', 'O', 'M', 'E', ' ', 'T', 'E', 'S', 'T', ' ', 'P', 'A', 'T',
'T', 'E', 'R', 'N', ' ', 'T', 'O', ' ', 'C', 'A', 'L', 'C', 'U', 'L',
'A', 'T', 'E', ' ', 'S', 'U', 'M', ' ', 'F', 'R', 'O', 'M', ']', ' ', '\0' };
Это оставляет вас с pattern
в качестве массива, а не указателя и без отдельного массива для строкового литерала.Это некрасиво и сложнее в обслуживании, но преобразовать строковую буквальную форму в такую несложно - мне потребовалось около 30 секунд, чтобы это сделать.Однако, если вы сделаете это, не забудьте добавить явный терминатор строки, как указано выше.