Сломанный указатель C в заголовке Objective C - PullRequest
0 голосов
/ 18 ноября 2011

В моем заголовке есть указатель CGFloat, который используется для указания на массив CGFloat. Я заявляю это так: CGFloat* pointer;. В инициализации я пытаюсь установить указатель, используя этот код:

CGFloat newArray[2] = {
            0.0f, 1.0f,
        };

        pointer = newArray;

Это "на самом деле" работает. Я не получаю никаких ошибок компилятора и прочее. Когда я печатаю второе значение массива сразу после установки указателя с этим кодом: printf("%f", pointer[1]); Я получаю правильный результат (1.000000). Однако, когда я печатаю второе значение массива в методе next, я получаю 0.000000, что означает, что указатель больше не указывает на массив.

У меня есть два вопроса. Как я могу решить эту проблему и почему указатель работает сразу после установки, но снова «забывает» его значение?

Ответы [ 4 ]

1 голос
/ 18 ноября 2011

Larcus, newArray инициализируется в стеке в неглобальной области.Память для вашего массива выделяется в одной конкретной области видимости.Когда вы вызываете другой метод, CGFloat* pointer больше не указывает на newArray, потому что newArray может существовать или не существовать на данный момент.Если второй метод не вызывается из первой области видимости, то строго newArray будет освобожден из его исходного стекового фрейма.Вместо этого присвойте указатель следующим образом: pointer = new CGFloat[2]; pointer[0] = 0.0; pointer[1] = 1.0;

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

См. Википедию по Висячие указатели

Изюминка в том, что если вы не выделяете память с помощью malloc или new и назначаете эту память указателю, состояние этой памятибудет неопределеннымТолько malloc и new могут инициализировать память таким образом, чтобы он постоянно сохранялся во всех областях вашего приложения.

1 голос
/ 18 ноября 2011
CGFloat newArray[2] = {
        0.0f, 1.0f,
    };

Индексы массива начинаются с 0. pointer[1] печатает второй элемент в массиве, а не первый. pointer[2] находится вне конца массива.

CGFloat newArray[2] = {0,0};
newArray[0]; // this is the 1st item
newArray[1]; // this is the 2nd item
newArray[2]; // this is nonsense.

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

Если вам нужна функция, которая возвращает массив из двух чисел с плавающей запятой, вы должны сделать:

 CGFloat *two_of_these() {
     CGFloat *newArray = malloc(2 * sizeof(CGFLoat));
     newArray[0] = 42.0;
     newArray[1] = 59.4;
     return newArray;
 }

Просто убедитесь и позвоните free на это возвращаемое значение позже. Обратите внимание, что очень редко можно выделить что-то такое маленькое. Как правило, это будет структура, которая возвращается напрямую. См. CGPoint, CGRect, NSRange и т. Д ....

0 голосов
/ 18 ноября 2011

В общем случае время жизни из newArray короче pointer, поэтому указатель становится недействительным при втором вызове.Чтобы решить эту проблему, вам нужно переместить инициализационную переменную var, чтобы у нее было то же время жизни, что и у pointer.Другим решением будет выделение памяти во время выполнения (с использованием malloc и т. Д.) И освобождение его после использования.

0 голосов
/ 18 ноября 2011

Я думаю, вы получите индексы массива из ответа bbum. указатель указывает на адрес. Вы устанавливаете его по адресу newArray, но newArray не гарантируется, когда вызывается ваш второй метод.

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