Указатели, массивы, строки и Malloc в C

#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));