Инициализация массивов типа char - PullRequest
2 голосов
/ 01 июня 2011

Я хочу инициализировать произвольные большие строки.Это строка символов с нулевым символом в конце, но я не могу напечатать ее содержимое.Кто-нибудь может сказать мне, почему?

char* b;
char c;
b = &c;
*b = 'm';
*(b+1) = 'o';
*(b+2) = 'j';
*(b+3) = 'a';
*(b+4) = '\0';
printf("%s\n", *b);

Ответы [ 8 ]

10 голосов
/ 01 июня 2011

Ваше решение вызывает неопределенное поведение , поскольку *(b+1) и т. Д. Находятся за пределами переменной стека c.Поэтому, когда вы пишете им, вы пишете по всей памяти, которой у вас нет, что может вызвать всевозможные искажения.Кроме того, вам необходимо printf("%s\n", b) (printf ожидает указатель для %s).

Решение зависит от того, что вы хотите сделать.Вы можете инициализировать указатель на строковый литерал:

const char *str1 = "moja";

Вы можете инициализировать массив символов:

char str2[] = "moja";

Это также можно записать как:

char str2[] = { 'm', 'o', 'j', 'a', '\0' };

Или вы можете вручную присвоить значения вашей строке:

char *str3 = malloc(5);
str3[0] = 'm';
str3[1] = 'o';
str3[2] = 'j';
str3[3] = 'a';
str3[4] = '\0';

...

free(str3);
2 голосов
/ 01 июня 2011

Это может привести к ошибке сегментации!* (b + 1), * (b + 2) и т. д. относятся к нераспределенным областям.Сначала выделите память, а затем запишите в нее!

1 голос
/ 01 июня 2011

printf не печатает, потому что ожидает символ *, поэтому вы должны передать b, а не * b.Чтобы инициализировать указатель на строковую константу, вы можете сделать что-то вроде:

char *s1 = "A string"

или

char s2[] = "Another string"

или выделить буфер сchar *b = malloc(5) и затем запись в этот буфер (как вы сделали, или с помощью строковых функций)

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

1 голос
/ 01 июня 2011
printf("%s\n", *b);

почему *?

printf("%s\n", b);

это то, что вы хотите

1 голос
/ 01 июня 2011

Ваш код вообще не безопасен! Вы выделяете только 1 символ в стеке с char c;, но записываете в него 5 символов! это даст вам переполнение стека, что может быть очень опасно.

Еще одна вещь: вы не должны разыменовывать строку при печати: printf("%s\n", b);

Почему бы просто не написать const char *b = "mojo";?

1 голос
/ 01 июня 2011

Если вы напишите следующее вместо printf, он напечатает первый символ.

printf("%c\n", *b);

Для того, чтобы у вас были произвольно большие строки, вам нужно будет использовать библиотеку, такую ​​как bstring или напишите свой собственный.

Это потому, что в C нужно получить память, использовать ее и, соответственно, освободить.b в вашем случае указывает только на символ, если вы не выделите ему память, используя malloc.А для malloc вы должны указать фиксированный размер.

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

1 голос
/ 01 июня 2011

b не хватает места для всех этих символов. Выделите достаточно места с помощью malloc или объявите b как массив char.

1 голос
/ 01 июня 2011

Вам необходимо назначить для нее пространство памяти либо с помощью malloc, либо с использованием статического массива. Здесь, в вашем коде, вы используете адрес только одного символа для хранения по адресам этих символов, и других, следующих за ним. Это не определено.

Обратите внимание, шаг за шагом, что вы делаете. Сначала вы назначаете указатель, указывающий на один символ в памяти. Затем, используя *b = 'm', вы устанавливаете в памяти символ «m». Но затем вы получаете доступ к следующей позиции памяти (которая не определена, потому что для этой позиции не зарезервирована память), чтобы сохранить другое значение. Это не сработает.

Как это сделать?

У вас есть два варианта. Например:

char *b;
char c[5];
b = &c[0];
*b = 'm';
... //rest of your code

Это будет работать, потому что у вас есть место для 5 символов в c. Другой вариант - напрямую назначить память для b, используя malloc:

char * b = (char*) malloc(5);
*b = 'm';
... // rest of your code

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

char c[] = "hello";
const char* b = "abcdef";
...