Можем ли мы инициализировать переменную-указатель вручную, кроме 0?какая причина, если не могу инициализировать - PullRequest
1 голос
/ 16 июля 2011

Почему мы не можем инициализировать переменную-указатель с помощью пользовательского ввода?

Ответы [ 4 ]

3 голосов
/ 16 июля 2011

Вы можете инициализировать переменную-указатель любым значением.

int *ptr = 0;

Инициализирует указатель ptr в 0 (что практически означает, что он не указывает ни на что действительное)

int a = 10;
int *ptr = &a;

Инициализирует указатель ptr, указывающий на адрес целочисленной переменной a.

2 голосов
/ 16 июля 2011

Вы можете инициализировать указатель в глобальной области видимости для любого значения, которое является либо константным выражением, либо разрешается компоновщиком.Это потому, что компилятор C помещает константы прямо в код инициализации.Ссылочные символы также помещаются в код инициализации, и компоновщик заменяет эти символы действительными значениями адреса.

// global scope
int foo;
int* bar = &foo; // ok, since &foo is a known address
int* bar2 = &foo+1; /* ok, since &foo is a known
            address and the offset is constant. */
int* whatever = (int*) 0xabcd; /* Ok, since 0xabcd is
                a constant value, and can be used as
                an address, but it depends on your
                environment if this address makes any
                sense */
int *baz = bar; /* not OK, since the value of bar is
                   stored into the RAM at run time,
                   and the linker can't determine that
                   this value does point to &foo */

В функции вы можете инициализировать любую нестатическую переменную-указатель значением, которое уже существует,Это потому, что эти инициализации работают как обычные присвоения переменных.

Редактировать: Недопустимая int *baz = bar; часть

Отказ от ответственности: я описываю поведение типичного компилятора +наборы инструментов компоновщика, встречающиеся в Windows, Linux и * BSD, во встроенном мире инициализация может выглядеть очень по-разному.

Все инициализации переменных на глобальном уровне помещаются в отдельный сегмент данных в исполняемом файлеи копируются при запуске программы в ОЗУ.Это означает, что компоновщик должен создавать эти разделы путем сбора всех глобальных переменных и разрешения ссылок на символы в этом разделе.Компоновщик может разрешать только те значения, которые содержат только значения констант времени соединения, которые являются адресами и числовыми константами.Оператор int *baz = bar; использует косвенное значение, bar.Хотя bar может быть разрешена до &foo в данном конкретном случае, компилятору это не важно, поскольку стандарт требует, чтобы это было присваивание baz с содержимым оперативной памяти bar.И поскольку такие ссылки на память во время выполнения недоступны для компоновщика, так как компоновщик не может запустить программу, компилятор отказывается генерировать код для этого оператора.

Также изменяется тип bar с int* bar to int* const bar не помогает, потому что также константа имеет область памяти, и компилятор C должен действовать так, как будто он использует эту область памяти, когда значения используются где-то.Это означает, что даже когда ясно, какое значение имеет bar, компилятор не может поместить постоянное значение в объектный код, поскольку стандарт требует, чтобы память времени выполнения использовалась для определения значения bar, когда оноused.

В качестве примечания, в C ++ разрешено делать инициализации, основанные на данных времени выполнения.

1 голос
/ 16 июля 2011

Вы можете сделать это, например,

uint16_t *p = 0x00DFF01C;

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

(или выполняете избиение металла на «классическом» оборудовании Amiga в C)

1 голос
/ 16 июля 2011

Дай угадаю, ты пытаешься сделать что-то вроде этого:

char* usersInput;
scanf("%s", usersInput);     /* error */

Это не работает, потому что строка не была выделена. Вы могли бы, например, выберите максимальную длину ввода и выполните:

char* usersInput = malloc(10000);
scanf("%s", usersInput);     /* fine */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...