Объясните вывод этого кода C? - PullRequest
0 голосов
/ 14 августа 2010

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

 /*
  * This code in C attempts to exploit insufficient bounds checking
  * to legitimate advantage.
  * 
  * A dynamic structure with the accessibility of an array.
  * Handy for small-time code, but largely unreliable.
  */
 int array[1] = {0};
 int index = 0;

 put(), get();

 main ( )
 {
    put(1); put(10), put(100);
    printf("%6d %5d %5d\n", get(0), get(1), get(2));
 }

 put ( x )
 int x;
 {
    array[index++] = x;
 }

 get ( index )
 int index;
 {
    return array[index];
 }

Вывод:
1 3 100

Ответы [ 3 ]

2 голосов
/ 14 августа 2010

Существует проблема, заключающаяся в том, что вы объявляете 'массив' как массив длиной 1, но вы записываете в него 3 значения.Должно быть как минимум 'array [3]'.Без этого вы пишете в нераспределенную память, поэтому может произойти все что угодно.

Причина, по которой он выводит «3» без исправления, заключается в том, что он выводит значение глобальной переменной «index», котораяследующий int в памяти (в вашем случае - как я уже сказал, может произойти все что угодно).Даже если вы перезаписываете это с помощью вызова put(10), значение индекса используется в качестве индекса в присваивании, а затем постинкрементно, что устанавливает его обратно в 2 - затем оно устанавливается в 3 в концеput(100) вызов и последующий вывод через printf.

1 голос
/ 14 августа 2010

Это неопределенное поведение, поэтому единственное реальное объяснение: «Он делает некоторые вещи на одной машине, а другие - на других машинах».

Кроме того, что с синтаксисом функции K & R?

РЕДАКТИРОВАТЬ: printf предположение было неверным. Что касается синтаксиса, прочитайте K & R 2nd Edition (на обложке отмечена красная отметка ANSI), в котором используется современный синтаксис функций (среди других полезных обновлений).

0 голосов
/ 14 августа 2010

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

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

Наконец, ваш синтаксис объявления функции действителен, но архаичен. Эта форма редко встречается и практически не слышна в новом коде. Объявите put как:

int put(int x) {…}

И всегда объявлять main как:

int main(int argc, char **argv) {…}

Имена argc и argv не важны, но типы имеют значение. Если вы забудете эти параметры, демоны могут вылететь из вашего носа.

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