Этот сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Странности bc

Чем больше узнаёшь bc, тем больше в нём находишь странностей. Особенно меня поражают массивы.

Например, как вы думаете, чему равна длина массива, в который мы ещё ни разу не инициализировали? Правильно, единице. Почему? Да чёрт его знает, так в коде написано:

void
bc_array_init(BcVec* a, bool nums)
{
    BC_SIG_ASSERT_LOCKED;

    // Set the proper vector.
    if (nums) bc_vec_init(a, sizeof(BcNum), BC_DTOR_NUM);
    else bc_vec_init(a, sizeof(BcVec), BC_DTOR_VEC);

    // We always want at least one item in the array.
    bc_array_expand(a, 1);
}

Или вот такой код:

define void f(*a[]) {
    . = a[99]
}

f(b[]); length(b[])

Чему будет равна длина массива b[]?

Правильный ответ — она будет равна ста. Потому что в функции, куда мы передали этот массив по ссылке, происходит чтение из 99-го (массивы начинаются с нуля) элемента. В коде bc ясно сказано:

// The bc spec says that if an element is accessed that does not
// exist, it should be preinitialized to 0. Well, if we access
// an element *way* out there, we have to preinitialize all
// elements between the current last element and the actual
// accessed element.
if (v->len <= idx)
{
    BC_SIG_LOCK;
    bc_array_expand(v, bc_vm_growSize(idx, 1));
    BC_SIG_UNLOCK;
}

Как только идёт обращение к несуществующему элементу массива, неважно, для чтения или записи, он получается значение «ноль».

В этих случаях я даже уже и не понимаю — баги это или нет. Вроде нет, но выглядит контринтуитивно.

6 комментариев
hsh 1 мес

Почему? Да чёрт его знает, так в коде написано

вообще-то потому что они всегда хотят иметь хотя бы один элемент в массиве!

Евгений Степанищев 1 мес

Для чего? :-)

hsh 1 мес

Для чего? :-)

ну хочется им что вы мешаете людям вайбить

Евгений Степанищев 1 мес

И правда :-)

hsh 1 мес

Правильный ответ — она будет равна ста. Потому что в функции, куда мы передали этот массив по ссылке, происходит чтение из 99-го (массивы начинаются с нуля) элемента.

ну вот в lua например так не сделали и поэтому если есть дырка в ключах — оно ломается

```
a = {}
a[1] = 1
print(#a) — — length: 1

a = {}
a[2] = 1
print(#a) — length: 0

a = {}
a[1] = 1
a[3] = 1
print(#a) — length: 1
```

так что может не так уж всё и плохо!

Евгений Степанищев 1 мес

Тут я скорее про чтение говорю. Читаешь, в массиве значения появляются.

hsh 1 мес

print(#a) — — length: 1

интересно оно тут два дефиса в два тире превращает

Евгений Степанищев 1 мес

Эгеевские приколы.

abuse 1 мес

vsegda byli startovye znacheniya massivah — programisty pro eto znayit

Евгений Степанищев 1 мес

Не пишите ерунды.

abuse 1 мес

tak zhe znayut chto masdiv uzhe zapolnen tekuschimi znacheniyami pamyati i nado ne zabyvat ego pronulit esli nado pustye — vsegda srazu eto vsyo bylo izvestno eschyo shkolnikam

Евгений Степанищев 1 мес

Ну не пишите ерунды, пожалуйста, а? Я просто буду стирать в следующий раз, ваши усилия будут просто пропадать зря.

Во-перых, вы путаете выделение памяти в системе с массивом в высокоуровневом языке. Во-вторых, нет тут никаких «технических значений». В свежесозданном массаве тут всегда ровно один элемент с нулём.