Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C结构中元素的顺序_C_Struct_Valgrind_Elements - Fatal编程技术网

C结构中元素的顺序

C结构中元素的顺序,c,struct,valgrind,elements,C,Struct,Valgrind,Elements,我对C非常陌生,我想知道结构中元素的顺序是否重要 我有以下结构: struct list { struct list_el *head; int size; } 我用这个来制作一个链表。头部指向第一个元素,大小显示列表中元素的数量 typedef struct list list; list* list_init() { list *list = malloc(sizeof(list)); if(list) { list->hea

我对C非常陌生,我想知道结构中元素的顺序是否重要

我有以下结构:

struct list
{
    struct list_el *head;
    int size;
}
我用这个来制作一个链表。头部指向第一个元素,大小显示列表中元素的数量

typedef struct list list;

list* list_init()
{
    list *list = malloc(sizeof(list));
    if(list)
    {
        list->head = NULL;
        list->size = 0;
        return list;
    }
    return NULL;
}
我还有以下函数来初始化列表

typedef struct list list;

list* list_init()
{
    list *list = malloc(sizeof(list));
    if(list)
    {
        list->head = NULL;
        list->size = 0;
        return list;
    }
    return NULL;
}
该程序编译得很好,没有任何错误、警告或注释,但当我使用valgrind运行该程序时,它会说我在
list_init()
函数中的行上有一个无效的大小为4的写操作,在该函数中,我将0分配给
list->size
。每次访问size变量时,我都有相同的无效读/写。我不知道为什么。另外,当我切换两个struct元素时(先声明
size
,然后声明
head
),我在行中得到无效的写入,我将NULL赋值给
head
,然后使用
size
变量。有人能解释一下为什么会发生这种情况,以及我如何解决它吗


最后注意:这里显示的结构是在头文件中定义的,而函数是在C文件中定义的。不确定这是否重要。

您使用与类型相同的名称命名变量,因此
sizeof(list)
实现为变量(指针)的大小,而不是结构的大小。该结构有一个指针和一个整数,因此大小将大于指针,因此发生了对未分配位置的访问

重命名变量

例如:

list *list_init(void)
{
    list *list_data = malloc(sizeof(list));
    if (list_data)
    {
        list_data->head = NULL;
        list_data->size = 0;
        return list_data;
    }
    return NULL;
}

使用类型名作为变量名是令人困惑的,因此我建议您更改变量名。一个好的编译器会警告(总是启用警告!)关于从外部作用域隐藏名称。警告不仅仅是为了显示一些奇特的消息。@Olaf:GCC 5.3.0在问题中的代码上运行:
GCC-O3-g-std=c11-Wall-Wextra-Werror-c ll97.c
不会对问题发出警告(这是一组非常严格的警告标志)。只有当你添加
-Wshadow
时,它才会抗议:
错误:“列表”的声明隐藏了一个全局声明[-Werror=shadow]
(一个错误是因为
-Werror
;否则,只是一个警告)。@JonathanLeffler:嗯,对不起,你是对的。刚刚检查了我的标准结构。我确实明确地包含了
-Wshadow
。错误的记忆,我真的认为是在
-Wextra
中。也许有太多的坏代码。@Olaf:因为我不经常编写与问题不符的代码(经过这么多年),所以我大部分时间都不使用
-Wshadow
。我定期使用更严格的选项对代码进行扫描,偶尔会出现,但不经常出现。对于其他人编写的代码,这很可能是一个问题。使用GCC和
-Wshadow
是一个好主意,尤其是在学习时。这是一个微妙的问题——这是一个相当合理的问题。