2017-01-12 3 views
0

Здравствуйте, извините, я некоторое время застрял в этом коде, и оба они работают, я просто не понимаю различий.Structs 'const char * x' vs 'char x [30]'

struct faveThings{ 

    const char *favFood; 
    const char *faveFriend; 


}; 

struct dog{ 

const char name[20]; 
const char breed[20]; 
int height; 
int weight; 

struct faveThings dogFaves; 

}; 

Я могу полностью понять структуру собаки, использование «char name [20]» имеет для меня весь смысл. Но с faveThings я борюсь с 'char * favFood', я понимаю, что это указатель, но как это может содержать строку, если это просто символ? Разве это не будет множество символов?

const char *favFood[20]; 

Благодарим за любую помощь. Я несколько часов стуча головой о стену, пытаясь найти разницу.

ответ

6

favFood не содержит нити. Он указывает где-то. И можно указать на символ, который является первым, в строке. По соглашению, поскольку строки c могут иметь разную длину, они заканчиваются символом '\0'. Таким образом, даже если все, что у вас есть, является указателем на первый символ, вы можете найти конец строки.

Таким образом, функция библиотеки, такая как strlen, будет использовать указатель для перехода от первого символа к каждому последующему, пока не найдет символ NUL.

const char *favFood[20]; - совершенно другой зверь. Это массив из 20 указателей. Каждый указатель может указывать на что-то другое.

+0

Я понял, что он указывает где-то, но я не понимаю, как это можно использовать для извлечения строки, например, я могу использовать ее для хранения «Мясо» и вернуть ее с помощью «theDog.dogFaves.favFood», shouldn 't это просто возвращает один символ' M ', а не строку? – fdbdcbc

+0

@ MGordon0405 - 'theDog.dogFaves.favFood' ничего не возвращает. Он ** оценивает ** на адрес первого символа в строке, а не на сам символ. – StoryTeller

+0

@ MGordon0405 - Забудьте о строках на данный момент. Вы понимаете, почему передать массив целых чисел функции, указатель на первый элемент и длина массива - это все, что нужно? – StoryTeller

1

Вы правы, что const char *favFood; действительно указывает на один char, но следует понимать, что будет блок памяти, содержащий последовательные char с, и что указатель указывает на первый. Таким образом, код может использовать этот указатель для доступа ко всем char s в блоке.

Код, который использует favFood, также предполагает выполнение выделения памяти, заполнение этой памяти символами (и нулевым терминатором) и просмотр favFood, чтобы указать на это выделение.

const char *favFood[20]; будет представлять собой массив из 20 указателей.

+0

Ах, спасибо, это имеет смысл. Цените помощь! – fdbdcbc

0

const char * favFood [20] представляет собой массив указателей, указывающих на данные кастратора.

Это походит

* favFood [1] --------> MemLocation (0x001) = а * favFood [2] --------> MemLocation (0x002) = б

и так далее, пожалуйста смотрите здесь также: Can I create an Array of Char pointers in C?

Я надеюсь, что ответ на ваш вопрос

0

Ниже массив постоянных символов. Он фактически содержит пять элементов, потому что язык C добавляет '\ 0' в конец строки, разделенной символами ". В C объект массива, такой как MEAT, фактически является указателем на первый элемент массива, поэтому MEAT на самом деле является адресом памяти, а не целым массивом символов!

const char[] MEAT = "Meat"; 

Ниже указателя к const char. Символ * сообщает вам, что это указатель.(Не имеет значения, ставите ли вы звезду по типу, на который указывает или по имени переменной. Это может сбивать с толку, поэтому я обычно храню информацию о типе вместе и имею имя самостоятельно, но я считаю, что это не является самым обычным соглашением.) Переменная favFood инициализируется адресом первого символа в массиве MEAT. (Помните, что MEAT является адресом памяти, так это установка одного адреса памяти равным другому.)

const char* favFood = MEAT; 

В какой-то момент в будущем, ваше животное может внезапно решить, что он больше не любит мясо, и теперь он на самом деле предпочитает печенье (более вероятно, что кошка изменит свое мнение, чем собака, я знаю, но это всего лишь пример).

const char BISCUITS[] = "Biscuits"; 

/* Some code is done here, until you find... */ 

favFood = BISCUITS; 

Теперь, как MEAT и BISCUITS постоянны, что означает, что вы не можете изменить их, но favFood сама по себе не постоянна, но указывает на постоянной строки (первый символ в строке в любом случае), так что вы можете изменить его !

Вы также можете иметь непостоянные строки:

char nameAndFaveFood[50]; 
sprintf(nameAndFaveFood, "%.26s likes %.9s best.", name, favFood); 

... но убедитесь, что вы не копировать больше символов - включая завершающий «\ 0» нулевой символ - чем вы выделили пространство, в этом случае 49 символов и терминатор. Вот почему функция sprint имеет спецификаторы точности для ограничения длины подстроки.

И вы можете иметь постоянные указатели на сменную память.

char* const LIKES_FOOD = &nameAndFaveFood[27]; 

Обратите внимание, что объект LIKES_FOOD инициализируется, чтобы указать часть пути через nameAndFaveFood массива. Он всегда укажет на этот адрес. Вы можете вызвать процедуру в предыдущем блоке кода с различными параметрами name и favFood, но LIKES_FOOD всегда укажет на 28-й символ в массиве nameAndFaveFood.

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