全局指针值丢失。 2个c档

时间:2015-08-31 09:50:39

标签: c pointers global-variables

我正在使用3个文件制作trie:speller.c是主文件,dictionary.c包含函数& global root trie pointer,dictionary.h声明了一个字典的函数。 在dictionary.c中完成函数加载后,全局根指针值出现问题。

speller.c

int main(int argc, char* argv[])
{   
    // load dictionary
    char* dictionary = TMPDICT;

    bool loaded = load(dictionary);

    // abort if dictionary not loaded
    if (!loaded)
    {
        printf("Could not load %s.\n", dictionary);
        return 1;
    }

    //next I need to call check function, but root value is missing here

}

dictionary.c

typedef struct TrieNode
    {
      struct TrieNode **children;
      bool is_word;
    } TrieNode;
struct TrieNode * root;


struct TrieNode *create_trienode(char c, struct TrieNode *parent);
bool load(const char* dictionary)
    {

        FILE * file = fopen(dictionary, "r"); 
        if (file == NULL) 
        {
            printf("trie: No such file(dictionary)\n"); 
            return 1;
        }

        struct TrieNode *root = create_trienode(' ', NULL);
        struct TrieNode *ptr = root; 
        int character;
        int converted;
        int buffer;

        //This handles if file does not end with a newline
        character = fgetc(file);
        buffer = fgetc(file);

        while(character != EOF)
        {
            character = tolower(character);
            if (character == 10) // if newline, start new word read
            {

            }
            else 
            if(isalpha(character))
            {
                converted = character - 'a'; 
                if(ptr->children[converted] == NULL)
                {
                    ptr->children[converted] = create_trienode(character, ptr); 
                }
            ptr = ptr->children[converted]; 
            }


        if (character == SLASHNUM) //if backslash
        {
            if(ptr->children[SLASH_TMP] == NULL)
            {
                ptr->children[SLASH_TMP] = create_trienode(character, ptr);
            }
            ptr = ptr->children[SLASH_TMP];
        }

        if(ptr != root && (!(character == SLASHNUM  || isalpha(character)) || buffer == EOF)) 
        {
            ptr->is_word = true;
            ptr = root;
            word_count++;
        }

          character = buffer;
          buffer = fgetc(file);
        }

       return true; 
    }


struct TrieNode *create_trienode(char c, struct TrieNode *parent)
{
    struct TrieNode *node = malloc(sizeof(struct TrieNode));
    node->children = malloc(ALPHABET_SIZE * sizeof(struct TrieNode*));
    node->is_word=false;

    for (int i = 0; i < ALPHABET_SIZE; i++)
    {
        node->children[i] = NULL;
    }

    return node; 
}

GDB

Breakpoint 1, load (dictionary=0x80489c4 "tmpDict") at dictionary.c:100
100     character = fgetc(file);
(gdb) info locals
file = 0x804b008
root = 0x804b170
ptr = 0x804b170
character = 1267019363
converted = 262929407
buffer = 1266804984
(gdb) c
Continuing.

Breakpoint 2, main (argc=1, argv=0xbffff0d4) at speller.c:40
$1 = (struct TrieNode *) 0x0
(gdb)

如何在speller.c中显示root?另外在任务中说我不能改变speller.c

2 个答案:

答案 0 :(得分:5)

通常,您需要在 dictionary.h 文件中将root声明为extern,并将该头文件包含在 speller.c

这样,root将可用于翻译单元 spleller.c 。接下来,您可以在 speller.c 中使用root,就像任何其他本地变量(在该文件本身中已定义)一样。

[正如Mr. alk在以下评论中正确指出的那样]

问题此处本地 root变量的定义

 struct TrieNode *root = create_trienode(' ', NULL);

load()函数内实际阴影全局root

struct TrieNode * root;`

因此,全局root永远不会更新。

相关,来自C11标准,章节§6.2.1(强调我的

  

[...]如果标识符指定同名的两个不同实体   空间,范围可能重叠。如果是这样,一个实体的范围(内部范围)将结束   严格地在另一个实体的范围之前(外部范围)。 在内部范围内,   identifier指定在内部作用域中声明的实体;在外部宣布的实体   范围在内部范围内隐藏(并且不可见)。

答案 1 :(得分:1)

您的代码定义root两次,其中load()的本地定义会影响全局定义。

这一行

struct TrieNode *root = create_trienode(' ', NULL);

在本地定义root,并将create_trienode()的结果分配给root的本地定义。

根据root on的本地定义,全局定义的root会被本地定义,并且无法再访问。

要解决此更改:

    struct TrieNode *root = create_trienode(' ', NULL);
    struct TrieNode *ptr = root; 

    struct TrieNode *ptr= create_trienode(' ', NULL);
    root = ptr;