#c #arrays #string #pointers #malloc
#c #массивы #строка #указатели #malloc
Вопрос:
В настоящее время я изучаю строки, указатели и массивы в C. Я попытался написать программу, в которой массив содержит три указателя на строковые адреса. Кажется, что все это работает, но программа ведет себя странно.
Вот код:
char** getUserDetails()
{
char* host = "localhost";
char* username = "root";
char* password = "mypassword";
// create array for holding pointers to strings
char *userDetailsHolder[3];
userDetailsHolder[0] = malloc(sizeof(char)*strlen(host));
strcpy(userDetailsHolder[0], host);
userDetailsHolder[1] = malloc(sizeof(char)*strlen(username));
strcpy(userDetailsHolder[1], username);
userDetailsHolder[2] = malloc(sizeof(char)*strlen(password));
strcpy(userDetailsHolder[2], password);
return userDetailsHolder;
}
int main()
{
char** userDetails = getUserDetails();
printf("Host: %snUsername: %snPassword: %sn", userDetails[0], userDetails[1], userDetails[2]);
printf("Host: %snUsername: %snPassword: %sn", userDetails[0], userDetails[1], userDetails[2]);
return 0;
}
Вывод: вывод указывает на то, что что-то пошло ужасно неправильно
Host: localhost
Username: root
Password: mypassword
Host: root
Username: localhost
Password: Host: %s
Username: %s
Password: %s
Первое printf
вроде бы работает, но во втором содержатся неправильные данные. Что я сделал не так?
Ответ №1:
Проблема в том, что вы возвращаете указатель на массив, который находится в стеке. userDetailsHolder
выделяется в стеке и становится недоступным после возврата функции.
Вы могли бы использовать malloc
еще раз для выделения самого массива, и тогда он будет доступен после возврата функции.
Комментарии:
1. Спасибо, это имеет смысл. Однако я никогда этого не делал. Я попытался добавить следующий код:
2. char** arrayOnStack = malloc(sizeof(userDetailsHolder)); arrayOnStack = userDetailsHolder; возвращает arrayOnStack;
3. Новый код будет
char **userDetailsHolder = malloc(sizeof(char *) * 3)
4. Привет, спасибо, работает отлично. Есть ли какое-то правило, которое вы используете, чтобы отслеживать все отмены ссылок? Будучи новичком, я нахожу довольно запутанным понимание того, на каком уровне я нахожусь..
5. Это довольно просто, когда вы это понимаете… Каждая звездочка в объявлении указателя соответствует одному разыменованию. Например, если вы объявили
int *****a
, выражение**a
выдаст указатель типаint ***
.
Ответ №2:
Также не забудьте выделить strlen(s) 1
байты для строк. Строки C заканчиваются нулевым байтом, и вам нужно убедиться, что для него есть место.
Комментарии:
1. Спасибо, я уже добавил это в код: userDetailsHolder[0] = malloc(sizeof(char)*(strlen(host) 1));