在哪种情况下,函数原型必须包含参数名称?

时间:2015-05-30 23:17:30

标签: c function

我正在研究K& R的C编程语言,并且有一个练习如下:

练习3-5:编写将整数n转换为字符串s中的基本b字符表示的函数itob(n,s,b)。特别是,itob(n,s,16)将n格式化为s中的十六进制整数。

所以我写了这样的程序:

#include <stdio.h>
#include <string.h>
#define MAXLINE 1000

void reverse(char );
void itob(int , char , int );

main()
{
    char line[MAXLINE];
    int n, i;
    printf("integer: ");
    scanf_s("%d",&n);
    printf("base: ");
    scanf_s("%d",&i);
    itob(n, line, i);
    printf("%s", line);
}

void itob(int n, char s[], int b)
{
    int i, sign;

    if ((sign = n) < 0)
        n = -n;
    i = 0;
    do 
    {

        n % b < 10 ? (s[i++] = n % b + '0') : (s[i++] = n % b + '7');
    }
    while ((n /= b) > 0);
    if (sign < 0)
        s[i++] = '-';
    s[i] = '\0';
    reverse(s);
}

void reverse(char s[])
{
    int c, i, j;

    for  (i = 0, j = strlen(s)-1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

我觉得一切都还好。但是当我运行程序时,输入整数和基数值后出现错误,如下所示:

  

练习3-5.exe中0x10022050(msvcr110d.dll)的未处理异常:   0xC0000005:访问冲突读取位置0x000000EC。

因此该程序在功能itob调用时遇到了问题。

然后经过大约2个小时的调试,我发现原因是反向的功能原型需要包含这样的参数名称:

void reverse(char s[]);
void itob(int , char , int );

我做的唯一改变是在反向函数原型中添加了s [],然后程序正常工作。

我很困惑,因为我学到的只是函数原型的参数名是可选的。为什么参数名称必须包含在反向函数原型中?为什么itob的函数原型不需要参数名称而且没有弹出错误?我的IDE是Visual Studio 2012.

感谢大家的时间和帮助。

1 个答案:

答案 0 :(得分:2)

你问题中的代码有很多错误,其中许多错误都是你的编译器应该至少警告你的。

当我复制代码并使用gcc编译它时,即使没有任何其他参数,第一条错误信息是:

c.c: In function ‘main’:
c.c:16:5: warning: passing argument 2 of ‘itob’ makes integer from pointer without a cast [enabled by default]
     itob(n, line, i);
     ^
c.c:6:6: note: expected ‘char’ but argument is of type ‘char *’
 void itob(int , char , int );
      ^

错误消息是正确的。您使用类型为itob的第二个参数声明了char,然后使用类型为char*的第二个参数调用它(由数组line的隐式转换产生)。 / p>

稍后,您使用类型为itob的第二个参数定义 char[](因为它是一个参数,实际上属于char*类型)。这与之前的声明不兼容,它也应该由编译器标记。

要回答标题中的问题,在独立原型(不属于函数定义的原型)中,参数名称是可选的。这两个原型是等效且有效的:

void itob(int, char, int);

void itob(int x, char y, int z);

我个人喜欢指定参数名称只是因为它使代码更清晰。

对于作为函数定义一部分的原型,名称是必需的,因为这是参数对象的定义方式。

但首先,修复代码中的错误。