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

C 如何为自定义函数生成非空参数警告?

C 如何为自定义函数生成非空参数警告?,c,gcc,C,Gcc,我试图编写一个库函数,其中参数不应为null,并希望gcc在有人试图传递null时生成警告。我的代码是 #include <stdio.h> #include <string.h> int own_strcmp(const char *str1, const char *str2) { if( str1 == NULL || str2 == NULL){ if(str1 == NULL && str2 == NULL

我试图编写一个库函数,其中参数不应为null,并希望gcc在有人试图传递null时生成警告。我的代码是

#include <stdio.h>
#include <string.h>
int own_strcmp(const char *str1, const char *str2)
{
        if( str1 == NULL || str2 == NULL){
            if(str1 == NULL && str2 == NULL) 
                return 0;
            else if( str1 == NULL)
                return str2[0];
            else
                return str1[0];
        }
        int i=0;
        while(str1[i] && str2[i]){
                if( str1[i] != str2[i]){
                        break;
                }
                i++;
        }
        return str1[i]-str2[i];
}



int main(int argc, char *argv[]){
        const char *str1 = "hello";
        const char *str2 = "hello";
        printf("%s and %s is %d\n", str1, str2, own_strcmp(NULL, str2));
        printf("%s and %s is %d\n", str1, str2, strcmp(NULL, str2));
        return 0;
}
也许你要找的就是这个。您可以指定所有指针参数都应为非null,也可以提供一个参数列表,指定哪些参数应为非null

按照我读取文档的方式,如果声明了
nonnull
属性,则将null指针传递给非null参数是未定义的行为。必须启用
-Wnonnull
选项才能获得警告。启用警告后,如果将
NULL
传递给非NULL参数,则会发出警告。但是,对于传递的空指针变量不会发出警告。因此,在运行时处理不正确的输入非常重要。感谢您指出这一重要问题

看起来像。Clang还具有可空性类型限定符
\u Nonnull
,但这在GCC中不可用

我应该强调,这种行为在C标准中不受支持,而是一种编译器扩展。为了便于移植,您应该使用设计良好的函数在运行时处理不正确的输入

下面是使用该属性声明的函数(不带
NULL
指针检查的早期版本)。我添加了一行调用
own\u strcmp()
,并使用空指针变量;请注意,此行不会导致发出警告。还请注意,使用空指针变量调用标准库strcmp(),无法触发警告

#include <stdio.h>
#include <string.h>

int own_strcmp(const char *str1, const char *str2)__attribute__((nonnull));

int main(void)
{
    const char *str1 = "hello";
    const char *str2 = "hello";
    const char *arg = NULL;

    /* Warning issued for this NULL argument */
    printf("%s and %s is %d\n", str1, str2, own_strcmp(NULL, str2));

    /* No warning issued for the NULL variable arg */
    printf("%s and %s is %d\n", str1, str2, own_strcmp(arg, str2));

    /* No warning issued for strcmp() either */
    printf("%s and %s is %d\n", str1, str2, strcmp(arg, str2));    
    return 0;
}

int own_strcmp(const char *str1, const char *str2)
{
    int i=0;
    while(str1[i] && str2[i]){
        if( str1[i] != str2[i]){
            break;
        }
        i++;
    }
    return str1[i]-str2[i];
}
也许你要找的就是这个。您可以指定所有指针参数都应为非null,也可以提供一个参数列表,指定哪些参数应为非null

按照我读取文档的方式,如果声明了
nonnull
属性,则将null指针传递给非null参数是未定义的行为。必须启用
-Wnonnull
选项才能获得警告。启用警告后,如果将
NULL
传递给非NULL参数,则会发出警告。但是,对于传递的空指针变量不会发出警告。因此,在运行时处理不正确的输入非常重要。感谢您指出这一重要问题

看起来像。Clang还具有可空性类型限定符
\u Nonnull
,但这在GCC中不可用

我应该强调,这种行为在C标准中不受支持,而是一种编译器扩展。为了便于移植,您应该使用设计良好的函数在运行时处理不正确的输入

