Reputation: 185
I am trying to define a function titled scanEntries which takes an int argument and a pointer argument. When i tried to compile it, I got an error message:
"warning: passing argument 2 of ‘scanEntries’ makes pointer from integer without a cast [enabled by default]"
I tried looking up that error message here, but all I got was results about existing string-related functions, not customized functions. I've never tried writing functions with pointers as arguments before; what am I doing wrong? What exactly needs to be casted here and how do I do it?
/* function to scan any integer value */
int scanInt() {
int output;
scanf("%d\n", output);
return(output);
}
/* scanInt but as one entry out of a group */
int scanEntry(int number, int total) {
printf("Please enter score %d of %d: ", number+1, total);
return(scanInt());
}
/* scanEntry for an entire dynamic array) */
void scanEntries(int total, int *p) {
int number;
for(number = 0; number < total; number++) {
*(p + number) = scanEntry(number, total);
/* for testing */
printf("%d", *(p + number));
}
}
Here is where scanEntries is called, plus one more function not shown above that I used here:
/* scanInt but with a prompt to enter size */
int enterSize() {
printf("Please enter size of array: ");
return(scanInt());
}
int main() {
/* entering initial size, done in a separate function */
int initSize = enterSize();
int *p; /* p is an int pointer */
p = calloc(initSize, sizeof(int));
printf("%d", initSize);
scanEntries(enterSize(), *p);
}
Upvotes: 0
Views: 138
Reputation: 1840
This is the basic gist on how to :
Minimal Example:
#include <stdio.h>
void incrementMyInt(int *p) {
// increment the value of the int that p points to
(*p)++;
}
int main() {
int n1 = 3;
int *n2 = malloc(sizeof(int));
*n2 = 7;
incrementMyInt(&n1); // pass the address of n
incrementMyInt(n2);
printf("n1 is %d\n", n);
printf("n2 is %d\n", *n2);
return 0;
}
It outputs n1 is 4
and n2 is 8
.
Upvotes: 1
Reputation: 84541
Continuing from my comments - If you declare int *p
; and your prototype is void scanEntries(int total, int *p)
, you simply call it as scanEntries(initSize, p);
(no '*'
here) "warning: passing argument 2 of ‘scanEntries’ makes pointer from integer without a cast [enabled by default]"
is due to your attempt to pass *p
which dereferences the integer pointer 'p'
resulting in an int
value instead of a pointer to int.
Beyond your initial pointer passing problem, you have a large number of additonal errors:
In main()
you should not call enterSize()
a second time, instead:
scanEntries (initSize, p);
Further, you must validate EVERY allocation and EVERY input, e.g.
p = calloc(initSize, sizeof(int));
if (!p) { /* VALIDATE EVERY ALLOCATION */
perror ("calloc-p");
return 1;
}
and finally, if you allocate memory, develop good habits and ensure you free
it when it is no longer needed, e.g.
free (p); /* don't forget to free what you allocate */
}
In scanInt()
, you must provide a pointer to output
to scanf
, e.g.
if (scanf ("%d", &output) != 1) { /* VALIDATE EVERY INPUT */
fputs ("error: invalid input - not an integer.\n", stderr);
exit (EXIT_FAILURE);
}
(note: the &output
in the scanf
call)
Further, while equivalent, don't use pointer notation for *(p + number)
, instead simply use p[number]
it is more readable.
Putting it altogether, you could do:
#include <stdio.h>
#include <stdlib.h>
/* function to scan any integer value */
int scanInt (void)
{
int output;
if (scanf ("%d", &output) != 1) { /* VALIDATE EVERY INPUT */
fputs ("error: invalid input - not an integer.\n", stderr);
exit (EXIT_FAILURE);
}
return (output);
}
/* scanInt but as one entry out of a group */
int scanEntry (int number, int total)
{
printf ("Please enter score %d of %d: ", number+1, total);
return (scanInt());
}
/* scanEntry for an entire dynamic array) */
void scanEntries (int total, int *p)
{
int number;
for (number = 0; number < total; number++) {
p[number] = scanEntry (number, total);
#ifdef TESTING
printf (" scanEntries testing - %d\n", p[number]);
#endif
}
}
/* scanInt but with a prompt to enter size */
int enterSize (void)
{
printf ("Please enter size of array: ");
return (scanInt());
}
int main (void) {
/* entering initial size, done in a separate function */
int initSize = enterSize(),
*p; /* p is an int pointer */
p = calloc(initSize, sizeof(int));
if (!p) { /* VALIDATE EVERY ALLOCATION */
perror ("calloc-p");
return 1;
}
printf ("%d\n", initSize);
scanEntries (initSize, p);
printf ("%d entries read:\n\n", initSize);
for (int i = 0; i < initSize; i++)
printf ("p[%2d] : %d\n", i, p[i]);
free (p); /* don't forget to free what you allocate */
}
Example Use/Output
(note: you can add -DTESTING
to your compiler options to define TESTING
to activate the additional code.)
$ ./bin/scanentries
Please enter size of array: 4
4
Please enter score 1 of 4: 1
Please enter score 2 of 4: 2
Please enter score 3 of 4: 3
Please enter score 4 of 4: 4
4 entries read:
p[ 0] : 1
p[ 1] : 2
p[ 2] : 3
p[ 3] : 4
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind
is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/scanentries
==11795== Memcheck, a memory error detector
==11795== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==11795== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==11795== Command: ./bin/scanentries
==11795==
Please enter size of array: 4
4
Please enter score 1 of 4: 1
Please enter score 2 of 4: 2
Please enter score 3 of 4: 3
Please enter score 4 of 4: 4
4 entries read:
p[ 0] : 1
p[ 1] : 2
p[ 2] : 3
p[ 3] : 4
==11795==
==11795== HEAP SUMMARY:
==11795== in use at exit: 0 bytes in 0 blocks
==11795== total heap usage: 1 allocs, 1 frees, 16 bytes allocated
==11795==
==11795== All heap blocks were freed -- no leaks are possible
==11795==
==11795== For counts of detected and suppressed errors, rerun with: -v
==11795== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.
Upvotes: 0
Reputation: 223699
The definition of your function is fine. The problem is how you're calling it.
In your main
function, you declare p
as a pointer:
int *p; /* p is an int pointer */
But then you dereference that pointer when calling scanEntries
:
scanEntries(enterSize(), *p);
You're actually passing an int
to the function instead of a pointer to int
, so the compiler is attempting to convert the int
into a pointer to match the parameter. That's what the warning is telling you.
Since the function expects an int *
, just pass it directly to the function. Also, you don't need to call enterSize
again here since you already got the size. use initSize
instead:
scanEntries(initSize, p);
Also, this is wrong:
scanf("%d\n", output);
The %d
format specifier expects a pointer to int
, but you're just passing a plain int
. Using the wrong type for a format specifier invokes undefined behavior.
You want to pass the address of output
to the function, that way it gets updated. Also, the \n
in the format will cause your program to prompt for extra input. It's not needed.
scanf("%d", &output);
Upvotes: 1
Reputation: 111
Change:
scanEntries(enterSize(), *p);
To:
scanEntries(enterSize(), p);
You have to pass a pointer as the second parameter of the function. p is a pointer to an int, thus, the call you made is passing the int instead of the pointer. That's why you have the warning.
Upvotes: 1