Подтвердить что ты не робот

Объявление типа указателей?

Я просто прочитал, что нам нужно указать тип указателей, объявляя их в C (или С++) i.e.:

int *point ;

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

4b9b3361

Ответ 1

Type-безопасности. Если вы не знаете, к чему должен указывать p, тогда не было бы ничего, чтобы предотвратить ошибки категории, такие как

*p = "Nonsense";
int i = *p;

Проверка статического типа - очень мощный инструмент для предотвращения всех подобных ошибок.

C и С++ также поддерживают арифметику указателя, которая работает только в том случае, если известен размер целевого типа.

адрес занимает тот же объем памяти, какой бы ни был тип

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

Ответ 2

Потому что:

  • адреса для разных типов не должны иметь одинаковый размер. Стандарт явно указывает это (стандарт C 2011 (онлайн-проект), 6.2.5/28).
  • type-safety: это позволяет компилятору обнаруживать, когда вы предоставляете несовместимый указатель на функцию или в задании. Это, в свою очередь, предотвращает уродливые ситуации, когда вы испортили порядок аргументов функции.
  • компилятор должен знать тип, когда указатель разыменован.
  • для выполнения арифметики указателя размер объекта, на который указывает, должен быть известен и, следовательно, его тип.

Последние два пункта не относятся к указателям void, поэтому они не могут быть разыменованы, и на них не может быть выполнена арифметика указателя. В стандарте указано, что указатель void должен быть достаточно большим, чтобы удерживать какой-либо указатель (кроме указателей на объекты, которые представляют собой совсем другую историю), и что назначение и указатели void могут быть сделаны без приведения ( по крайней мере, в C, в С++ всегда нужны броски).

Ответ 3

Одна из причин заключается в арифметике указателя. Вы не можете сделать p+1, если не знаете размер элемента, к которому относятся p - это размер типа, для которого p является указателем. Если вы попробуете p+1 на void *p, вы, вероятно, получите плохой ответ (это то же самое, что и в случае с char *, но, возможно, вы этого не хотели, он попал на -pedantic как предупреждение и -pedantic-errors как ошибка).

Другая причина - безопасность типа. Если функция получает в качестве аргумента int *, вы не можете передать указатель на char (строку). Вы получите предупреждение (ошибка с -Werror/-pedantic-errors). Рассмотрим этот (фиктивный) код:

void test(int *x)
{
}

int main()
{
    char *x = "xyz";
    test(x);
    return 0;
}

Компиляция (с использованием gcc (GCC) 4.8.2 20131017 (Red Hat 4.8.2-1)) дает:

1.c: In function ‘main’:
1.c:8:2: warning: passing argument 1 of ‘test’ from incompatible pointer type [enabled by default]
  test(x);
  ^
1.c:1:6: note: expected ‘int *’ but argument is of type ‘char *’
 void test(int *x)
      ^

Ответ 4

Итак, зачем нам объявлять его тип?

Вы хотите узнать тип указателя, чтобы можно было выполнить проверку статического типа.

Нам также нужно знать тип для арифметики указателя для работы, например, когда мы индексируем в массив (что эквивалентно арифметике указателя) разных size, указатель будет скорректирован на зависящую от типа сумму. Если мы рассмотрим проект стандарта C99 6.5.6 Аддитивные операторы говорят (внимание мое):

Для добавления оба операнда должны иметь арифметический тип, или один операнд должен быть указатель на тип объекта [...]

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

Вы также сказали:

адрес занимает тот же объем памяти, какой бы тип он ни был. Итак, зачем нам объявлять его тип?

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

Кроме того, мы можем видеть, что и в разделе стандартного раздела C99 проекта 6.2.5 Types 27, где говорится:

[...] Указатели на другие типы не должны иметь одинаковые требования к представлению или выравниванию.

а в проекте стандартного раздела С++ 3.9.2 В составных типах параграф 3 говорится:

[...] Представление значений типов указателей определяется реализацией. Указатели на cv-квалифицированные и cv-неквалифицированные версии (3.9.3) совместимых с макетами типов должны иметь одинаковые требования к представлению и выравниванию значений (3.11). [...]

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

Ответ 5

Вам нужно указать тип в соответствии с требованиями стандарта. Более того, чтобы не возникало проблем при попытке выполнить арифметику указателя, такую ​​как сложение или вычитание.

Ответ 6

Тип указателя появляется во время разыменования и арифметики указателя. Например

int x=10;     //Lets suppose the address of x=100
int *ptr=&x;   //ptr has value 100
printf("The value of x is %d", *ptr);
ptr++;  // ptr has value 104(if int is 4bytes)

В приведенном выше примере тип указателя является int, поэтому компилятор начнет искать значения, хранящиеся в следующих 4 байтах (если int составляет 4 байта), начиная с адреса памяти 100. Таким образом, тип указателя сообщает компиляторам, сколько байты, которые он должен искать во время разыменования. Если типа указателя не было, как бы компилятор знал бы, сколько байтов должно выглядеть во время разыменования. И когда мы сделали ptr ++, тип указателя указывает, сколько ptr должно быть увеличено. Здесь ptr увеличивается на 4.

