printf函数行为打印%d个时,不提供变量名 [英] Behaviour of printf when printing a %d without supplying variable name

查看:308
本文介绍了printf函数行为打印%d个时,不提供变量名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚遇到了一个奇怪的问题,我想给printf一个整型变量,但我忘了指定变量名,即

 的printf(%D);

而不是

 的printf(%d个,integerName);

令人惊奇的程序编译,有输出,它不是随机的。事实上,这恰好是非常整数,我想在所述第一位置,这恰好是m-1个打印

该errorneous 的printf 语句将持续输出M-1只要程序继续运行......换句话说,它的表现究竟是否语句读取<作为/ p>

 的printf(%d个M-1);

任何人都知道这种行为背后的原因吗?我用g ++的不带任何命令行选项。

 的#include&LT;&iostream的GT;
#定义MAXN 100
#定义ON 1
#定义OFF 0使用命名空间std;无效clearArray为(int *数组,INT N);
INT fillArray为(int *阵列,诠释男,INT N);诠释的main()
{
    INT N = -1,I,M;
    int数组[MAXN]
    INT找到;    scanf函数(%d个,&安培; N);    而(N!= 0)
    {
        找到= 0;
        m = 1时;
        而(找到了!= 1)
        {
            如果(M = 2及!&放大器; M = 3及!&放大器; M = 4和!&放大器; M = 6和;!&放大器; M = 12!)
            {
                clearArray(数组,N);
                如果(fillArray(数组,M,N)== 0)
                {
                    找到= 1;
                }
            }
            M +;
        }        的printf(%d个\\ n);        scanf函数(%d个,&安培; N);
    }    返回0;
}无效clearArray为(int *数组,INT N)
{
    的for(int i = 1; I&LT; = N;我++)
        数组[我] = ON;
}INT fillArray为(int *阵列,诠释男,INT N)
{
    INT I = 1,J,offCounter = 0,incrementCounter;    而(offCounter!= N)
    {
        如果(*(阵列+ I)== ON)
        {
            *(阵列+ I)= OFF;
            offCounter ++;
        }
        其他
        {
            J = 0;
            而((*阵列+ I + J)== OFF)
            {
                J ++;
            }
            *(数组+ I + J)= OFF;
            offCounter ++;
        }
        如果(*(阵列+ 13)== OFF和放大器;&安培;!offCounter = N)返回1;
        如果(offCounter == n)的突破;        incrementCounter = 0;
        而(incrementCounter!= m)个
        {
            我++;
            如果(ⅰ将N)I = 1;
            如果(*(阵列+ I)== ON)incrementCounter ++;
        }
    }    返回0;
}


解决方案

您说令人惊讶的是程序编译。实际上,这是不奇怪的。 C&放大器; c + +允许函数具有可变参数列表。像printf的定义是这样的:

INT的printf(字符*,...);

中的...表示有零个或多个可选参数的函数。事实上,主要的原因C具有可选的参数之一就是支持的printf&放大器; scanf系列的功能。

C的printf函数没有专门的知识。在您的例子:

 的printf(%D);

编译器不分析格式字符串,并确定一个整数参数丢失。这是完全合法的C code。您缺少一个观点的事实是,只出现在运行时的语义问题。 printf函数将假定您提供的参数,去寻找它在堆栈上。它会拿起无论发生什么事要在那里。碰巧,在你的特殊情况下,它打印正确的事情,但是这却是个例外。一般来说,你会得到垃圾数据。这种行为将有所不同的编译器编译器,并根据什么编译您使用的选项也将发生变化;如果你打开​​编译器的优化,你可能会得到不同的结果。

由于在评论我的答案之一指出,一些编译器有棉绒一样,实际上可以检测出错误的printf / scanf的通话功能。这包括编译器解析格式字符串和确定预期的附加参数的数目。这是非常特殊的编译器的行为,并在一般情况下,将不会检测错误。也就是说,如果你写它具有相同的签名的printf自己的printf_better功能,编译器不会,如果任何参数缺失检测。

I've just encountered a weird problem, I'm trying to printf an integer variable, but I forgot to specify the variable name, i.e.

printf("%d");

instead of

printf("%d", integerName);

Surprisingly the program compiles, there is output and it is not random. In fact, it happens to be the very integer I wanted to print in the first place, which happens to be m-1.

The errorneous printf statement will consistently output m-1 for as long as the program keeps running... In other words, it's behaving exactly as if the statement reads

printf("%d", m-1);

Anybody knows the reason behind this behaviour? I'm using g++ without any command line options.

#include <iostream>
#define maxN 100
#define ON 1
#define OFF 0

using namespace std;

void clearArray(int* array, int n);
int fillArray(int* array, int m, int n);

int main()
{
    int n = -1, i, m;
    int array[maxN];
    int found;

    scanf("%d", &n);

    while(n!=0)
    {
        found=0;
        m = 1;
        while(found!=1)
        {
            if(m != 2 && m != 3 && m != 4 && m != 6 && m != 12)
            {
                clearArray(array, n);
                if(fillArray(array, m, n) == 0)
                {
                    found = 1;
                }
            }
            m++;
        }

        printf("%d\n");

        scanf("%d", &n);
    }

    return 0;
}

void clearArray(int* array, int n)
{
    for(int i = 1; i <= n; i++)
        array[i] = ON;
}

int fillArray(int* array, int m, int n)
{
    int i = 1, j, offCounter = 0, incrementCounter;

    while(offCounter != n)
    {
        if(*(array+i)==ON) 
        {
            *(array+i) = OFF;
            offCounter++;       
        }
        else 
        {
            j = 0;
            while((*array+i+j)==OFF)
            {
                j++;
            }
            *(array+i+j) = OFF;
            offCounter++;           
        }
        if(*(array+13) == OFF && offCounter != n) return 1;
        if(offCounter ==n) break;

        incrementCounter = 0;       
        while(incrementCounter != m)
        {
            i++;
            if(i > n) i = 1;
            if(*(array+i) == ON) incrementCounter++; 
        }       
    }

    return 0;
}

解决方案

You say that "surprisingly the program compiles". Actually, it is not surprising at all. C & C++ allow for functions to have variable argument lists. The definition for printf is something like this:

int printf(char*, ...);

The "..." signifies that there are zero or more optional arguments to the function. In fact, one of the main reasons C has optional arguments is to support the printf & scanf family of functions.

C has no special knowledge of the printf function. In your example:

printf("%d");

The compiler doesn't analyse the format string and determine that an integer argument is missing. This is perfectly legal C code. The fact that you are missing an argument is a semantic issue that only appears at runtime. The printf function will assume that you have supplied the argument and go looking for it on the stack. It will pick up whatever happens to be on there. It just happens that in your special case it is printing the right thing, but this is an exception. In general you will get garbage data. This behaviour will vary from compiler to compiler and will also change depending on what compile options you use; if you switch on compiler optimisation you will likely get different results.

As pointed out in one of the comments to my answer, some compilers have "lint" like capabilities that can actually detect erroneous printf/scanf calls. This involves the compiler parsing the format string and determining the number of extra arguments expected. This is very special compiler behaviour and will not detect errors in the general case. i.e. if you write your own "printf_better" function which has the same signature as printf, the compiler will not detect if any arguments are missing.

这篇关于printf函数行为打印%d个时,不提供变量名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