Может ли обычная переменная содержать адрес другой переменной? - PullRequest
0 голосов
/ 05 июля 2019

Моя проблема довольно сумасшедшая, но послушайте, я создал две нормальные переменные, подобные int a,b, а затем назначил адрес переменной b для a, и когда я печатаю адрес обоих a и&b показывает случайное число, но одинаковое для обоих.Как это возможно?в то время как a не является переменной-указателем.

int main()
{
    int a,b;
    a = &b;
    printf("%u  %u",a,&b);
    return 0;
}

I got a number that must be address and both are same.

Ответы [ 2 ]

4 голосов
/ 05 июля 2019
  1. Если вы скомпилировали эту программу с помощью компилятора C, компилятор должен предупредить вас, что в a = &b; указаны неправильные типы, поскольку он нарушает ограничения для присваивания.Вы получили это предупреждение?Вы игнорировали это?

  2. После того, как компилятор предупредил вас, он предположительно сгенерировал код для a = &b; для преобразования &b, который имеет тип int *, в тип int,В некоторых реализациях C int может содержать всю информацию int *, и преобразование работает простым способом.В некоторых реализациях C int слишком мал, чтобы содержать всю информацию int *.

  3. printf("%u %u",a,&b); использует неправильные спецификаторы.%u для unsigned int, но a - int, а b - int *.Стандарт C не определяет результирующее поведение при использовании неправильных спецификаторов.

  4. Несмотря на отсутствие определения, вполне вероятно, что ваша реализация C напечатала значение a какесли он был преобразован в unsigned int, и он мог сделать то же самое с &b.Это приведет к выводу двух одинаковых чисел.Этот результат не является надежным из-за нарушения правил о спецификаторах, упомянутых выше.

  5. Если ваша реализация действительно определяет преобразование указателя в int обычным способом иint достаточно широк, чтобы вместить всю информацию int *, тогда правильный способ написания вашей программы:

#include <stdio.h>

int main(void)
{
    int a, b;
    a = (int) &b;
    printf("%#x %p\n", (unsigned) a, (void *) &b);
}

Это не гарантированно отображатьодинаковые выходные строки для двух значений, в частности потому, что %p является гибким - точный формат определяется реализацией, поэтому он может варьироваться в зависимости от реализаций Си.Но они будут одинаковыми или похожими во многих реализациях C.

Как правило, указатели не следует преобразовывать в целые числа.Однако бывают случаи, когда это необходимо, например, при написании кода ядра, который должен обрабатывать адреса особым образом, или при написании высокопроизводительного кода, который должен решать проблемы выравнивания.В этой ситуации лучшим решением, чем использование int, является включение <stdint.h> и использование uintptr_t.uintptr_t - это целочисленный тип без знака, который подходит для преобразования в указатели.

1 голос
/ 05 июля 2019

Может ли обычная переменная содержать адрес другой переменной?

Да (возможно).

Компилятор обычно преобразует исходный код в машинный код для целевого процессора. Для машинного кода ЦП (почти для всех ЦП) нет типов - все (все инструкции, все указатели, все целые числа, все числа с плавающей запятой, ...) являются просто структурами битов; и процессор не имеет представления, является ли последовательность битов (в памяти или в регистре) адресом, целым числом или чем-то еще.

Это означает, что если вы можете убедить компилятор сохранить указатель в целое число, сам ЦП не будет знать или заботиться.

для С; довольно легко убедить компилятор сохранить указатель в int, либо выполнив a = &b; и проигнорировав любое предупреждение; или сделав a = (int)&b;, чтобы подавить предупреждение. Конечно, это не будет переносимым, и значение может быть искажено для соответствия (например, если указатель 64-битный, а int 32-битный, то вы можете ожидать, что половина указателя будет отброшена для получения значения вписывается в int).

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