Как этот указатель был разрешен в этом C-коде? - PullRequest
2 голосов
/ 02 сентября 2011

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

main()
{
   int a[]={11,2,3};
   int *p=&a;
   printf("%d",*(p+1));
}

Это должно дать мне некоторое значение мусора, так как p указывает на следующий 1D массив

main()
{
   int a[]={11,2,3};
   int *p=a;
   printf("%d",*(p+1));
}

Это должно вывести 2.

Однако ОБА этих функций печатают 2.

Это не то, что я ожидал. Кто-нибудь может объяснить, что происходит?

Может кто-нибудь сказать, как я делаю указатель, указывающий на весь массив, чем на отдельный элемент.

Ответы [ 3 ]

3 голосов
/ 02 сентября 2011

Если вы скомпилируете первую программу, вы получите предупреждение компилятора:

 warning: initialization from incompatible pointer type

Поскольку тип p является указателем на целое число, а тип &a равен pointer to array of integer. Compiling the second program is fine, because again p has type int *and a has type int [] `(т. е. массив целых чисел), но в C вы можете просто передать / назначить целочисленный массив целочисленному указателю.Значению указателя присваивается начальный адрес массива.

Когда вы определяете массив с квадратными скобками в C, массив помещается сразу в стек или раздел данных, поэтому начальный адрес массивасовпадает с адресом самой переменной массива!Это отличается от массивов, созданных с помощью malloc.

. Для вас это означает следующее: предположим, что переменная a расположена по адресу 4e78ccba.Это означает, что &a равно 4e78ccba.Но в C значение a при передаче / назначении указателю по определению является адресом начала массива, так что это также 4e78ccba.

Опять же, есливы устанавливаете вещи с помощью malloc, все будет иначе.(Попробуйте !!) И, кстати, обратите внимание на предупреждения.:) Это интересный вопрос, потому что C настолько слабо напечатан, что только в первом случае предупредил вас.Языку со строгой типизацией не понравилось бы смешивание целочисленного указателя с указателем целочисленного массива.

ADDENDUM

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

#include <stdio.h>
int main() {
    /* a is an array of ints, but can be used as a pointer to int */
    int a[] = {11, 2, 3};

    /* Using a as an int pointer */
    int* p = a;
    printf("%d\n", *(p+1));

    /* Now here is how to make a pointer to the array itself! */
    int (*q)[] = &a;
    printf("%d\n", (*q)[2]);

    return 0;
}

Эта программа выводит

2
3
3 голосов
/ 02 сентября 2011

Это связано с тем, что идентификатор пустого массива в этом случае распадается на указатель типа int *.

&a вычисляет указатель на весь массив (типа int (*)[3]), который, хотя и другого типа, является тем же адресом, что и адрес первого элемента.

1 голос
/ 02 сентября 2011

Оба раза это указатель на int, а p + 1 увеличивается только на размер int независимо от того, откуда на самом деле пришел указатель.

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