Date Редакция Категория comp Теги C

Рассмотрим следующий пример:

char * strA = "somestring";

strA является указателем (char *) на место в памяти, содержащее строковую константу (литерал) "somestring″.

Обычно компиляторы размещают такие константы в области памяти, доступной только для чтения — сегменте данных. Поэтому попытка изменить strA приведет к ошибке времени выполнения:

char * strA = "somestring";
strA[0] = 'x'; //runtime error

Заметим также, что strA, как указатель, хранится в стеке.

Следующий пример, напротив, будет скомпилирован и выполнен без ошибок:

char strB[] = "somestring";
strB[0] = 'x';

strB является массивом символов (char []). По команде char strB[] = "somestring"; компилятор резервирует буфер достаточного для хранения "somestring" размера в области памяти доступной для чтения и записи, и копирует в этот буфер инициализирующее выражение ("somestring").

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

Путаница между char* и char[] возникает, поскольку допустима запись вида:

void some_func(char * strSomeString)
{
    return;
}

int main()
{
    char * strA = "somestring";
    char strB[] = "somestring";

    some_func(strA);
    some_func(strB);

    return 0;
}

В some_func() пользователь получает доступ к содержимому буфера, на который указывает strSomeString. Если пользователь захочет изменить содержимое этого буфера, когда в some_func() передается strA, то он получит ошибку времени выполнения.

Вместо char * в качестве типа параметра функции можно указать char [], однако проблемы это не решит: по-прежнему при передаче в функцию strA будем получать ошибку времени выполнения

void some_func(char strSomeString[])
{
    strSomeString[0] = 'x';
    return;
}

int main()
{
    char * strA = "somestring";
    char strB[] = "somestring";

    some_func(strA);
    some_func(strB);

    return 0;
}

Разница между char* и char[] видна и при использовании sizeof():

char * strA = "somestring";  //sizeof(strA) = 4
char strB[] = "somestring";  //sizeof(strB) = 11

Так как strA — указатель, то sizeof() и возвращает размер указателя. strB, напротив, является массивом из 10 символов "somestring" и '\0', обозначающего конец строки.

Таким образом sizeof() — плохое решение для подсчета числа символов в строке, с этой целью лучше использовать strlen():

char * strA = "somestring";  //strlen(strA) = 10
char strB[] = "somestring";  //strlen(strB) = 10


Комментарии

comments powered by Disqus