Почему генерируется ошибка, когда я печатаю указатель и вычитаю его? - PullRequest
0 голосов
/ 04 февраля 2020

Почему здесь не работает типизация??

#include<stdio.h>
int main(){
   int x = 5;
   float y = 7.0;
   float *p = &y;
   int *q = &x;
   printf("p is %d\nq is %d\np - q is %d", p, q, (p - q));
   return 0;  
  }

Я получаю эту ошибку invalid operands of types 'float*' and 'int*' to binary 'operator-'; что это значит?

Ответы [ 4 ]

3 голосов
/ 04 февраля 2020

Ошибка означает, что компилятор не может определить общий тип двух операндов, один из которых имеет тип float *, а другой int *. Не существует неявного преобразования между этими типами.

Но в любом случае программа имеет неопределенное поведение, потому что, по крайней мере, вы не можете вычесть два указателя, которые не указывают на элементы одного и того же массива или на память после последнего элемент одного и того же массива.

Из стандарта C (6.5.6 Аддитивные операторы)

9 Когда вычтены два указателя, оба должны указывать на элементы одного массива объект или один последний элемент массива; Результатом является разница индексов двух элементов массива.

И использование неправильных спецификаторов преобразования (как, например, %d с указателем) для предоставленных аргументов в функции printf также вызывает неопределенное поведение.

из C стандарта (7.21.6.1 функция fprintf)

9 Если спецификация преобразования недопустима, поведение не определено.275) Если какой-либо аргумент не является правильным типом для соответствующей спецификации преобразования, поведение не определено.

0 голосов
/ 04 февраля 2020

Вы не можете вычесть такие указатели и получить значимый результат в стандарте C.

За 6.5.6 Аддитивные операторы , параграф 9 стандарта C11 :

Когда вычитаются два указателя, оба должны указывать на элементы одного и того же объекта массива или один за последним элементом последнего объекта массива; В результате получается разница индексов двух элементов массива.

В этом случае одна переменная int или float считается массивом размером 1.

Полученная

int x = 5;
float y = 7.0;
float *p = &y;
int *q = &x;

попытка вычислить значение p - q приводит к неопределенному поведению.

Per J.2 Неопределенное поведение :

Поведение не определено в следующих обстоятельствах:

...

  • Указатели, которые не указывают на или чуть дальше один и тот же объект массива вычитается

Однако подобный код, скорее всего, не вызовет проблем, поскольку он просто вычитает два целочисленных значения (хотя я не проверил тщательно), но результат не должно быть значимым:

int x = 5;
float y = 7.0;
float *p = &y;
int *q = &x;

intptr_t diff = ( intptr_t ) p - ( intptr_t ) q;
0 голосов
/ 04 февраля 2020

Полагаю, вы хотите вычесть фактические значения, на которые указывают ваши указатели. C преобразует int в float неявно, когда вы работаете на float и int.

Кроме того, у вашей программы есть некоторые проблемы:

  • Не используется %f спецификатор типа для печати float указатель

  • Не используется оператор * для доступа к значениям указателя.

Вот ваша программа, работающая:

#include <stdio.h>
int main()
{
    int x = 5;
    float y = 7.0;
    float *p = &y;
    int *q = &x;
    printf("p is %f\nq is %d\np - q is %f", *p, *q, (*p - *q));
    return 0;
}

С выходами:

p is 7.000000
q is 5
p - q is 2.000000
0 голосов
/ 04 февраля 2020

Редактировать: Как было отмечено в комментариях, вычитание двух указателей void * не соответствует стандарту C. Если вы хотите вычесть два указателя, чтобы найти расстояние между ними, правильный подход - привести их к целому числу соответствующего размера, а затем выполнить целочисленное арифметическое c.

Например:

printf("p is %p\nq is %p\np - q is %ld\n", p, q, ((intptr_t)p - (intptr_t)q));

Исходный ответ:

Это означает, что оператор минуса не определен для смешанных типов указателей. Если вы хотите вычесть эти два указателя, например, чтобы найти расстояние между ними, лучшим вариантом будет привести их оба к void* указателям.

Кроме того, вы должны напечатать значения указателей с помощью %p спецификатор вместо %d.

Например:

printf("p is %p\nq is %p\np - q is %ld\n", p, q, ((void*)p - (void*)q));

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...