2015-10-12 2 views
1

Есть ли разница в назначении адреса строкового литерала указателю на символ?Назначение адреса строкового литерала указателю

char *ptr = &"Hello"; 
printf("%s",ptr); 

При печати напечатано «Hello» правильно. Это похоже на присвоение адреса массива указателю? Существует ли использование назначения адреса таким образом? Что такое & «Привет» возвращается? Постоянный указатель на символ?

char a[]="Hi"; 
char *ptr2 = &a; 

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

for(i=0;i<((&a+1)-&a);i++) printf("%c",*ptr2++); 

ответ

3
char *ptr = &"Hello"; 

Ваш компилятор должен был предупредить вас об этом. "Hello" имеет тип char[6] (длина строки плюс 1 для завершающего '\0' null символ). Таким образом, &"Hello" имеет тип char (*)[6], или указатель на массив из 6 char. Нет никакого неявного преобразования из этого типа в char*.

Если вы хотите указатель на строку, падение &:

const char *ptr = "Hello"; 

Это использует правило, что выражение типа массива (например, "Hello" неявно преобразуется в указатель на массив сначала элемент. (Это преобразование не выполняется, если массив является операнд одноместной & или sizeof оператора, или строковый литерал используется для инициализации объекта массива.)

(я добавил const, потому что это безопаснее , вы не можете юридически изменять содержимое o f строковый литерал, а const напоминает компилятору, чтобы вы не попробовали. Спасибо, что напомнили мне Батшеву.) (На самом деле изменение содержания имеет неопределенное поведение.)

Вы заметите, что ptr указывает на первый символ строки, а не на всю строку. Это (возможно) именно то, что вы хотите. В C массив обычно обрабатывается с помощью указателя на его элементы, а не с помощью указателя на весь массив.Арифметика указателя используется для перемещения массива и доступа ко всем его элементам.

Важно помнить, что при построении указателя на исходный элемент массива не запоминается размер массива. Вы должны сами следить за этим. Если массив содержит строку, вы обычно будете искать завершающий '\0' или использовать функцию, которая делает это. Для других массивов обычно хранить длину отдельно. Например, функция может принимать два аргумента, адрес начального элемента массива и целое число (size_t), содержащее количество элементов.

Предлагаемое чтение: Раздел 6 comp.lang.c FAQ.

+3

Плюс один, хотя я бы скорее посмотрел 'const char * ptr'. – Bathsheba

+0

@ Батшеба: Хорошо, я обновил свой ответ. –

4
char *ptr = &"Hello"; 

Это не является действительным. Компилятор выдает предупреждение.

Тип "Hello" - char[6] и тип &"Hello" - char(*)[6]. Объявить и инициализировать ptr как это -

char (*ptr)[6] = &"Hello";  // ptr is pointer to array of char of size 6 

В for цикл, ваше состояние -

i<((&a+1)-&a); // it should be i<(*(&a+1)-a); 

Но не делать этого, как он вызывает неопределенное поведение.

To know more about it refer here.

+0

Заметил, что предупреждение компилятора отключено. Теперь я получаю предупреждение по крайней мере. –

+0

@JonWheelock Ну, вы всегда должны включать предупреждение компилятора :) – ameyCU

+0

Также просто для любопытства, как распечатать адрес (& a) +1 вместо & a + 1? Если я помещаю скобки, он все равно печатает значение адреса за границей массива. Например, в приведенном ниже коде, я хочу, чтобы последний оператор печати отображал 0028FF05, а не 0028FF10. Является ли добавление константы в (ptr *) [] недопустимым? char a [] = "Hello World"; char (* ptrToEntireArray) [] = & a; Е ("& ptrToEntireArray =% р \ п", &a); Е ("& ptrToEntireArray + 1 =% р \ п", (&a)+1); Результаты: & ptrToEntireArray = 0028FF0 & ptrToEntireArray + 1 = 0028FF10 –

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