Передача указателя на struct в C?

#c #pointers #struct

#c #указатели #структура

Вопрос:

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

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

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

Заранее спасибо. -Крис

 #include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

struct memList
{
    int mem;
    struct memList* next;
};

void readDirectory(const char*, struct memList*);
void printHistogram(struct memList*, int binSize);



int main(int argc, char* argv[])
{
    struct memList* head = NULL;

    if (argc != 3)
    {
        perror("Not enough parametersn");
    }

    int binSize = strtol(argv[2], NULL, 10);

    readDirectory(argv[1], head);

    printHistogram(head, binSize);

    return 0;
}

void readDirectory(const char * passedDir, struct memList* head)
{
    DIR * directory = opendir(passedDir);

    if (directory == NULL)
            printf("Unable to open directoryn");

    while(1)
    {
        struct dirent * current;

        current = readdir(directory);
        if (!current)
            break;

        if ((current->d_type == 4) amp;amp; (strcmp(current->d_name, ".") != 0) amp;amp; (strcmp(current->d_name, "..") != 0))  //current path is directory but not the current or parent
        {
            char * path = malloc(sizeof(char) * 300);

            strcpy(path, passedDir);

            if (path[strlen(path) - 1] != '/')
                strcat(path, "/");
            strcat(path, current->d_name);

            readDirectory(path, head);

            free(path);
        }

        else
        {   
            char * path = malloc(sizeof(char) * 300);

            strcpy(path, passedDir);

            if (path[strlen(path) - 1] != '/')
                strcat(path, "/");
            strcat(path, current->d_name);

            struct stat tempStat;
            stat(path, amp;tempStat);

            free(path);

            int temp = tempStat.st_size;

            if (head == NULL)
            {   
                head = (struct memList*)malloc(sizeof(struct memList));
                head->next = NULL;
                head->mem = temp;
            }
            else
            {
                struct memList * tempStruct = (struct memList*)malloc(sizeof(struct memList));
                tempStruct->next = head;
                tempStruct->mem = temp;
                head = tempStruct;
                //printf("mem is %dn", head->mem);   //debugging
            }
        }

    }
    closedir(directory);
}

void printHistogram(struct memList* head, int binSize)
{
    int numElements = 10;

    int * array = (int*)malloc(sizeof(int) * numElements);
    for (int i = 0; i < numElements; i  )
        array[i] = 0;

    while(head != NULL)
    {
        //printf("mem is %dn", head->mem);   //debugging
        int temp = head->mem;
        int temp2 = ((temp - (temp % binSize)) / binSize);

        if ((temp2   1) > numElements)
        {
            int * new = realloc(array, (sizeof(int) * (temp2   1)));
            array = new;
            for (int i = numElements; i < (temp2   1); i  )
                array[i] = 0;
            numElements = (temp2   1);
        }

        array[temp2]  = 1;      

        head = head->next;
    }

    for (int i = 0; i < numElements; i  )
    {
        printf("%dn", array[i]);
        printf("Block %d:  ", i   1);
        for (int j = 0; j < array[i]; j  )
            printf("*");
        printf("n");
    }
}
  

Комментарии:

1. readDirectory(argv[1], head); head передается по значению.

2. Не имеет отношения к рассматриваемой проблеме, но вы можете захотеть использовать nftw вместо того, что вы делаете прямо сейчас.

Ответ №1:

Изучите «передача по ссылке» и «передача по значению». C передается по значению.

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

Комментарии:

1. Спасибо за помощь, ребята. Я изменил параметры заголовка функции с * на **, изменил переданные параметры с head на amp;head , и мой метод вызывает из head-> в (*head)-> После пары настроек моих формул программа, наконец, отлично работает. Я уверен, что это можно оптимизировать больше, как упомянутый выше nftw, но для начала я доволен этим.