为什么将链表指针传递给main()中的函数会影响main中的链表?

时间:2017-02-12 10:36:47

标签: c list pointers

我在C中编写程序。程序接收从标准输入到包含数据的文件的文件路径。然后根据数据构建链表。链表必须是循环的,但为了简单起见(用于添加节点,打印列表)我将循环列表转换为常规的非循环链表。这是通过uncirc函数完成的。最后,我使用circ函数将列表组装回循环结构。

我将指向链表的指针传递给函数printList,该函数打印列表的内容。但是,在uncirc内部使用printList后,列表实际上仍然是" unirc" -ed甚至是主要内容。据我所知,指针是按值传递的,因此对printList中的列表执行任何操作都不应影响原始列表。

代码如下(我只包含与问题相关的基本功能,否则代码会非常大)。我怀疑有一些你是否可以说我可以轻松打印列表,即使是圆形结构,但真正困扰我的是原始列表是从指针改变。

#include <stdio.h>
#include <stdlib.h>
#define MAX_FILE_NAME_LEN 300
#define MAX_LINE_LEN 300
#define MATERIAL_LEN 100
#define FIELDS_IN_LIGHTING_NUM 8

enum l_type {
    TABLE = 1, WALL, CEILING
};

typedef struct Lighting {
    enum l_type type;
    int length;
    int width;
    int height;
    int bulbs;
    char material[MATERIAL_LEN];
    int strength;
    struct Lighting * next;
} Lighting;

char * getFileName();
int getVolume(Lighting * light);
Lighting * uncirc(Lighting * light);
Lighting * circ(Lighting *light);
void addNode(Lighting **head,  FILE *fd);
void printNode(Lighting * light);
void printList(Lighting * light);
int countLines(FILE *fd);
void printMaxLight(Lighting * light);

int main() {
    FILE * fd;
    char * path;
    Lighting * n1 = NULL;
    int linesInFile, lightNum, i;
    path = getFileName();
    if(!(fd = fopen(path, "r+"))) {
        printf("Cannot open file %s\n", path);
        fprintf(stderr, "Cannot open file %s\n", path);
        exit(0);
    }

    linesInFile = countLines(fd);
    lightNum = linesInFile / 7;

    for(i = 0; !(feof(fd)) && i < lightNum; i++) {
        addNode(&n1, fd); //read file data and create node
                          //7 lines of data are required to create node                                                     
    }

    fclose(fd);
    printList(n1); //print the linked list
    return 0;
}

Lighting * uncirc(Lighting * light) {
    Lighting * p = light;

    if(p == NULL) {
        return p;
    }
    while(p -> next != light) {
        p = p -> next;
    }

    p -> next = NULL;
    return light;
}

Lighting * circ(Lighting *light) {
    Lighting * p = light;

    if(p == NULL) {
        return p;
    }
    while(p -> next != NULL) {
        p = p -> next;
    }
    p -> next = light;
    return light;
}

void printList(Lighting * light) {
    Lighting * p;
    p = uncirc(light);
    if(p == NULL) {
        printf("Empty list\n");
        return;
    }

    while(p != NULL) {
        printNode(p);
        p = p -> next;
    }
}

2 个答案:

答案 0 :(得分:2)

指针中的列表不是包含。只有第一个元素的地址存在。而且你不是要在任何时候修改main中指针所包含的地址。

如果传递第一个元素的地址,然后使用它来遍历列表并修改元素,那么当你再次使用相同的地址进行遍历时,它将自然可见。

旁注

while(p -> next != light) {

如果您传递的列表不是循环的,那么这将是一个无限循环。

答案 1 :(得分:2)

是&#34; 指针按值传递&#34;但指针指向的任何东西都是&#34;通过值&#34;传递。也就是说,列表本身不会被复制。

因此,如果更改函数中指向的列表,则只会更改列表!