I am studying the C programming language by K&R and there is a exercise as below:
Exercise 3-5: Write the function itob(n, s, b) that converts the integer n into a base b character representation in the string s. In particular, itob(n, s, 16) formats n as a hexadecimal integer in s.
So I wrote program like this:
#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;
}
}
I thought everything was OK. But when I ran the program, I got error after I input integer and base values, like below:
Unhandled exception at 0x10022050 (msvcr110d.dll) in Exercise 3-5.exe: 0xC0000005: Access violation reading location 0x000000EC.
So the program had trouble with function itob call.
And then after about 2 hour struggle for debugging, I found the cause was the function prototype of reverse need to include parameter name like this:
void reverse(char s[]);
void itob(int , char , int );
The only change I made was I added s[] in the function prototype of reverse and then program worked properly.
I am confused because all I learned is that parameter names of function prototype are optional. Why does the parameter name have to include in function prototype of reverse? And why does function prototype of itob not need parameter name and there is not pop-up error? My IDE is Visual Studio 2012.
Thanks for everyone's time and help.
The code in your question has a number of bugs, many of which your compiler should have at least warned you about.
When I copied the code and compiled it using gcc, even without any additional arguments, the first error message was:
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 );
^
The error message is correct. You declared itob
with a second parameter of type char
, then called it with a second parameter of type char*
(resulting from the implicit conversion of the array line
).
Later, you define itob
with a second parameter of type char[]
(which, since it's a parameter, is really of type char*
). This is incompatible with the earlier declaration, and it should also have been flagged by your compiler.
To answer the question in your title, in a standalone prototype (one that's not part of the function definition), parameter names are optional. These two prototypes are equivalent and valid:
void itob(int, char, int);
and
void itob(int x, char y, int z);
Personally I like to specify parameter names just because it makes the code clearer.
For a prototype that's part of a function definition, the names are required, because that's how the parameter objects are defined.
But first, fix the errors in your code.
User contributions licensed under CC BY-SA 3.0