警告:格式“%d”需要“int”类型的参数,但参数 2 的类型为“long int”[-Wformat=]

Posted

技术标签:

【中文标题】警告:格式“%d”需要“int”类型的参数,但参数 2 的类型为“long int”[-Wformat=]【英文标题】:warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=] 【发布时间】:2015-02-27 19:16:56 【问题描述】:

这段代码是关于。

比赛条件: 调度和编译器行为在进程或线程同步中起着重要作用。演示同步需求的最简单场景来自试图修改共享变量值的两个线程/进程之间创建的竞争条件,这通常会导致数据不一致和错误结果。下面的例子演示了这种情况:

我是 C 的新手,我对这个警告所发生的事情感到困惑。警告是什么意思,我该如何解决。我写的代码在这里:

q1.c: In function ‘runner’:
q1.c:13:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
 printf("T tid: %d x before: %d\n", syscall(SYS_gettid),x); int i;
 ^
q1.c:19:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
 printf("T tid: %d x after: %d\n", syscall(SYS_gettid),x);

代码如下:

// Race condition
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
int x=0;
void * runner(void *arg)

printf("T tid: %d   x before: %d\n", syscall(SYS_gettid),x); int i;
for (i = 0; i < 100000; i++ )

x = x + 1;

printf("T tid: %d   x after: %d\n", syscall(SYS_gettid),x);


int program()

pthread_t t1,t2,t3,t4;
printf("Parent pid: %d  x before threads: %d\n", getpid(),x); int i;
if(pthread_create(&t1,NULL, runner, NULL)) printf("Error creating thread 1\n"); return 1;

if(pthread_create(&t2,NULL, runner, NULL)) printf("Error creating thread 2\n"); return 1;

if(pthread_create(&t3,NULL, runner, NULL)) printf("Error creating thread 1\n"); return 1;

if(pthread_create(&t4,NULL, runner, NULL)) printf("Error creating thread 1\n"); return 1;


if(pthread_join(t1,NULL)) printf("error joining thread 1"); return 1;

if(pthread_join(t2,NULL)) printf("error joining thread 1"); return 1;

if(pthread_join(t3,NULL)) printf("error joining thread 1"); return 1;


if(pthread_join(t4,NULL)) printf("error joining thread 1"); return 1;

printf("Parent pid: %d  x after threads: %d\n", getpid(),x); return 0;


int main(int argc, char *argv[])  
int count=0;
// loop runs the program count times 
while(count<5)

// running program program();
count++;
//reset global x for next run of program. x=0;
printf("\n\n");

return 0;

【问题讨论】:

适当的缩进会让你的代码非常更容易阅读。 请注意,copy'n'paste 会导致您创建(或未能创建)“线程 1”三次,并导致您加入(或未能加入)“线程 1”四次。除了需要使用数组之外,您还需要记住在复制代码时对其进行完全编辑。 【参考方案1】:

您必须将"%d" 更改为"%ld""%d" 用于签名int,这里l 代表long,因此"%ld" 用于签名long int

【讨论】:

【参考方案2】:

syscall() 的原型返回 long

#include <sys/syscall.h>
long syscall(long number, ...);

当调用printf() 时,它的格式说明符,如"%d",应该与参数的类型相匹配(在参数通过可变参数的通常提升之后)。改为

                 v---- long --------v 
                              v----------- int ----------v
printf("T tid: %ld x before: %d\n", syscall(SYS_gettid), x);

【讨论】:

值得注意的是,虽然这从大约永远 (sourceware.org/git/… -- 实际上是 1996 年) 以来一直是正确的,但文档仅在几个月前更新 (git.kernel.org/cgit/docs/man-pages/man-pages.git/commit/man2/…),因此错误是可以理解的。错误信息对我来说似乎很清楚,但后来我的英语和 C 语言流利。:)【参考方案3】:

编写代码时应始终考虑到人类会阅读它。 甚至作者在阅读代码时也遇到了重大问题 如许多“复制和粘贴”错误所示

注意:当'//'注释在一行上开始时,该行的所有其余部分都是注释

除 main 之外的任何函数都应该有一个原型。 在调用它们的任何函数之前声明被调用函数的方法 将适用于琐碎的程序,但不适用于多文件程序,也不适用于 具有交叉调用路径的程序 IE。始终提供原型语句。

