определение простого массива целых чисел - PullRequest
0 голосов
/ 25 мая 2011

Почему я могу это сделать?

int array[4]; // i assume this creates an array with 4 indexes

array[25]=1; // i have assigned an index larger than the int declaration

NSLog(@"result: %i", array[25]); // this prints "1" to the screen

Почему это работает, если индекс превышает декларацию?каково значение числа в объявлении, если оно не влияет на то, что вы действительно можете сделать с массивом?

Спасибо.

Ответы [ 8 ]

4 голосов
/ 25 мая 2011

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

Если произойдет запись в местоположение, сопоставленное с соответствующими разрешениями, оно будет работать. До тех пор, пока это не произойдет из-за другого макета.

1 голос
/ 25 мая 2011

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

В этом случае вы выделили 4 дюйма памяти.

Так что, если вы перейдете к массиву [2], он будет думать "память в массиве + sizeof (int) * 2"

Измените 2 на 25, и вы только посмотрите, сколько памяти у 25 int за стартом. Поскольку нет никаких проверок, чтобы убедиться, что вы находитесь в границах (при назначении или печати), это работает.

Ничего не скажешь, что-то еще может быть выделено там!

1 голос
/ 25 мая 2011

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

0 голосов
/ 25 мая 2011

C по своей конструкции не выполняет проверку границ массива. Он был разработан как язык системного уровня, и накладные расходы на явную проверку границ во время выполнения могут быть непомерно высокими во многих случаях. Следовательно, C допускает «опасный» код и должен использоваться осторожно. Если вам нужно что-то «более безопасное», тогда C # или Java могут быть более подходящими, но есть определенный удар по производительности.

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

В C массив - это непрерывный блок памяти. Получая доступ к массиву за пределами, вы просто получаете доступ к памяти за пределами массива. Доступ к такой памяти будет недетерминированным, он может быть нежелательным, он может принадлежать смежной переменной или может принадлежать переменным вызывающей функции или выше. Это может быть адрес возврата для текущей функции или вызывающей функции. В ОС с защитой памяти, такой как Windows или Linux, если вы заходите настолько далеко за пределы, что больше не находитесь в диапазоне адресов, назначенном процессу, возникнет исключительная ситуация ошибки.

0 голосов
/ 25 мая 2011

Это небезопасное программирование.Этого действительно следует избегать, потому что это не может привести к сбою вашей программы.Что действительно лучшее, на что ты мог надеяться.Это может дать вам результаты мусора.Это непредсказуемо и может действительно испортить вашу программу.Однако, поскольку вы не знаете, что это неправильно, потому что это не приведет к сбою, это нарушит целостность ваших данных.Поскольку в C нет try / catch, вам действительно следует проверить входные данные.Помните, что scanf возвращает int.

0 голосов
/ 25 мая 2011

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

0 голосов
/ 25 мая 2011

Он делает очень плохие вещи. Если массив объявлен функции локально, вы, вероятно, пишете в расположениях стека выше кадра стека текущей функции. Если он объявлен глобально, вы, вероятно, пишете в памяти, выделенной для смежных переменных. В любом случае, это «работает» по чистой случайности.

0 голосов
/ 25 мая 2011

Число в объявлении определяет, сколько памяти должно быть зарезервировано, в этом случае 4 * sizeof(int).

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

Поведение зависит от компилятора, платформы и некоторой случайности. Не делай этого.

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