Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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_Memory_Compilation_Malloc - Fatal编程技术网

当我错过了C中的动态内存分配时,为什么不出现编译错误?

当我错过了C中的动态内存分配时,为什么不出现编译错误?,c,memory,compilation,malloc,C,Memory,Compilation,Malloc,假设我正在尝试编写一个函数,用C语言创建一个简单的链表 功能如下: node* createLinkedList(int n) { int i = 0; node* head = NULL; node* temp = NULL; node* p = NULL; for (i = 0; i < n; i++) { //create isolated node temp = malloc(sizeof(node))

假设我正在尝试编写一个函数,用C语言创建一个简单的链表

功能如下:

node* createLinkedList(int n) {

    int i = 0;
    node* head = NULL;
    node* temp = NULL;
    node* p = NULL;

    for (i = 0; i < n; i++) {

        //create isolated node

        temp = malloc(sizeof(node));
        printf_s("\nEnter the data for node number %i:", i);
        scanf_s("%d", &(temp->data));
        temp->next = NULL;

        if (head == NULL) {
            //if list is empty then make temp as first node
            head = temp;
        }
        else {
            p = head;
            while (p->next != NULL)
                p = p->next;
            p->next = temp;
        }
    }
    return head;
}
如果我故意删除temp=mallocsizeofnode行;这个程序编译得很好,但我显然遇到了一个运行时错误

我的问题是:编译器不应该警告我没有为temp变量分配内存吗?是隐式分配内存吗?如果是,如何分配?

根据定义,malloc不会隐式分配内存。此函数的目的是返回一个有效的内存地址,编译器显然无法验证该地址,因为它将在运行时调用

此时,编译器只假设指针是有效的。它无法猜测指针是否已经指向有效的内存地址。

根据定义,malloc不会隐式分配内存。此函数的目的是返回一个有效的内存地址,编译器显然无法验证该地址,因为它将在运行时调用

此时,编译器只假设指针是有效的。它无法猜测指针是否已经指向有效的内存地址

编译器不应该警告我没有为temp变量分配内存吗

没有。分配在运行时完成。编译器最多只能在变量未初始化时发出警告。这就是为什么我认为初始化指向NULL的指针是个坏主意的原因

$ cat main.c
int main(void)
{
    int *p;
    *p =42;
}

$ gcc main.c -Wall -Wextra
main.c: In function ‘main’:
main.c:4:8: warning: ‘p’ is used uninitialized in this function [-Wuninitialized]
    4 |     *p =42;
      |     ~~~^~~
如果你改变int*p;到int*p=NULL;你不会得到那个警告的

把它简化一点。编译器完全不知道如何分配。malloc的返回值只是一个地址。在这方面,这三种说法没有根本区别:

int *p = NULL;
int *p = &k;
int *p = malloc(sizeof *p); 
在这三种情况下,p都被分配了地址的值。编译器无法知道该地址是否指向有效的内存地址

编译器不应该警告我没有为temp变量分配内存吗

没有。分配在运行时完成。编译器最多只能在变量未初始化时发出警告。这就是为什么我认为初始化指向NULL的指针是个坏主意的原因

$ cat main.c
int main(void)
{
    int *p;
    *p =42;
}

$ gcc main.c -Wall -Wextra
main.c: In function ‘main’:
main.c:4:8: warning: ‘p’ is used uninitialized in this function [-Wuninitialized]
    4 |     *p =42;
      |     ~~~^~~
如果你改变int*p;到int*p=NULL;你不会得到那个警告的

把它简化一点。编译器完全不知道如何分配。malloc的返回值只是一个地址。在这方面,这三种说法没有根本区别:

int *p = NULL;
int *p = &k;
int *p = malloc(sizeof *p); 

在这三种情况下,p都被分配了地址的值。编译器无法知道该地址是否指向有效的内存地址。

好的,我明白了,但我觉得奇怪的是,编译器无法检测到代码中没有内存分配,这肯定会产生运行时错误。@DanielZardo给指针非空值有很多不同的方法。马洛克只是其中之一。在取消引用指针之前,您需要确保指针具有有效值。举个例子,你没有使用malloc给head赋值,但是你不期望也不希望编译器给你一个错误,但我觉得奇怪的是,编译器无法检测到代码中没有内存分配,这肯定会产生运行时错误。@DanielZardo给指针非空值有很多不同的方法。马洛克只是其中之一。在取消引用指针之前,您需要确保指针具有有效值。例如,您没有使用malloc将值分配给head,但您不希望也不希望编译器为此向您提供错误。编译器将在未初始化的用法时警告您:node*temp。。。扫描%d,&temp->数据;但事实并非如此,即使删除malloc行,temp也会被初始化。您需要一个静态分析器,在这种情况下,像cppcheck这样的工具将返回错误:NULL指针解引用或类似的内容。OT:scanf\s?印刷厂?scanf和printf都是必须按照C标准实现的标准函数。除了Microsoft,没有人反对使用它们,使用它们会使您的代码不可移植。“不,微软改进的功能并没有任何安全性。”安德烈·惠恩承认这一点。我试着实现了gets_s,过程是。。。有趣的@AndrewHenle我知道,但是Visual Studio在没有scanf_和printf_的情况下编译代码。我不知道为什么有些配置我应该做,而没有做。编译器会在未初始化的情况下警告您:node*temp。。。扫描%d,&temp->数据;但事实并非如此,即使删除malloc行,temp也会被初始化。您需要一个静态分析器,在这种情况下,像cppcheck这样的工具将返回错误:NULL指针解引用或类似的内容。OT:scanf\s?脉波重复间隔
NTFS?scanf和printf都是必须按照C标准实现的标准函数。除了Microsoft,没有人反对使用它们,使用它们会使您的代码不可移植。“不,微软改进的功能并没有任何安全性。”安德烈·惠恩承认这一点。我试着实现了gets_s,过程是。。。有趣的@AndrewHenle我知道,但是Visual Studio在没有scanf_和printf_的情况下编译代码。我不知道为什么可能是一些配置,我应该做,但没有。太好了。很高兴知道这一点。“我宁愿收到编译错误,也不愿不收到。@DanielZardo小心。这只是一个警告,您需要使用-Wall来获取它。我推荐-墙壁-WextraGreat。很高兴知道这一点。“我宁愿收到编译错误,也不愿不收到。@DanielZardo小心。这只是一个警告,您需要使用-Wall来获取它。我推荐-沃尔-韦克斯特拉