下面是使用该属性声明的函数(不带
NULL
指针检查的早期版本)。我添加了一行调用
own\u strcmp()
,并使用空指针变量;请注意,此行不会导致发出警告。还请注意,使用空指针变量调用标准库strcmp(),无法触发警告

#include <stdio.h>
#include <string.h>

int own_strcmp(const char *str1, const char *str2)__attribute__((nonnull));

int main(void)
{
    const char *str1 = "hello";
    const char *str2 = "hello";
    const char *arg = NULL;

    /* Warning issued for this NULL argument */
    printf("%s and %s is %d\n", str1, str2, own_strcmp(NULL, str2));

    /* No warning issued for the NULL variable arg */
    printf("%s and %s is %d\n", str1, str2, own_strcmp(arg, str2));

    /* No warning issued for strcmp() either */
    printf("%s and %s is %d\n", str1, str2, strcmp(arg, str2));    
    return 0;
}

int own_strcmp(const char *str1, const char *str2)
{
    int i=0;
    while(str1[i] && str2[i]){
        if( str1[i] != str2[i]){
            break;
        }
        i++;
    }
    return str1[i]-str2[i];
}

C有一个声明指针参数的方法,该参数不能为null。但是,它不能保证空指针永远不会错误地传递。它建议编译器可以编译例程,期望参数永远不会为null,但并不一定能防止调用例程错误地传递null。编译器可能会检测到对此类例程的一些错误调用,并发出有关这些调用的警告或错误,但无法检测到其他调用

这是通过将
static
关键字放在参数声明中这一很少使用的语法实现的:

void foo(int p[static 1])
{
    … body of function …
}
这表示
p
必须根据C 2011[N1570]6.7.6.3 7提供对至少一个元素的数组的第一个元素的访问。由于必须存在
p
点所在的元素,
p
不能为空。例如,编译此代码时:

#include <stddef.h>

void foo(int p[static 1])

void bar(void) { foo(NULL); }
但是,此代码编译时没有警告:

#include <stddef.h>

void foo(int p[static 1]) {}

void bar(int *p) { foo(p); }

void baz(void) { bar(NULL); }
#包括
void foo(int p[static 1]){}
空条(int*p){foo(p);}
void baz(void){bar(NULL);}

因此,似乎只有当直接传递此类参数时,此编译器才能检测到该参数的null传递错误。

C有一种方法用于声明指针参数,该参数不得为null。但是,它不能保证空指针永远不会错误地传递。它建议编译器可以编译例程,期望参数永远不会为null,但并不一定能防止调用例程错误地传递null。编译器可能会检测到对此类例程的一些错误调用,并发出有关这些调用的警告或错误,但无法检测到其他调用

这是通过将
static
关键字放在参数声明中这一很少使用的语法实现的:

void foo(int p[static 1])
{
    … body of function …
}
这表示
p
必须根据C 2011[N1570]6.7.6.3 7提供对至少一个元素的数组的第一个元素的访问。由于必须存在
p
点所在的元素,
p
不能为空。例如,编译此代码时:

#include <stddef.h>

void foo(int p[static 1])

void bar(void) { foo(NULL); }
但是,此代码编译时没有警告:

#include <stddef.h>

void foo(int p[static 1]) {}

void bar(int *p) { foo(p); }

void baz(void) { bar(NULL); }
#包括
void foo(int p[static 1]){}
空条(int*p){foo(p);}
void baz(void){bar(NULL);}

因此,似乎只有在直接传递此类参数时,此编译器才能检测到该参数的null传递不正确。

为什么不直接处理函数中的
null
输入?可靠地检测
null
值将意味着编译器解决了停止问题。不太可能。为什么您希望gcc能够这样做?如果您希望生成这样的代码,C不是您的语言。@DavidBowling我可以这样做,但我希望向用户显示警告,以便更好地为我的库用户使用。@Olaf gcc已经生成这样的警告,我希望生成相同的警告。你能推荐一些编译器警告出现的手册吗