Подтвердить что ты не робот

C - элемент за пределами массива

Я читал книгу K и R на C и обнаружил, что арифметика указателей в C позволяет получить доступ к одному элементу за пределами массива. Я знаю, что C позволяет делать почти что угодно с памятью, но я просто не понимаю, какова цель этой особенности?

4b9b3361

Ответ 1

C не позволяет доступ к памяти за пределами массива. Однако он позволяет указателю указывать на один элемент за пределами массива. Различие важно.

Таким образом, это нормально:

char array[N];
char *p;
char *end;

for (p = array, end = array + N; p < end; ++p)
    do_something(p);

(Выполнение *end будет ошибкой.)

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

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

Это означает, что C, возможно, не является хорошим инструментом для программирования приложений общего назначения.

Ответ 2

Часто полезно обозначить позицию "конец", которая находится за пределами фактического распределения, поэтому вы можете написать код, например:

 char * end = begin + size;
 for (char * curr = begin; curr < /* or != */ end ; ++curr) {
    /* do something in the loop */
 }

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

Почему у этого есть такая гарантия? Скажем, у вас была машина с 2 ^ 16 байтами памяти, адреса 0000-FFFF, 16-разрядные указатели. Предположим, вы создали 16-байтовый массив. Можно ли выделить память в FFF0?

Существует 16 байтов, которые свободно смежны, но:

begin + size == FFF0 + 10 (16 in hex) == 10000

который обертывается до 0000 из-за размера указателя. Теперь условие цикла:

curr < end == FFF0 < 0000 == false

Вместо итерации по массиву цикл ничего не сделает. Это нарушит много кода, поэтому в стандарте C указано, что распределение недопустимо.

Ответ 3

вы можете выйти далеко за пределы массива например `

int main()
{
        char *string = "string";
        int i = 0;
        for(i=0; i< 10;i++)
        {
                printf("%c\n", string[i]);
        }
        return 0;
}

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