char c='a';   //Lets suppose the address of c = 200
char* ptr=&c;   //ptr has value 200
ptr++;   //ptr has value 201(char assumed to be 1 byte) 

Тип указателя указывает, что ptr увеличивается на 1 байт.

Ответ 7

В то время как у процессоров часто есть разные инструкции для "загрузки байта с адреса", "загрузка 16-разрядного полуслова с адреса" и "загрузка 32-битного слова из адреса", а также для "хранения", операции, C использует тот же синтаксис для загрузки байта из адреса, чтобы загрузить любое другое значение размера. Учитывая утверждение:

int n = *p;

компилятор может генерировать код, который загружает байт, полуслово или слово из адреса в p и сохраняет его в n; если p является * float, он может генерировать более сложную последовательность кода для загрузки значения с плавающей запятой в c, обрезать его, преобразовать в int и сохранить преобразованное значение в n. Не зная тип p, компилятор не может знать, какая операция будет подходящей.

Аналогично, оператор p++ может увеличить адрес в p на один, два, четыре или какое-то другое число. Сумма, на которую увеличивается адрес, будет определяться объявленным типом p. Если компилятор не знает тип p, он не знает, как настроить адрес.

Можно объявить указатель без указания типа вещи, на которую он указывает. Тип такого указателя void*. Однако нужно преобразовать void* в реальный тип указателя, прежде чем делать что-нибудь полезное с ним; основная полезность void* заключается в том, что если указатель преобразуется в void*, он может передаваться как void* по коду, который ничего не знает о фактическом типе указателя. Если указатель в конечном итоге предоставляется коду, который знает его тип, и этот код возвращает указатель обратно к этому типу, результат будет таким же, как указатель, который был преобразован в void*.

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

Ответ 8

Чтобы он мог выполнять арифметические и другие операции. Рассмотрим эти два примера:

int* p; /* let the address of the memory location p pointing to be 1000*/
p++;
printf("%u",p); /* prints 1004 since it is an integer pointer*/


char *p; /* let the address of the memory location p pointing to be 1000*/
p++;
printf("%u",p); /* prints 1001 since it is an char pointer*/

Надеюсь, это поможет вам!

Ответ 9

На самом деле нам не требуется (см. ниже), чтобы объявить тип, но мы должны. Указатель хранит информацию о местоположении объектов, а тип определяет, сколько места занимает память.

Размер объекта, хранящегося в указанной памяти, необходим в различных случаях: создание массива, копирование, копирование и, наконец, создание объекта с помощью new.

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

void* dontKnowWhatTypeIsHere;

Указатель на пустоту считается универсальным. Он может указывать на любой объект, и когда мы хотим использовать его с типом, мы просто сделаем reinterpret_cast.

Ответ 10

Множество вышеназванных высказываний, но apan является чисто правильным. Теперь ваш вопрос почему мы определяем тип указателей? Первое определение указателя Указатель, который может содержать адрес другой переменной. Вышеприведенное определение является частичным. Точное определение указатель - это переменная, которая может содержать адрес переменной, и если мы де-ссылку (выборку), он вернет значение настоящего на этом адресе. Если указатель не возвращает значение для разыменования, то это не указатель. Вы можете попробовать, что даже в gcc-компиляторе простая переменная может также содержать адрес другой переменной, но при разыменовании она даст вам ошибку. Теперь размер Независимо от типов данных размер указателя всегда равен размеру целого в этом конкретном компиляторе. Таким образом, размер указателя в gcc-компиляторе составляет 4 байта (размер целого), а в turboc его размер равен 2 байтам (размер целого). Теперь вопрос в том, почему равен размеру целого числа. Каким будет адрес любой переменной, которая может быть int, char, float и т.д., Адрес всегда является целым целочисленным числом и где целое число является хранилищем в int. Поэтому размер указателя равен размеру int, так как он также сохраняет адрес, который всегда является чистым целым числом.  Тогда в чем разница между int и char любого другого указателя типов данных. Во время извлечения ваш компилятор будет отображать количество байтов в соответствии с вашими типами данных, другие мудрые вы получите ошибку или не ошибку, но для вас есть непредсказуемый результат, но не для меня. То же правило применяется для приращения и уменьшения указателя, который он всегда увеличивает и уменьшает в соответствии с типами данных указателя.  Размер указателя не зависит от типа данных и, следовательно, от того, что ваш список ссылок попадает в изображение, потому что если вы попытаетесь объявить структуру внутри одной и той же переменной, тогда вы получите ошибку времени компиляции, потому что ваш компилятор не имеет размера структуры до его полной декларации, но сам ссылочный указатель той же структуры разрешен почему? Единственный ответ, потому что размер указателя не зависит от размера типа данных. Если у вас есть какие-либо вопросы, пожалуйста, спросите меня. благодаря asif aftab