c - 取消引用数组中结构中字符串的 C 指针?

标签 c pointers struct dereference

我有一个棘手的 C 语法问题。我正在构建一个链表数组,其中列表中的每个节点都由一个结构表示。每个结构体保存一个字符串,这在后面很重要:

// "linkedList.h"

typedef struct llnode listnode;
struct llnode {
    char* data;     // string
    // ...and other data
};

我的代码构建了一个指向这些“列表节点”的指针表,并将所有这些指针设置为 NULL,原因超出了本文的范围:

void initTable(listnode** table){
    // Initialize all pointers in the table to NULL
    for (int i = 0; i < TABLESIZE; i++)
        table[i] = NULL;
}

int main(){    
    // Create table of linked lists
    listnode** table = (listnode**) malloc(TABLESIZE * sizeof(listnode*));
    initTable(table);

    return 1;
}

到目前为止,还不错。稍后,我的程序将数据填充到表中,并在必要时添加到正确的链表中。执行此操作的代码有效,但为了使我的帖子尽可能简短,我将在此处提供一个高度简化的版本:

void insert(listnode** table, int index, char* newData){
    if(*(table+index)==NULL){
        // Create the new Node
        listnode *newNode = NULL;
        newNode = (listnode*)malloc(sizeof(listnode));  // allocate for the struct
        newNode->data = (char*)malloc(sizeof(char)*15); // allocate for the string within the struct
        strcpy(newNode->data, newData);                 // copy newData into newNode->data

        // Insert node into table (Super simple version)
        *(table+index) = newNode;
    }
}

int main(){
    listnode** table = (listnode**) malloc(TABLESIZE * sizeof(listnode*));
    initTable(table);

    insert(table, 0, "New String A");
    insert(table, 5, "New String B");
    insert(table, 7, "New String C");

    return 1;
}

这一切都很好。现在问我真正的问题……假设我想进入表格并取消引用其中一个字符串?

void printTable(listnode** table){
    for(int i=0; i<TABLESIZE; i++){
        if(*(table+i)==NULL)
            printf("table[%d]  ==  NULL\n", i);
        else
            printf("table[%d]  ==  %s\n", i, **(table+i)->data);  // << PROBLEM IS HERE!
    }
}

int main(){
    // create & initialize the table, as above
    // insert data into the table, as above
    printTable(table);

    return 1;
}

编译器不喜欢我的语法:

$ gcc -Wall linkedList.c
linkedListc: In function ‘printTable’:
linkedList.c:31:48: error: request for member ‘data’ in something not a structure or union
    printf("table[%d]  ==  %s\n", i, **(table+i)->data);
                                                ^
$

所以我知道对于一个简单的问题来说这是一个冗长的前提,但是有人可以在这里帮助我使用正确的语法吗?我尝试了多种语法变体,但没有成功。

更令人费解的是,当我稍微修改代码编译它时,然后在 GDB 中查看这个,我可以看到 **(table+i) 是我的结构,但是 **(table+i)->data 不可访问。这是我调试(修改后的)程序时的 GDB 输出;表示“New String A”的节点首先插入表中的索引 0 处。 :

31           printf("table[%d]  ==  %d\n", i, **(table+i));
(gdb) p *(table+i)
$1 = (listnode *) 0x6000397b0
(gdb) p **(table+i)
$2 = {data = 0x6000397d0 "New String A"}
(gdb) p **(table+i)->data
Cannot access memory at address 0x4e
(gdb)

我真的很困惑。一旦一个 C 指针经历了不止一层的取消引用,我就开始怀疑了。有人知道这里的正确语法是什么吗?

感谢一百万, -皮特

PS - 为这篇超长的帖子道歉。我发誓我努力将它保持在可管理的大小......

最佳答案

给出声明

listnode **table;

则以下表达式具有指定的类型

   Expression             Type
   ----------             ----
        table             listnode **
    table + i             listnode **
       *table             listnode *
 *(table + i)             listnode *
     table[i]             listnode *
**(table + i)             listnode
    *table[i]             listnode   

因此,您将使用以下表达式之一来访问 data 成员,从最难看的到最难看的:

table[i]->data      // use this, please
(*table[i]).data
(*(table + i))->data
(**(table + i)).data

分组括号是必需的 - .-> 成员选择运算符的优先级高于一元 *,因此 * table[i].data 将被解析为 *(table[i].data),这不是您想要的。

关于c - 取消引用数组中结构中字符串的 C 指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39923870/

相关文章:

c - 使用 GNU GCC 编译器编译 C 项目时出现 "undefined reference to "错误

函数中的 C 指针

c++ - 取消引用无效指针但不使用结果是 C++ 中的未定义行为吗?

c++ - 存储两个不同值的相同内存位置

c - 为什么 struct BMPFILE_ 类型不完整?在C中

c# - 互操作 C# 到 C++ 结构

c++ - 如何在 Cuda 中使用 struct inside struct

c - 如何让X11窗口跨越多个显示器

c - 通过引用传递并将值赋给结构指针的指针

c - Visual Studio 将不完整数组视为零长度数组