Jump to content

    
Sign in to follow this  
Target

Как определить массив больше 32768 значений?

Recommended Posts

Есть Atmega2561, внешняя память и сам чип позволяют адресовать до 64К ОЗУ.

В то же время не могу определить массив

__no_init byte array[40000];

 

Компилятор IAR для AVR ругается "array is too large".

 

Можно ли как-нибудь обойти ограничение в 32768 значений и определить байтовый массив до 64К?

Share this post


Link to post
Share on other sites
Компилятор IAR для AVR ругается "array is too large".
Да. Согласно стандарту максимальный размер массива - INT_MAX. Обойти никак. Вы можете сделать структуру из нескольких массивов и через приведение указателей обращаться к массивам как к одному сплошному через *(ptr+index), при обращении же через ptr[index] index будет трактоваться как знаковое число. Я так думаю.

 

Share this post


Link to post
Share on other sites
Согласно стандарту максимальный размер массива - INT_MAX.

Здесь - иное. Например, массив типа int нельзя создать с числом элементов больше чем 16383, для float - 8191...

Share this post


Link to post
Share on other sites
Здесь - иное. Например, массив типа int нельзя создать с числом элементов больше чем 16383, для float - 8191...
Всё правильно, здесь именно «это». Максимальный размер массива — INT_MAX байтов.

Максимальное число элементов типа T — INT_MAX / sizeof(T)

Причина: в языке C разница двух указателей имеет тип int (именно знаковая) и допустима для любых двух (под)элементов одного агрегата (включая элемент сразу за последним элементом массива). Учитывая возможность приведения к char*.

Вот и получается, что раз разница двух приведённых к char* указателей должна влазить в int, то и размер (в смысле sizeof() — размера объекта) любого агрегата — массива или структуры — не может превышать INT_MAX.

Всё остальное — расширения языка.

 

Вы можете сделать структуру из нескольких массивов
Нельзя.

struct {
    char a[XXX];
    char b[YYY];
} foo;
ptrdiff_t d1 = &foo.b[YYY] - &foo.a[0];
ptrdiff_t d2 = &foo.a[0] - &foo.b[YYY];

Для того, чтобы можно было получить обе разности, должно быть sizeof(foo) <= INT_MAX

 

upd:

Тьху, это уже (ещё) привычка равенства размера указателя и int работает.

 

Строго говоря, не int, а таки ptrdiff_t, так что на x86_64 можно и больше, чем INT_MAX, там sizeof(int) = 4 а sizeof(void*) = 8

 

Так что вполне может быть «модель памяти» для 8- или 16-битной архитектуры, у которой указатель по умолчанию 24-или-более-битный и объект может занимать больше INT_MAX. С такими вещами сталкивался, но никогда не пользовался ввиду неэффективности и поэтому забыл.

 

В большинстве случаев таки упор в INT_MAX.

Share this post


Link to post
Share on other sites
... при обращении же через ptr[index] index будет трактоваться как знаковое число. Я так думаю.

А какая разница, если адрес 16-битный? Пусть как хочет его трактует, но адресует-то всё-равно правильно.

Share this post


Link to post
Share on other sites
Всё правильно, здесь именно «это».

Я с Вами соглашусь, если Вы объясните: при чём здесь INT_MAX ?

Имхо: размер определяется типом size_t (и значением SIZE_MAX), а разность указателей - типом ptrdiff_t

 

В компиляторе IAR для mega2561:

typedef size_t unsigned long

typedef ptrdiff_t signed long

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this