Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.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_Function_Warnings_Implicit Declaration - Fatal编程技术网

C 警告:函数的隐式声明— ;我的代码为什么还能工作?

C 警告:函数的隐式声明— ;我的代码为什么还能工作?,c,function,warnings,implicit-declaration,C,Function,Warnings,Implicit Declaration,我经历了以下几个方面: 我的问题可能与此有关。但是,虽然它们提供了在使用函数之前应该声明函数原型的解决方案,但我想探究当函数名不匹配时会发生什么。在我的测试中,它仍然可以正常工作 主C文件 #include "node.h" int main(){ nd *head=NULL; nd *tail=NULL; create_node(&head, &tail, 10); create_node(&head, &tail, 2

我经历了以下几个方面:

我的问题可能与此有关。但是,虽然它们提供了在使用函数之前应该声明函数原型的解决方案,但我想探究当函数名不匹配时会发生什么。在我的测试中,它仍然可以正常工作

主C文件

#include "node.h"
int main(){
    nd *head=NULL;
    nd *tail=NULL;

    create_node(&head, &tail, 10);
    create_node(&head, &tail, 20);
    create_node(&head, &tail, 15);
    create_node(&head, &tail, 35);
    create_node(&head, &tail, 5);
    create_node(&head, &tail, 25);
    print_list(head, tail);
    create_node(&head, &tail, 55);
    create_node(&head, &tail, 52);
    create_node(&head, &tail, 125);

    printf("%d\n",tail->data);
    printf("%d\n",head->data);
    print_list(head, tail);
    return 0;
}
#ifndef NODE_H
#define NODE_H

#include<stdio.h>
#include<stdlib.h>

typedef struct node{
    int data;
    struct node *next;
    struct node *prev;
}nd;

void insert_node(nd **head, nd **tail, int data);

void print_list(nd *head, nd *tail);

#endif
#include "node.h"
void create_node(nd **head, nd **tail, int d){

    nd *temp=(nd *) malloc(sizeof(nd));
    temp->data=d;
    temp->next=NULL;
    temp->prev=NULL;
    /* Start of the Queue.              */
    if(*head==NULL && *tail==NULL){
        *head=temp;
        *tail=temp;
    }
    /* Linking with tail of the Queue.              */
    else if((*tail)->next==NULL){
        (*tail)->next=temp;
        temp->prev=*tail;
        *head=temp;
    }
    /* Adding remaining elements of the Queue.      */
    else{
        (*head)->next=temp;
        temp->prev=*head;
        *head=temp;
    }
}

void print_list(nd *head, nd *tail){
    if(NULL==head){
        printf("Queue is empty\n");
    }
    else{
        printf("Printing the list\n");
        nd *temp;
        for(temp=tail;temp!=NULL;temp=temp->next){
            printf("%d ",temp->data);
        }
        printf("\n");
    }
}
node.h
文件

#include "node.h"
int main(){
    nd *head=NULL;
    nd *tail=NULL;

    create_node(&head, &tail, 10);
    create_node(&head, &tail, 20);
    create_node(&head, &tail, 15);
    create_node(&head, &tail, 35);
    create_node(&head, &tail, 5);
    create_node(&head, &tail, 25);
    print_list(head, tail);
    create_node(&head, &tail, 55);
    create_node(&head, &tail, 52);
    create_node(&head, &tail, 125);

    printf("%d\n",tail->data);
    printf("%d\n",head->data);
    print_list(head, tail);
    return 0;
}
#ifndef NODE_H
#define NODE_H

#include<stdio.h>
#include<stdlib.h>

typedef struct node{
    int data;
    struct node *next;
    struct node *prev;
}nd;

void insert_node(nd **head, nd **tail, int data);

void print_list(nd *head, nd *tail);

#endif
#include "node.h"
void create_node(nd **head, nd **tail, int d){

    nd *temp=(nd *) malloc(sizeof(nd));
    temp->data=d;
    temp->next=NULL;
    temp->prev=NULL;
    /* Start of the Queue.              */
    if(*head==NULL && *tail==NULL){
        *head=temp;
        *tail=temp;
    }
    /* Linking with tail of the Queue.              */
    else if((*tail)->next==NULL){
        (*tail)->next=temp;
        temp->prev=*tail;
        *head=temp;
    }
    /* Adding remaining elements of the Queue.      */
    else{
        (*head)->next=temp;
        temp->prev=*head;
        *head=temp;
    }
}

