2013-04-29 4 views
3

Рассмотрим две следующие строки кода:Есть ли разница между const char * const и const char []?

const char *ptr = "Hello"; 
char arr[] = "Hello"; 

Для определения указателя, то "Hello" строковый литерал, по существу неизменны, а сама переменная ptr может изменить и держать другой адрес.

Для определения массива, то "Hello" строка литерал копируется в местоположение массива, но arrне может точку в другое место; однако строка, удерживаемая массивом, является изменяемой и, следовательно, может быть изменена.

Теперь рассмотрим следующие две строки кода:

const char * const ptr = "Hello"; 
const char arr[] = "Hello"; 

Здесь обе строки неизменны в результате const char классификаторе - более интересно, хотя: с ptr определяется как постоянный указатель, его не может указать другой адрес.

Эти две строки кода приведут к одинаковому поведению? Если конечный эффект тот же, есть ли теоретическая разница в реализации - например, метод указателя выделяет память для анонимного массива для хранения строки в дополнение к самому указателю, тогда как метод массива выделяет память только для массив?

+8

Различия: 1. массивы не указатели, 2. указатели не являются массивами, 3. 'sizeof()' – 2013-04-29 21:21:11

ответ

4

Вот несколько отличий.

Во-первых, это может справедливы на некоторых реализациях как указатели могут указывать на ту же память:

const char * const ptr1 = "Hello"; 
const char * const ptr2 = "Hello"; 

ptr1 == ptr2; 

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

В любом случае, реальная разница в том, что их типы различны. В частности, версия char[] сохраняет свой размер в массиве. Таким образом, sizeof(arr) дает вам размер массива, а не указатель, и вы также можете создавать указатели на массивы до arr.

+0

Что касается «определенных реализаций», то в Visual Studio есть опция «String pooling» (параметр компилятора GF) , Обычно он отключен по умолчанию, но если вы его включите, то компилятор найдет в вашей программе все равные строковые литералы и превратит их в одну константу, тем самым сохранив некоторую память. Это уравнивает ptr1 и ptr2. –

2

Ну, есть хотя бы одна семантическая разница в том, что &ptr и &arr будут давать разные типы - один указатель на указатель и другой указатель на массив. Будь то на самом деле вопросов в любом месте, конечно, будет зависеть от того, как вы их используете. Для получения конкретных результатов проверьте код выходного компьютера из вашего компилятора.

+0

У меня возникли проблемы с пониманием различия между указателем * на указатель * и указателем * -array *. Будет ли 'sizeof (* (& arr))' задавать размер массива? –

+1

Да, я так думаю. Вы должны попробовать и посмотреть. Я бы порекомендовал проверить [раздел 6 of the comp.lang.c FAQ] (http://c-faq.com/aryptr/index.html), чтобы начать. –

+0

Да, я думаю, что этот раздел объясняет это отлично: http://c-faq.com/aryptr/ptrtoarray.html –

3

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

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

3
const char *ptr = "Hello"; 

Объявляет PTR, как константный указатель на символ, инициализируется, чтобы указать на строковый литерал «Hello». То, что указано в файле NOT, имеет тип const, хотя для реализации разрешено размещать его в постоянной памяти.

char arr[] = "Hello"; 

Объявляет обр как массив [6] полукокса, инициализируется {'H', 'e', 'l', 'l', 'o', '\0'}.

const char * const ptr = "Hello"; 

Объявляет PTR, как константный указатель на сопзЬ-голец, инициализируется, чтобы указать на строковый литерал «Hello». Хотя этот указатель объявлен как указывающий на константную память, сам литерал строки по-прежнему не имеет типа const, хотя по-прежнему разрешено помещать его в постоянную память.

const char arr[] = "Hello"; 

Объявляет обр, как константный массив [6] полукокса, снова инициализируется {'H', 'e', 'l', 'l', 'o', '\0'}.

Все разные, но я вижу, что другие уже предоставили лучшие ответы на ваш вопрос.

+0

Если я использую 'const char * ptr', теоретически я могу использовать второй указатель для доступа к той же ячейке памяти, чтобы изменить память? Это верно и для 'const char arr []'? –

+1

Вы всегда можете использовать второй указатель для отбрасывания типов, таких как 'const'ness. Это нарушение, однако, и иногда то, что указано на самом деле, будет немодифицировано (что приведет к сбоям программы), и любой полузащитный жизнеспособный компилятор будет предупреждать об этом. –

1

Для определения массива, то "Hello" строкового литерала копируется в расположение массива, но аранжировка не может указывать на другое место

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

char arr[] = { 'H', 'e', 'l', 'l', 'o', '\0' }; 

в качестве стандарта говорит:

Массив типа символа может быть инициализирован символьным строковым литералом или строковым литералом UTF-8, необязательно заключенным в фигурные скобки.

И массивы не «указывают», arrays are not pointers.

Эти две строки кода приведут к одинаковому поведению?

Нет, у них совершенно разные типы, по той же причине.

Метод указателя выделяет память для анонимного массива для хранения строки в дополнение к самому указателю, в то время как метод массива выделяет память только для массива?

Да и «анонимный» создан массив может быть использован повторно в другом месте, если та же строка буквальное используется (но в общем случае вы не можете знать, что на самом деле делает компилятор):

Не определено, являются ли эти массивы отличными, если их элементы имеют соответствующие значения.

Опять же, вторая строка представляет собой просто синтаксический сахар для инициализации массива.

Смежные вопросы