2017-01-17 12 views
1

What is the difference between char s[] and char *s?Зачем возвращать заданную ошибку в C?

Я привел пример двух кодов на основе данной ссылки. Предположим getstring() функцию.


char *str = "GfG"; /* "GfG" is stored in read only part of shared segment */ 
/* str has auto storage duration,so stored on the stack 
/* No problem: remains at address str after getString() returns*/ 
return str; 

И

char str[] = "GfG"; /* "GfG" is stored in read only part of shared segment */ 
/* str has auto storage duration,so stored on the stack. 
/* Problem: string may not be present after getSting() returns */ 
return str; 

Поскольку оба имеют автоматическую продолжительность хранения и обе переменные, хранящиеся на сегмент стека.

Тогда почему возвращение ули работает первого один на, а не для второго?

+3

Первый возвращает указатель на строковый литерал статического времени жизни, который не будет уничтожен, когда останется область 'getString()'. Однако во втором «GfG» 'на самом деле не является строковым литералом и не имеет статического времени жизни, это время жизни связано с областью, в которой оно было выделено. Таким образом, указатель, возвращаемый вторым, будет недействительным, и попытка прочитать его вызовет неопределенное поведение. – George

+0

Если вы определяете 'str []' как 'static char', он не будет уничтожен при выходе из функции. –

+0

проверить это http://stackoverflow.com/questions/9970295/life-time-of-string-literal-in-c – Karthick

ответ

4

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

char *str - указатель. Он указывает на строковый литерал. Длительность хранения литерала статична. Возвращаясь str, вернет адрес литерала (возвращается содержимое str), все в порядке.

char str[] - это локальный массив. Он инициализируется из литерала. Но продолжительность всего буфера автоматическая. Когда вы возвращаете его, он распадается на указатель (возвращается адрес str). Буфер выходит за пределы области действия, так что адрес приводит к оборванному указателю.

2

Строковые литералы имеют срок службы всего исполнения программ, они никогда не выходят за рамки. Поэтому указатели на них всегда будут работать.

Как вы отметили, массив во втором примере имеет автоматическое хранилище и выходит из области действия после возвращения функции, указатель, который вы возвращаете, недействителен.


И небольшая заметка о комментариях в вашем примере массива:

char str[] = "GfG"; /* "GfG" is stored in read only part of shared segment */ 

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

Определение и инициализация выше массива эквивалентно

char str[4] = { 'G', 'f', 'G', '\0' }; 

Я надеждой комментарий является то же самое на примере массива, как на примере указателя из-за плохой копией наклеивать?

+0

Там _might_ быть строковым литералом, участвующим в инициализации массива. C11 6.7.9/14: 'Массив типа символа может быть инициализирован литералом строковой буквы или строковым литералом UTF-8, необязательно заключенным в фигурные скобки.'. Пример с clang: https://godbolt.org/g/j6Q052 –

2

В первом фрагменте кода переменная str объявлена ​​как

char *str = "GfG"; 

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

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

Во втором случае объявляется локальный массив

char str[] = "GfG"; 

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

Вы можете достичь того же эффекта с массивом символов, как с строкового литерала в первом фрагменте кода, если объявить его как

static char str[] = "GfG"; 

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