I'm attempting to use pointers as conditions for a do...while loop that takes user input in C - but I keep getting a read access violation no matter what I try. I've tried to look everywhere I can for answers but I'm not really understanding well as I am very new to pointers. What am I doing wrong here?
//Sub prototype
void GetEmployeeInfo(int* pintEmployeeType);
//Actual sub code
void GetEmployeeInfo(int* pintEmployeeType)
{
//Getting employee type (if the entry is 1 they are a standard employee, while 2 is a manager)
do
{
printf("Enter employee type ('1' for employee or '2' for manager).\n");
scanf("%d", &pintEmployeeType);
}
while (*pintEmployeeType != 1 && *pintEmployeeType != 2); //This is where I'm getting an exception
CodePudding user response:
Creating an mre for you since you didn't provide one, consider the following code:
#include <stdio.h>
//Sub prototype
void GetEmployeeInfo(int* pintEmployeeType);
int main(void)
{
int empType;
GetEmployeeInfo(&empType);
printf("successfully returned, empType = %d\n", empType);
return 0;
}
//Actual sub code
void GetEmployeeInfo(int* pintEmployeeType)
{
//Getting employee type (if the entry is 1 they are a standard employee, while 2 is a manager)
do
{
printf("Enter employee type ('1' for employee or '2' for manager).\n");
scanf("%d", pintEmployeeType);
}
while (*pintEmployeeType != 1 && *pintEmployeeType != 2);
}
The program starts in main
and reserves space for empType
in automatic storage (probably 4 bytes and on a stack. None of these are mandated by the C standard, but assuming that to be the case for your C implementation moving forward). After declaring int empType;
, your stack frame for main
now contains:
__ main __________________________
| Variable | Address | Value |
| empType | 0x1234 | ??? |
----------------------------------
I've made the address up, but it has some address on your stack. It has no value yet because nothing has been assigned to it. Now when you call GetEmployeeInfo
passing the address of empType
, this is what (an abbreviated look at) your stack looks like^:
__ GetEmployeeInfo ___________________
| Variable | Address | Value |
| pintEmployeeType | 0x4567 | 0x1234 |---|
--------------------------------------| |
| __ main ____________________________| |
| empType | 0x1234 | ??? |<---
|_____________________________________|
It now has two frames, one for GetEmployeeInfo
and one for main
. Again, I've made up the address for pintEmployeeType
, but what I'm trying to illustrate with the arrow is that pintEmployeeType
points to empType
. A pointer is nothing more than a variable whose value is an address to something else; in this case pintEmployeeType
is an int
pointer (or an int*
), and its value is an address to empType
, an int
.
Your scanf
line is wrong, because the "%d"
format specifier expects an int*
as a parameter. &
in this context means "the address of". pintEmployeeType
is already an int*
, so taking the address of that is an int**
. This is something your compiler should warn you about; turn up its warning level if it isn't. After fixing that line, we have
scanf("%d", pintEmployeeType);
Let's say you enter 4. Now this is what our stack looks like^:
__ GetEmployeeInfo ___________________
| Variable | Address | Value |
| pintEmployeeType | 0x4567 | 0x1234 |---|
--------------------------------------| |
| __ main ____________________________| |
| empType | 0x1234 | 4 |<---
|_____________________________________|
pintEmployeeType
points back to empType
in main
; that hasn't changed. What has changed is the value of empType
. When we hit the while
loop
while (*pintEmployeeType != 1 && *pintEmployeeType != 2);
The *
in this context means "dereference the pointer". That is, "give me the value that the pointer is pointing to". In this case, that's 4. 4 != 1 and 4 != 2, so it will loop back again and re-prompt. Assuming you behave and always enter input that corresponds to the "%d"
format specifier, this loop will continue until you enter 1 or 2, and break the loop. Each time you enter a value, it's the value of empType
that changes since this is what pintEmployeeType
is pointing at.
As mentioned in the comments, you should at least check the return value of scanf
to see if input matched your format specifier. A more robust way of gathering user input is to use fgets
to read input in as a string and do your own parsing from there.
^ understand there's more on your stack than just these two variables (such as return pointers), omitting everything extra for clarity.
CodePudding user response:
void GetEmployeeInfo(int* pintEmployeeType)
{
//Getting employee type (if the entry is 1 they are a standard employee, while 2 is a manager)
do
{
printf("Enter employee type ('1' for employee or '2' for manager).\n");
scanf("%d[1|2] \n",pintEmployeeType);
printf("you entered %d\n",*pintEmployeeType);
}
while (*pintEmployeeType != 1 && *pintEmployeeType != 2); //This is where I'm getting an exception
}
int main()
{
int x=0;
GetEmployeeInfo(&x);
return 0;
}