В чем разница между способами создания строки в C? - PullRequest
2 голосов
/ 20 сентября 2009

В чем разница между этими двумя формами строковой переменной в языке Си?

char *string1;
char string2[];

Есть ли другой способ сделать это?

Большое спасибо.

Ответы [ 3 ]

10 голосов
/ 20 сентября 2009

char *string1 = "foo";

string1 - указатель на строковый литерал (ради аргумента он указывает на последовательность символов, хранящихся в сегменте данных программы, доступном только для чтения).

char string2[] = "foo";

string2 - это массив из 4 символов. Инициализируется байтами 'f', 'o', 'o', ASCII_NUL.

Вероятно, наиболее существенным отличием является то, что если вы выполните string1[0] = 'b';, вы получите неопределенное поведение, потому что вы пытаетесь изменить сохраненное представление строковым литералом. Если вы сделаете string2[0] = 'b';, тогда вы измените свою личную строку на «boo», что хорошо.

Как правило, переменная типа char* является указателем на символ. Он часто используется, чтобы указывать на первый символ в NUL-концевой последовательности символов, и в этом случае он указывает на строку. Переменная типа char[] представляет собой массив символов. Если он имеет терминатор NUL, то он на самом деле является строкой.

Проблема слегка смущена двумя фактами:

1) В C всякий раз, когда имя переменной массива используется в контексте, который принимает указатель, он «означает» указатель на первый элемент массива. Таким образом, массивы и указатели часто считаются взаимозаменяемыми.

2) В C параметром функции типа char[] является , а не , фактически массив. Это просто указатель, точно такой же, как char*. Итак, опять же, массивы и указатели часто считаются взаимозаменяемыми.

Итак, еще одно различие между указателем и массивом:

string1 = "bar"; // changes string1 to point to another string literal.

string1 = string2; // changes string1 to point to the first character of string2.

string2 = string1; // doesn't compile - you can't assign to an array,
                   //   only initialize it and then modify element-by-element.

[Примечание: объявление char string2[]; в вопросе не является допустимым синтаксисом C в функции, но используемые мной определения будут действительными либо в функции, либо в области видимости файла, вне какой-либо функции. В любом случае они ведут себя так, как я описал для инициализации и назначения, но у них разные времена жизни.]

3 голосов
/ 20 сентября 2009

Они отличаются способом внутреннего представления, но почти аналогичны способу работы программиста.

Хотя char string2[]; - это массив символов, при непосредственном назначении компилятор понимает, что это набор символов, поэтому sizeof () возвращает размер массива (а не строки).

char *string1 - указатель на первый символ в строке. Он не содержит информации времени компиляции о том, что он содержит, и при запросе sizeof возвращает размер указателя (4 на 32 бита, 8 на 64 бита). Указатели обладают встроенным operator[] (переопределяемым в C ++), который заставляет их действовать как массивы.

Указатели являются более гибкими и могут изменять содержимое, на которое они указывают, в то время как массивы не могут. Единственный способ заполнить массивы - использовать strcpy, memcpy или аналогичное ручное копирование. Указатели могут быть свободно назначены первому и четному N-му элементу любой ячейки памяти, чтобы обеспечить большую гибкость в отношении содержимого.

0 голосов
/ 20 сентября 2009

1) * char string1; - указатель на (возможно) строку, тогда как

2) char string2 []; является более явным в том смысле, что имеется намерение указать на массив

В любом случае вам все равно нужно выделить память для хранения указанной строки. Я бы пошел с # 2 с точки зрения элегантности.

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