Борьба с указателями в C - PullRequest
3 голосов
/ 06 июня 2011

Мне показалось, что я понял основные понятия указателей согласно учебникам на C, но я действительно запутался, когда на самом деле кодировал. У меня есть несколько вопросов:

1 - допустим, у меня есть:

customList arrayOfLists[3]; //global
//...
void someMethod()
{
   int i;
   for (i=0; i<3; i++)
   {
        customList l = arrayOfLists[i];

        //METHOD1
        //Next time I come back to this function, element is still there!
        removeFirstElement(&l);              

        //METHOD2
        //Next time I come back to thsi function, element is gone!
        //removeFirstElement(&(arrayOfLists[i])); 
   }
}

Почему бы Method1 и Method2 не работали одинаково? В обоих случаях я в основном говорю, удалить первый элемент списка, расположенный по адресу addressX. Создает ли это копию массива?

2 - В чем разница между:

struct1.ptr1->ptr2->someIntValue //1
&(struct1).ptr1->ptr2->someIntValue //2

2-й способ не имеет смысла для меня, и я не знаю, что там происходит, но, похоже, это работает. Я ожидал первого способа работы, но он не дает мне правильного ответа.

3 - допустим, я делаю это:

ptr2 = ptrToStruct;
ptr1 = ptr2;
ptr2->intProp = 5;
ptr2 = ptrToStruct2;

ptr1 все еще указывает на начальную ячейку памяти или это тот же самый ptr2? Что такое ptr1-> intProp?

Спасибо.

Ответы [ 5 ]

1 голос
/ 11 сентября 2014

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

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

0 голосов
/ 06 июня 2011

Для вопроса 1 метод 1 берет адрес переменной l. l инициализируется для хранения копии значения i элемента массива. Это совершенно другое место в памяти. Обратите внимание, что если функция removeFirstElement() зависит от аргумента, являющегося указателем на массив, она с треском провалится, используя метод 1.


Для вопроса 2 строка 2 действительна, но не по той причине, о которой вы, вероятно, думаете. То, что он оценивает, получает адрес struct1.ptr1->ptr2->someIntValue. Обратите внимание, что вы взяли не адрес структуры, а член члена, на который он указывал. Вы, вероятно, хотели, чтобы это было так:
(&struct1).ptr1->ptr2->someIntValue

Это с треском провалится.

Оператор доступа к члену (.) используется в значениях структуры для доступа к члену. На LHS у вас есть указатель на структуру, и он должен использовать оператор стрелки (->) для доступа к члену. Или, разыменуйте указатель сначала, затем используйте точку (чему эквивалентен оператор стрелки).

(*(&struct1)).ptr1
/* is equivalent to: */
(&struct1)->ptr1


Что касается вопроса 3, предположим, что ptr1 и ptr2 являются указателями на то, на что указывает структура ptrToStruct, тогда да, ptr1 все еще указывает на то, на что оно указывает. Вы никогда не изменяли переменную ptr1, только структуру, на которую она указывала. Поскольку и ptr1, и ptr2 указывают на одну и ту же структуру (другими словами, с псевдонимом), при доступе к элементу ptr1->intProp. вы должны увидеть одно и то же значение.
0 голосов
/ 06 июня 2011

Q3)

ptr2 = ptrToStruct;
ptr1 = ptr2;
ptr2->intProp = 5;
ptr2 = ptrToStruct2;

Указывает ли ptr1 на исходную ячейку памяти, или это тот же ptr2?

Да, ptr1 указывает на область памяти, на которую указывает ptrToStruct.Воздействие ptr2 на указание на другое местоположение (ptrToStruct2) не влияет на ptr1.

Что такое ptr1-> intProp?

5

0 голосов
/ 06 июня 2011
  1. customList - локальный указатель;arrayOfLists - это глобальный массив.Они живут в разных областях памяти.

  2. * & имеет более низкий приоритет, чем . или ->.Если бы я упростил 1-е выражение до j, 2-е выражение упростилось бы как &j.

  3. Указатели такие же, как и любой другой тип.В приведенном ниже коде

    int j, k;
    k = 5;
    j = k;
    k = 12;
    

    j имеет 5 или 12?

0 голосов
/ 06 июня 2011
customList l = arrayOfLists[i];
//METHOD1
//Next time I come back to this function, element is still there!
removeFirstElement(&l);     

Это неправильно: вам нужно что-то вроде:

customList *l = &arrayOfLists[i];
removeFirstElement(l);

Для второго вопроса:

struct1.ptr1->ptr2->someIntValue // this will give you someIntValue
&(struct1).ptr1->ptr2->someIntValue // this will give you the address of memory where someIntValue is stored
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...