C: Убедитесь, что элемент, который вы возвращаете из массива, правильный - PullRequest
1 голос
/ 03 августа 2009

Скажем, у нас есть этот код C:

int x[] = {1, 2, 3, 4, 5};

printf("%d", *(x + 1)); //prints 2
printf("%d", *(x + 500)); //prints 7209065 (...?)

Как вы можете видеть из второго вызова, он по-прежнему что-то возвращает ... но это мусор.

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

Ответы [ 11 ]

9 голосов
/ 03 августа 2009

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

4 голосов
/ 03 августа 2009

Проще говоря, вы не можете. Это просто функция / ошибка / дизайн языка C и C ++.

2 голосов
/ 03 августа 2009

Как все уже отметили, вы не можете сделать это из-за природы C. Однако, есть инструменты, которые вы можете использовать для инструментальной обработки вашего кода и выполнения дальнейших проверок доступа к памяти (для использования во время цикла разработки). ). Purify - один из таких инструментов, и я нашел бесценный для выявления таких проблем.

2 голосов
/ 03 августа 2009

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

1 голос
/ 03 августа 2009

C не проверяет границы массива. На вас лежит обязанность проверить, что доступ находится в пределах, сравнивая с длиной массива (sizeof(x)/sizeof(x[0])).

1 голос
/ 03 августа 2009

В общем, именно поэтому были созданы "более умные" типы данных - такие как массивы STL в C ++, которые могут генерировать исключения для ошибок индексации за пределами границ.

0 голосов
/ 03 августа 2009

По большей части ошибочно думать о том, что C имеет тип «массив».Синтаксис, который вы используете - сахар вокруг указателей. x [y] - это действительно синтаксический сахар для * x + sizeof (что-то) * y (где «что-то» сложнее, чем я хочу, в данном случае что-тоis int ).

Помните, что C - это язык среднего уровня ... своего рода "переносимая сборка", и вы не будете предъявлять необоснованные ожидания к таблице.

0 голосов
/ 03 августа 2009

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

Иногда это зависит от входных данных программы, что означает, что ошибка возникает только тогда, когда был введен какой-либо ввод (например, если ваше значение «500» было получено в качестве ввода от пользователя). (это немного раздражает в поиске и обработке)

Наиболее проблемные случаи, это те, в которых вы получаете «мусор» и «никак не можете об этом знать».

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

0 голосов
/ 03 августа 2009

Для уточнения ответов ДжаредПара и Эда:

Массивы C - это блок непрерывной памяти. Когда вы говорите int x [] = {1, 2, 3, 4, 5}; C выделяет достаточно памяти для 5 целых чисел. Вы просите 500-й элемент, так что вы получаете память, которая не была должным образом выделена для X. Это мусор, и он может меняться при каждом запуске.

Я согласен с Робом. Добавьте переменную с количеством элементов в X и просто выполните цикл for для каждого.

Если вы хотите, чтобы массивы изменяли длину во время выполнения, есть лучшие способы сделать это.

0 голосов
/ 03 августа 2009

Именно поэтому в большинстве (более надежных) библиотек C, использующих массивы, вы видите размер массива, передаваемого в качестве параметра, например, fread () fwrite ()

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