因此,我try 实现了一个简单的词典,如这post中所示.但是,我确实修改了代码:

A)词典:

/* String utility for duplication */
char *strdup(char *s) /* make a duplicate of s */
{
    char *p;
    p = (char *) malloc(strlen(s)+1); /* +1 for ’\0’ */
    if (p != NULL)
       strcpy(p, s);
    return p;
}

struct nlist {
    struct nlist *next;
    char *name;
    char *defn;
};

#define HASHSIZE 101
struct Dict {
    struct nlist *hashtab[HASHSIZE];
};

/* hash: form hash value for string s */
unsigned hash(char *s)
{
    unsigned hashval;
    for (hashval = 0; *s != '\0'; s++)
      hashval = *s + 31 * hashval;
    return hashval % HASHSIZE;
}

/* lookup: look for s in hashtab */
struct nlist *lookup(struct Dict *d, char *s)
{
    struct nlist *np;
    for (np = d->hashtab[hash(s)]; np != NULL; np = np->next)
        if (strcmp(s, np->name) == 0)
          return np; /* found */
    return NULL; /* not found */
}

struct nlist *insert(struct Dict *d, char *name, char *defn)
{
    struct nlist *np;
    unsigned hashval;
    if ((np = lookup(d, name)) == NULL) { /* not found */
        np = (struct nlist *) malloc(sizeof(*np));
        if (np == NULL || (np->name = strdup(name)) == NULL)
          return NULL;
        hashval = hash(name);
        np->next = d->hashtab[hashval];
        d->hashtab[hashval] = np;
    } else /* already there */
        free((void *) np->defn); /*free previous defn */
    if ((np->defn = strdup(defn)) == NULL)
       return NULL;
    return np;
}

B)示例:

int main() {
    struct Dict *dtest = (struct Dict*)malloc(sizeof(struct Dict));
    insert(dtest, "hello", "world");
    // Look up a definition by name
    struct nlist *result = lookup(dtest, "hello");
    
    if (result != NULL) {
        printf("Definition for 'hello': %s\n", result->defn);
    } else {
        printf("'hello' is not found in the dictionary.\n");
    }

    return 0;
}

当我try 调试它时,收到以下错误:

线程%1收到信号SIGSEGV,分段故障. 正在查找中的0x00007ff6bc661626(d=0x220924616e0,S=0x7ff6bc673006"Hello").c:40 40if(strcMP(S,NP-&>名称)==0)

我只是不明白简单的代码修改怎么会产生这种意想不到的行为,坦率地说,我也不确定如何go 做.

推荐答案

在原始代码片段中,hashtab数组被声明为static,这意味着它的元素在程序开始时自动初始化为NULL.这是与动态分配内存(如malloc)的关键区别,在动态分配内存中,内容未初始化.

当您声明一个像static struct nlist *hashtab[HASHSIZE];这样的static指针数组时,默认情况下,此数组中的所有指针都被初始化为NULL.此初始化由系统在程序启动时、调用任何函数之前完成.这是C语言标准的一部分,该标准规定,如果没有提供显式的初始化式,具有静态存储持续时间的对象将被初始化为零(或对于指针为NULL).

因此,hashtab数组开始时其所有元素都设置为NULL,并且该数组不需要额外的初始化代码.

在您提供的前面的代码片段中,情况有所不同:

struct Dict {
    struct nlist *hashtab[HASHSIZE];
};

在您的代码中,hashtab是 struct 的成员,并且没有声明为static.当您使用malloc为此 struct 动态分配内存时,如下所示:

struct Dict *dtest = (struct Dict*)malloc(sizeof(struct Dict));

dtest内的hashtab数组不会自动初始化.malloc函数在不对其进行初始化的情况下分配内存,因此分配的内存的内容是不确定的.对于hashtab,这意味着它的指针可以指向任意的内存位置.

因此,对于此 struct ,必须显式初始化hashtab数组,以确保在使用它们之前,数组中的每个指针都设置为NULL.如果不这样做,可能会导致未定义的行为,例如当您try 通过这些未初始化的指针访问或修改数据时出现分段错误.

可以按如下方式进行初始化:

// Initialize the hash table
for (int i = 0; i < HASHSIZE; i++) {
    dtest->hashtab[i] = NULL;
}

此循环将hashtab数组中的每个指针设置为NULL,确保它们在使用前已正确初始化.

C++相关问答推荐

如何将匿名VLA分配给指针?

带双指针的2D数组

try 使用sigqueue函数将指向 struct 体的指针数据传递到信号处理程序,使用siginfo_t struct 体从一个进程传递到另一个进程

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

从内联程序集调用Rust函数和调用约定

为什么我得到更多的256假阳性在PKZIP解密密钥验证?

如何判断宏参数是否为C语言中的整型文字

在C中使用动态内存分配找到最小的负数

为什么内核使用扩展到前后相同的宏定义?

为什么STM32G474RE上没有启用RCC PLL

如何将字符**传递给需要常量字符指针的常量数组的函数

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

C I/O:在Windows控制台上处理键盘输入

Boyer Moore算法的简单版本中的未定义行为

C语言中的数字指针

为什么我的二叉树删除删除整个左部分的树?

Makefile无法将代码刷新到ATmega328p

将char*铸造为空**

为什么 int32_t 和 int16_t 在 printf 输出中具有相同的位数?

我怎样才能用c语言正常运行这两个进程?