Ответ 1
const char* ch = "hello";
похож на
static const char string_literal[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
const char* ch = &string_literal[0];
за исключением того, что каждый идентичный строковый литерал необязательно указывает на отдельное место в памяти.
То же самое возможно и для любого другого типа:
static int integer_list[] = { 1, 2, 3 };
int* i = &integer_list[0];
// or equivalently, just int* i = integer_list;
Теперь i[0]
- 1
, i[1]
- 2
, а i[2]
- 3
.
Существует специальный синтаксис для строковых литералов, потому что они так часто используются и так часто в контекстах, где нежелательно загромождать код фиктивными переменными.
Если у вас много кода, который использует статически назначенные массивы только для чтения целочисленного типа, вы можете скрыть шаблон с помощью шаблонов:
template <int a, int b, int c>
struct int_array { static const int values[3]; };
template <int a, int b, int c>
const int int_array<a, b, c>::values[] = { a, b, c };
Вам нужно только определить шаблон один раз, и каждый пользователь может использовать этот шаблон для конкретных значений, которые интересуют пользователя.
const int* i = int_array<1, 5, 6>::values;
Часто бывает проще просто определить отдельную переменную массива, но бывают случаи, когда такой шаблон помогает.
Как отмечено в комментариях, можно более подробно определять шаблон, чтобы он работал для массивов произвольного типа и произвольной длины, но для этого требуется современный компилятор с хорошей поддержкой текущей версии С++ (для GCC и clang текущие версии являются точными, но обязательно передайте параметр -std=c++11
или -std=gnu++11
, чтобы включить возможности С++ 11):
template <typename T, T... v>
struct static_array {
static const T values[sizeof...(v)];
};
template <typename T, T... v>
const T static_array<T, v...>::values[sizeof...(v)] = { v... };
Теперь синтаксис для пользователя этого массива
const int* i = static_array<int, 1, 2, 3, 4>::values;
const unsigned* j = static_array<unsigned, 1, 2, 3, 4, 5>::values;