当调用某个函数时,始终知道(即查找)完整的细节 关于那个功能。对于 OP 发布的代码, 这尤其适用于 syscall() 函数。

编写线程时,需要了解的不仅仅是原型 为一个线程。就像在OPs代码中一样,也需要知道如何退出线程

总是在编译时启用所有警告。警告是问题 在继续之前应该修复的代码中。

顺便说一句:使用单个互斥体可以消除竞争条件问题

// Race condition
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>

void *runner( void * );
int   program( void );

int x=0;


// <-- compiler raises warning about unused parameter
void * runner(void *arg)

    // the returned value from the syscall is a long int
    //printf("T tid: %d   x before: %d\n",
    printf("T tid: %ld   x before: %d\n",
            syscall(SYS_gettid),
            x);
    int i;

    for (i = 0; i < 100000; i++ )
    
        x = x + 1;
    

    // <-- the returned value from syscall is a long int
    //printf("T tid: %d   x after: %d\n",
    printf("T tid: %ld   x after: %d\n",
            syscall(SYS_gettid),
            x);

    // <-- this line missing, compiler raises warning
    pthread_exit(NULL);
 // end function: runner


int program()

    pthread_t t1,t2,t3,t4;

    printf("Parent pid: %d  x before threads: %d\n",
            getpid(),
            x);

    //int i; // <-- this variable not used, results in compiler warning


    if( pthread_create(&t1, NULL, runner, NULL) )
    
        printf("Error creating thread 1\n");
        return 1;
    

    if( pthread_create(&t2, NULL, runner, NULL) )
    
        printf("Error creating thread 2\n");
        return 1;
    

    if( pthread_create(&t3, NULL, runner, NULL) )
    
        // <-- copy and paste error
        //printf("Error creating thread 1\n");
        printf("Error creating thread 3\n");
        return 1;
    

    if( pthread_create(&t4, NULL, runner, NULL) )
    
        // <-- copy and paste error
        //printf("Error creating thread 1\n");
        printf("Error creating thread 4\n");
        return 1;
    


    if( pthread_join(t1, NULL) )
    
        printf("error joining thread 1");
        return 1;
    

    if( pthread_join(t2, NULL) )
    
        // <-- copy and paste error
        //printf("error joining thread 1");
        printf("error joining thread 2");
        return 1;
    

    if( pthread_join(t3, NULL) )
    
        // <-- copy and paste error
        //printf("error joining thread 1");
        printf("error joining thread 3");
        return 1;
    

    if( pthread_join(t4, NULL) )
    
        // <-- copy and paste error
        //printf("error joining thread 1");
        printf("error joining thread 4");
        return 1;
    

    printf("Parent pid: %d  x after threads: %d\n",
            getpid(),
            x);
    return 0;
 // end function: program


// <-- this line cause compiler to raise two warnings about unused parameters
//int main(int argc, char *argv[])
int main()

    int count=0;

    // <-- there is no loop code perhaps you meant to put the 'while' on the next line
    // loop runs the program count times while(count<5)
    while( count < 5 )
    
        // <-- program is not run, perhaps you meant to put the 'program()' on the next line
        // running program program();
        program();

        count++;
        // <-- x is not being reset, perhaps you menat to put 'x=0;' on the next line
        //reset global x for next run of program. x=0;
        x=0;
        printf("\n\n");
    

    return 0;
  // end function: main

【讨论】:

以上是关于警告:格式“%d”需要“int”类型的参数,但参数 2 的类型为“long int”[-Wformat=]的主要内容,如果未能解决你的问题,请参考以下文章

警告:格式“%d”需要类型“int”,但参数 2 的类型为“int (*)(int *)”[关闭]

警告:格式“%ld”需要“long int”类型的参数,但参数的类型为“__builtin_neon_di”

格式“%d”需要“int”类型的参数,但参数 2 的类型为“int *”

格式指定类型“int”,但参数的类型为“UIViewContentMode”

在 C 中,如何修复此警告:格式“%s”需要“char *”类型的参数,但参数 3 的类型为“char (*)[100]

格式指定类型“int*”但参数类型为“int”