Эквивалентные константные массивы и указатели - PullRequest
0 голосов
/ 08 июня 2018

Правда ли, что эквивалент

const char arr[2] = {0, 0};

равен

const char *const arr = "\0\0";

, но не

const char * arr = "\0\0";

Имеет ли массив массив const?Мои инстинкты говорят да, потому что вы не можете назначить массив другому.(arr = arr2; error: assignment to expression with array type)

Я спрашиваю, потому что я собираюсь использовать константу глобального массива.

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

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

С другой стороны, указатель является указателем или ссылкой на первый элемент массива - одну переменнуюассимилируется с массивом размера 1 для этой точки.Он не имеет представления о размере своего остроконечного массива, а размер указателя - это именно то, что нужно реализации для представления адреса памяти.Если T является типом и если int_ptr является допустимым в реализации, то верно следующее равенство:

sizeof(T *) == sizeof(int_ptr)

Указатель обычно может указывать на разные переменные или зоны памяти на протяжении всего своегопродолжительность жизни.Конечно, это может быть сделано const, и в этом случае изменение его значения вызовет неопределенное поведение, но может быть разрешено компилятором, в то время как вы никогда не сможете изменить положение массива.

Теперь для ваших примеров:

const char arr[2] = {0, 0};

arr - это истинный массив: arr = x; вызовет ошибку компиляции, а sizeof(arr) - это 2

const char *const arr = "\0\0";

arr - это константный указатель на const char.arr = x; будет отклонено, но (const char *) arr = x; будет принято во время компиляции (и вызовет UB во время выполнения).Но за исключением 16-битной среды sizeof(arr) - это не 2, а размер указателя (4 в 32-битной среде, 8 в 64-битной)

const char *arr = "\0\0";

arr - это указатель на constголец.arr = "abcd"; допустимо и будет arr указывать на другой строковый литерал другого размера.Его размер по-прежнему равен размеру указателя.


Не имеет отношения к вопросу, но есть другое важное различие между массивами и указателями в неконстантном случае использования:

char arr[2] = "a";

здесь arr - массив , инициализированный символами 'a' и '\ 0'.arr[0] = 'b'; допустимо

char *arr = "a";

здесь arr - указатель на литеральную строку.Поскольку буквенные строки являются константными, arr[0] = 'b'; вызывает UB.(современные компиляторы должны выдавать предупреждение для char *arr = "a";, но по причинам совместимости они не обязаны это делать)


Кстати, путаница между массивами и указателями заключается в том, что массив может автоматически преобразовываться в указатели при использованииих значение:

   char arr[] = "abc";    // array of size 4 

   f(arr);                // the f function receives a pointer to the first element of arr
0 голосов
/ 08 июня 2018

Случай 1: - Оператор

const char arr[2] = {0, 0}; 

Здесь arr - это массив из двух символов, и оба значения arr[0] и arr[1] инициализируются с помощью 0.const означает, что вы не можете изменить arr[0] & arr[1].например,

 int main(void) {
        const char arr[2] = {0, 0};
        arr[0] = 'a';/* not possible, by putting const in front you made arr[0] as read only */
        return 0;
}

Случай 2: - Оператор

  const char *const arr = "\0\0"; 

Здесь также arr[0] и arr[1] инициализируются с \0.Но этот синтаксис означает, что arr - это постоянный указатель и где он указывает, что данные также только для чтения т.е. вы не можете изменять arr[0] и вы не можете изменять arr.например,

int main(void) {
        const char *const arr = "\0\0"; 
        arr = "hello"; /*not possible, read only arr */
        *arr = 'a'; /* not possible, can't change the arr[0] */ 
        return 0;
}

Случай 3: - Оператор

const char * arr = "\0\0";

Здесь arr - это указатель на символ и где он указывает, на эту область памяти независимо от того,данные есть, то есть только для чтения , хотя это вызывает неопределенное поведение, но вы можете изменить arr, т.е. arr теперь указывает на "\0\0", оно также может указывать на другую область памяти.например,

int main(void) {
        const char * arr = "\0\0";
        arr++; /* possible bcz arr is not constant pointer */
        *arr = 'a'; /* not possible, can't change the arr[0] */
        return 0;
}

Имеет ли массив секретный констант? Нет, массив не является указателем , но его постоянный указатель , так как имя массива представляет базовый адрес, и это константа, т.е. вы не можете это изменить.например,

char arr1[] = "hello",arr2[10];

Здесь вы не можете сделать arr1 = arr2, потому что arr1 является указателем константы, т.е. не может изменить адрес, но вы можете изменить значение его элементов.

Обратите внимание, что const char arr[10]; и char arr[10]; различны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...