Использование указателей void: 0xC0000005: место чтения нарушения прав доступа - PullRequest
2 голосов
/ 09 апреля 2020

Я просто экспериментирую с пустыми указателями, я хотел использовать их для строк типа C. Кажется, что эта строка кода вызывает исключение, но я не знаю почему:

printf("My name is %s", *((char*)ptr));

Вот весь код:

int main()
{
    char prenume[] = "Alexandru";
    char* name = prenume;
    int age = 33;
    float height = 1.81;

    void* ptr;
    ptr = name;
    printf("My name is %s", *((char*)ptr));
    ptr = &age;
    printf("\nAge:%d", *((int*)ptr));
    ptr = &height;
    printf("\nHeight:%2.2f", *((float*)ptr));
    return 0;  
}

Я использую MS Visual Studio

Буду признателен за любой ответ ... спасибо!

Ответы [ 2 ]

1 голос
/ 10 апреля 2020

Я думаю, вы хотите использовать void * ptr в качестве общего указателя на любые типы данных. Проблема в вашем коде, как показано ниже.

int main()
{
    char prenume[] = "Alexandru";
    char* name = prenume;
    int age = 33;
    float height = 1.81; //<=== this line will cause a truncation warning at compile time

    void* ptr;
    ptr = name;
    printf("My name is %s", *((char*)ptr)); // <======= this line will cause access violation error at runtime
    ptr = &age;
    printf("\nAge:%d", *((int*)ptr));
    ptr = &height;
    printf("\nHeight:%2.2f", *((float*)ptr));
    return 0;  
}

Вы должны использовать ((char*)ptr) (удалить ведущий *). Это выражение разрешается по адресу из A. Поскольку %s ожидает начальный адрес строки.

Если вы используете *((char*)ptr), он преобразуется в значение char A. Значение ASCII A равно 0x41, это не тот адрес, к которому вы обычно можете получить доступ. А ниже отладочное сообщение показывает, что именно адрес 0x41 вызывает нарушение прав доступа.

enter image description here

После внесения вышеуказанных изменений ваш код может работать, как показано ниже :

enter image description here

И, кстати, C опасная красота ...

1 голос
/ 09 апреля 2020

Ваш код не соответствует. Вы получаете адрес age и height и помещаете его в ptr, но вы прямо указываете значение name. Получение адреса значения добавляет уровень косвенности (например, использование & на char* дает вам не char*, а char**, адрес адреса символа).

Исправление вашего кода, чтобы сделать его согласованным:

void* ptr;
ptr = &name; //Added &.
printf("My name is %s", *((char**)ptr));
ptr = &age;
printf("\nAge:%d", *((int*)ptr));
ptr = &height;
printf("\nHeight:%2.2f", *((float*)ptr));

И теперь он должен работать. Вы также можете избавиться от этого дополнительного уровня косвенности (& и *) для уменьшения путаницы.

...