void print_list(nd *head, nd *tail){
    if(NULL==head){
        printf("Queue is empty\n");
    }
    else{
        printf("Printing the list\n");
        nd *temp;
        for(temp=tail;temp!=NULL;temp=temp->next){
            printf("%d ",temp->data);
        }
        printf("\n");
    }
}
输出

Printing the list
10 20 15 35 5 25 
10
125
Printing the list
10 20 15 35 5 25 55 52 125 
node.h
中声明的函数名是
insert\u node
,而在node.c中声明的函数名是
create\u node
。有人能分享一些关于它为什么运行的见解吗?但它发出了一个警告:

警告:函数的隐式声明


在您的示例中,您有一个隐式声明
create\u node
,并声明一个未实现的函数
insert\u node

调用
create_node
的原因将在您之前链接到的帖子中介绍

没有实现
insert\u node
这一事实对您的程序来说并不重要,因为没有任何东西试图调用它。如果将一行更改为调用
insert\u node
,它将在没有警告的情况下编译,但随后无法链接到
insert\u node
的未解决符号错误


我相信您知道这一点,但正确的方法是在
创建\u节点
插入\u节点
之一上进行标准化,并在整个程序中使用它。

首先,您声明了一个名为
插入\u节点
的函数,但这并不重要。只要不使用函数,就可以声明函数,但不定义它们(即不提供它们的代码)。这在现实生活中经常发生:头定义了很多函数,然后在链接时只需要提供实际使用的函数

警告与创建节点有关。由于编译主C文件时没有函数声明,编译器会对其参数类型进行一些假设。它提升所有参数:小于
int
(例如
char
short
)的整数类型提升为
int
float
s被提升为
double
;指针类型不转换。对于您的代码,这恰好起作用,因为

  • 您总是传递正确类型的参数
  • 所有参数类型均未升级
如果将
数据
参数的类型更改为
long
,则编译器将生成代码以调用函数,并假定函数的类型为
int
,但该函数将使用
long
参数。在
int
long
大小不同的平台上,您可能会得到垃圾数据、崩溃或其他错误行为

如果将
数据
参数的类型更改为
字符
,则编译器将生成代码来调用函数,并假定函数的类型为
int
,但该函数需要一个
字符
参数。同样,您可能会发现代码使用了错误的数据、崩溃等


C通常会给你足够的绳子吊死自己。如果你把一根绳子剪错了,它可能正好起作用。或者它可能不起作用。

它起作用是因为
main
调用
create\u node
,而
create\u node
实际上是在
node.c
中声明的。参数类型恰好足够通用,因此它们都是OK的。标题中的名称错误将导致警告。如果
node.c
中的
create\u节点
实际上被称为
insert\u节点
,该链接将失败,并说它找不到定义为
create\u节点
的函数。您的问题是“为什么我的编译器不将警告视为错误?”这是一个标志。它不是“工作正常”。如果调用未声明的函数会产生一些输出,那么不管发生什么,这都是错误的(因为行为当时是未定义的)。不过,它可以假装“工作正常”。这并不意味着它确实工作正常。如果使用gcc@H2CO3接受的答案解释了在这种情况下,带参数的默认编译器行为是可以的。虽然隐式声明可能并不总是正确的,但在这种情况下,它看起来不仅仅是“假装工作正常”;编译器所做的假设在这种情况下是正确的,因此这种情况是正确的。值得一提的是,您在这里描述的所有内容仅在C89中是正确的。C99使对未声明函数的调用无效。@H2CO3这一点很好,但由于代码无效且编译器已发出诊断,C89编译器可以保持完全相同的行为方式,并在这一点上符合C99。抱歉,我不理解。这在C89和C99下不可能有相同的行为。在C89中,如果提升的参数类型匹配,则它必须工作,而在C99中它是UB。(我也不明白你所说的“C89编译器将遵守C99”是什么意思,这也是不可能的。你能详细说明一下吗?@H2CO3有了C89编译器,这个例子必须工作——但问题是这个例子如何工作。对于C99,这个示例不必工作,但仍然允许编译器使其工作。