Home > Software engineering >  Read access violation when using a pointer as a loop condition
Read access violation when using a pointer as a loop condition

Time:09-28

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.

code demonstration

^ 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;
}
  • Related