LINUX.ORG.RU

максимальное число элементов в массиве в С?

 , , openrange


1

3

эт что же массив(еденичных элементов) по определению меньше всего адресного пространства ??

т.е если вся память адреса 0...2^64-1 то массив элементов единичного размера начинающийся с 0 адресса не может в себе содержать элемент максимального значения типа индекса

( ща когда 64 бита это не очень актуально но для 32 и тем более 16 оказывается массив(байтов) обязан быть меньше сегмента байтов.)

★★☆
Ответ на: комментарий от anonymous

Не удивляет? А как это понимать?

а это хрень какая-то. НЁХ. Ибо массив в принципе нельзя со скаляром сравнивать. Как круглое и тёплое. Но в ВАШИХ примерах вы _преобразуете_ массив в его адрес. Тебя же не удивляет то, что 0x80 == 0xFFFFFF80 ? Ну если первое char, а второе int. Ну наросло 24 единички, что в этом странного?

drBatty ★★
()
Ответ на: комментарий от drBatty

массив с лёгкостью отбрасывает свой размер, и становится скаляром, а именно константным указателем

Ты, наверно, хотел сказать rvalue типа указателя. Потому что с константными указателями (как переменными) у тебя промашечька выходит.

anonymous
()
Ответ на: комментарий от anonymous

А нельзя в C взять другую базу. Твое a[-1] по стандарту UB

это НЕ UB, если a указывает на ВТОРОЙ элемент массива. Я имею полное право сначала прибавить к указателю на массив 1, а потом вычесть. Даже для массива в один эл-т.

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

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

(да, посмотрел по ссылке — там я про это забыл сказать, извини)

drBatty ★★
()
Ответ на: комментарий от anonymous

Если количество элементов положительно помезается в ОДЗ типа, то и (количество элементов-1) тоже будет помещаться в этот тип.

и что?

drBatty ★★
()
Ответ на: комментарий от drBatty

$ ./a.out m=0x7fffb6a705a0 &m=0x7fffb6a705a0 &c=0x7fffb6a7059f &cp=0x7fffb6a70590 &ccp=0x7fffb6a70588 &cpc=0x7fffb6a70580

И что означают тогда значения выражений &cp, &ccp, &cpc?

anonymous
()
Ответ на: комментарий от anonymous
$ ./a.out 
m=0x7fffb6a705a0
&m=0x7fffb6a705a0
&c=0x7fffb6a7059f
&cp=0x7fffb6a70590
&ccp=0x7fffb6a70588
&cpc=0x7fffb6a70580

Надеюсь так лучше видно.

anonymous
()
Ответ на: комментарий от drBatty

При некоторых условиях максимальный индекс действительно численно равен размеру массива, даже без -1.

int a[5];
a[5];

UB, так как присутствует разыменование указателя.

Так в каких случаях максимальный индекс численно равен размеру массива (без -1), если считать за индекс то значение которое можно поставить в [] в выражении (не в декларации)?

anonymous
()
Ответ на: комментарий от anonymous

Почему? Откуда это следует? Нигде не сказано, что количество элементов в массиве должно помещаться в ptrdiff_t.

хорошо. Сказано, что _любая_ разность двух _допустимых_ указателей помещается в ptrdiff_t.

А раз так, то создав массив в X эл-тов, я получаю два допустимых указателя array+0 и array+X.

разность этих указателей равна очевидно X, и помещается в ptrdiff_t

Сл-но X помещается в ptrdiff_t.

Более того размер массива в байтах (sizeof(char [10])) должен помещаться в size_t, который беззнаковый тип.

ну и что? Ну значит ты рискуешь словить UB. Если сомневаешься, пусть malloc выделяет, и проверяй на NULL.

drBatty ★★
()
Ответ на: комментарий от drBatty

массив в принципе нельзя со скаляром сравнивать

А где у нас массив сравнивается со скаляром? Или где (кроме твоих постов) утверждается, что такое происходит?

anonymous
()
Ответ на: комментарий от drBatty

я тебе наверно не открою тайну что B ( предок С) был слотовый язык где все базовое это 16битовый слот отсюда у С и выросло что для указателя битвэлию лиш иногда p ==& p а для массива a== &a всегда

это просто так устоновленно эволюцией языка и пока не прикрутили более жёсткую(сохранив все преимущества безпиповости при необходимости) типизацию с явным выделением void

a == & a

было вообще синтаксически верно без всяких варнингов даже

qulinxao ★★☆
() автор топика
Ответ на: комментарий от anonymous

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

оно. Создавая массив ты получаешь множество эл-тов X, каждый x принадлежит типу(множеству) «указатель». вычитая любой x2 из любого x1 получаешь i12, который принадлежит множеству I, которое входит в множество ptrdiff_t. складывая x1 + i12 получаешь x2, который входит в X (и является указателем, причём валидным). Для упрощения многих алгоритмов у тебя ещё есть индекс i0n, который численно равен N (размеру массива X). элемент xn является допустимым указателем, но его нельзя разименовать. Индекс i12 может быть отрицательным, если x2>x1. Потому ptrdiff_t знаковый тип.

drBatty ★★
()
Ответ на: комментарий от anonymous

На уровне какого кода?

машинного, внутри одного модуля трансляции.

drBatty ★★
()
Ответ на: комментарий от drBatty

Я имею полное право сначала прибавить к указателю на массив 1

Да, но в этом случае у тебя не получится изменить базу индексации массива на 1.

anonymous
()
Ответ на: комментарий от anonymous

массив с лёгкостью отбрасывает свой размер, и становится скаляром, а именно константным указателем

Ты, наверно, хотел сказать rvalue типа указателя. Потому что с константными указателями (как переменными) у тебя промашечька выходит.

я хотел сказать ровно то, что я сказал. где промашечка-то?

drBatty ★★
()
Ответ на: комментарий от drBatty

Сказано, что _любая_ разность двух _допустимых_ указателей помещается в ptrdiff_t.

Где такое сказано? Сказано, что операция вычитания указателей определена только, если ее результата помещается в ptrdiff_t. Это лишь означает, что не всякие указатели можно вычитать.

anonymous
()
Ответ на: комментарий от drBatty

Если сомневаешься, пусть malloc выделяет, и проверяй на NULL.

Если для 64-битной машины пытаться выделить памяти на PTRDIFF_MAX байт, то malloc вернет NULL, тут даже memory overcommit не поможет (ну нет у меня столько памяти). А с крос компиляцией под 32-битную архитектуру у меня возникли проблемы.

anonymous
()
Ответ на: комментарий от drBatty

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

anonymous
()
Ответ на: комментарий от anonymous

Надеюсь так лучше видно.

видно. Вот смотри:

int a = 10;
int b = 10;
int c = 10;
int d = 10;
тут ты меня тоже будешь пытать, зачем компилятору надо хранить в памяти 4 десятки?

ВНЕЗАПНО: он их и НЕ хранит. Потому-что ты меня(и я тебя) обманул. Вот код полностью:

int main()
{
	int a = 10;
	int b = 10;
	int c = 10;
	int d = 10;
	return a+b+c+d;
}
а вот то, что получилось:
00000000004004a0 <main>:
  4004a0:	b8 28 00 00 00       	mov    eax,0x28
  4004a5:	c3                   	ret    
куда пропали все десятки?

вот ещё код, если ты сомневаешься в том, что с адресами это не работает

int a[20];
int main()
{
	int b = 7;
	return &a[b];
}
тут тоже получается тупо mov eax,0x600a3c и никаких гвоздей. Всё потому, что a и b — константы, и их сумма тоже константа, вот их и не нужно хранить.

drBatty ★★
()
Ответ на: комментарий от anonymous

Так в каких случаях максимальный индекс численно равен размеру массива (без -1), если считать за индекс то значение которое можно поставить в [] в выражении (не в декларации)?

в a[] нельзя поставить N, ибо a[N] это разименование. А вот написать int *b = a+5; вполне можно. А потом можно b[-1].

drBatty ★★
()
Ответ на: комментарий от qulinxao

было вообще синтаксически верно без всяких варнингов даже

сущность «массив» преобразуется в сущность «указатель». Что в этом странного? Вполне себе документированное и ожидаемое поведение.

drBatty ★★
()
Ответ на: комментарий от drBatty

Ты же писал, что

Потому-то они и равны, ибо для преобразования в (long long) массив необходимо переделать в указатель(ибо вообще говоря массив в скаляр преобразовать в принципе невозможно, а вот через указатель — без проблем).

Так есть там сравнение массива со скаляром, или там сравнение адресов?

anonymous
()
Ответ на: комментарий от anonymous

Это лишь означает, что не всякие указатели можно вычитать.

ясное дело что не всякие. А только из _одного_ массива X.

drBatty ★★
()
Ответ на: комментарий от drBatty

ага и поэтому (игнорирую разнотиповость)

для массива верно a == &a - что несколько хм как бы это сказать

по моему личному мнению &a просто не должно для массивов работать - но это услажняет компилятор поэтому предпочли просто отбрасывать в начальных версиях - а потом обратная совместимость зацементировала всё это

qulinxao ★★☆
() автор топика
Ответ на: комментарий от anonymous

Если для 64-битной машины пытаться выделить памяти на PTRDIFF_MAX байт, то malloc вернет NULL, тут даже memory overcommit не поможет (ну нет у меня столько памяти). А с крос компиляцией под 32-битную архитектуру у меня возникли проблемы.

ну вот для этого и придумали эти всякие типы, что-бы проблем не было. Их и не будет, если брать 32х битный limits.h. Видать у тебя что-то 64х битное пролезло(там Over9000 include).

drBatty ★★
()
Ответ на: комментарий от drBatty

ну посчитай чему равна разность между указателем на начало массива и на элемент указывающий за последний(ending указатель)

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

qulinxao ★★☆
() автор топика
Ответ на: комментарий от anonymous

которое входит в множество ptrdiff_t

Почему оно туда обязательно входит?

по вышеизложенному определению ptrdiff_t из стандарта.

drBatty ★★
()
Ответ на: комментарий от qulinxao

т.е на верхнем уровне взятие адреса от локального /глобального масива нонсенс

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

qulinxao ★★☆
() автор топика
Ответ на: комментарий от drBatty

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

qulinxao ★★☆
() автор топика
Ответ на: комментарий от drBatty

Естественно, компилятор при оптимизации не помещает в код значения, которые не используются. Естественно, компилятор при оптимизации заменяет выражения, которые может посчитать, на их значения. Ты оптимизацию-то выключи.

anonymous
()
Ответ на: комментарий от anonymous

Так есть там сравнение массива со скаляром, или там сравнение адресов?

там сравнение адресов. Хотя a это не адрес, а массив.

drBatty ★★
()
Ответ на: комментарий от drBatty

С поиском и установкой 32-х битных бибилиотек и заголовочных файлов у меня проблемы возникли.

anonymous
()
Ответ на: комментарий от drBatty

А только из _одного_ массива X.

Это условие необходимо, но не достаточно.

the expression (P)-(Q) has the value i−j provided the value fits in an object of type ptrdiff_t

Часть «provided the value fits in an object of type ptrdiff_t» переводится как «при условии, что значение помещается в объект типа ptrdiff_t».

anonymous
()
Ответ на: комментарий от qulinxao

для массива верно a == &a - что несколько хм как бы это сказать

НЕ ВЕРНО. Это преобразования массива в адрес.

по моему личному мнению &a просто не должно для массивов работать - но это услажняет компилятор

упрощает. Это не баг, а фича. Адрес константы не имеет смысла, потому строго говоря запись &a тоже не имеет смысла. И тем не менее, ввели фичу для того, что-бы &a таки работало, и делало из массива указатель на массив. Хотя оно и так делается.

Фича полезная, если-бы я решил отправить в функцию указатель на первый эл-т массива, а не массив. Без этой фичи, и с возможности передать ссылку на массив, была-бы неоднозначность(неясно что передать, ссылку на массив, или указатель на первый эл-т). В итоге мы имеем ненужную фичу + невозможность передать массив в функцию. Fail.

drBatty ★★
()
Ответ на: комментарий от drBatty

the signed integer type of the result of subtracting two pointers

«Знаковый целочисленный тип результата вычитания двух указателей». Где здесь сказано, что результат вычитания указателей всегда определен?

anonymous
()
Ответ на: комментарий от qulinxao

И то, и то имеет смысл. Если есть объект, то есть и адрес, по которому он хратиться. Литералы не задают объект, а лишь имеют значение.

anonymous
()
Ответ на: комментарий от drBatty

Как он относиться к вопросу. Где у тебя

максимальный индекс численно равен размеру массива (без -1), если считать за индекс то значение которое можно поставить в [] в выражении (не в декларации)

. Или твой ответ надо читать так

Ни в каких случаюх максимальный индекс не будет численно равен размеру массива (без -1), если считать за индекс то значение которое можно поставить в [] в выражении (не в декларации).

Если так, то зачем писать остальную часть вопроса?

А вот написать int *b = a+5; вполне можно. А потом можно b[-1].

anonymous
()
Ответ на: комментарий от drBatty

Хотя a это не адрес, а массив.

Адрес и массив это одно и тоже? Нет? Так что же там: адрес или массив?

anonymous
()
Ответ на: комментарий от drBatty

там сравнение адресов.

Вопрос остается открытым:

А где у нас массив сравнивается со скаляром? Или где (кроме твоих постов) утверждается, что такое происходит?

anonymous
()
Ответ на: комментарий от anonymous

но в том и прикол что побитово для массивов

&a == a

если бы для всех литералов выолнялось бы это

то &4 обязанно было бы быть равно 4 :)

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

ну посчитай чему равна разность между указателем на начало массива и на элемент указывающий за последний(ending указатель)

к примеру максимальный размер 32768 эл-тов. Разность 32767 эл-тов.

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

ты про эл-т за последним? В 16и битах указатель на эл-т ЗА ПОСЛЕДНИМ будет внезапно -32768 (0x8000). Это хрен знает где, но и так НЕ валидный. А вот перед ним -32768-1=32767=0x7FFF. Всё нормально.

И да, на 32х битах адресная арифметика будет работать с 4Гб памяти, но ВСЕ массивы должны быть не больше 2Гб. А ровно — можно, ибо наименьшее отрицательное число таки ровно -2³¹.

drBatty ★★
()
Ответ на: комментарий от drBatty

(bitvalue)a == (bitvalue)&a - что тут не ясного

а всё потому что для людей привычней одинаково записывать r-value и l-value

не будь этой привычки не появлялось бы таких забавностей

qulinxao ★★☆
() автор топика
Ответ на: комментарий от drBatty

не между крайними массива , маждй левым краем и указателем за коней массива ( что разрешено )

qulinxao ★★☆
() автор топика
Ответ на: комментарий от drBatty

для массива верно a == &a

НЕ ВЕРНО. Это преобразования массива в адрес.

Да там есть преобразование массива в адрес. Но, тем не менее, для всякого массива a выражение a==&a вычисляется в 1, что в C означает true, т.е. выражение имеет значение ИСТИНА.

anonymous
()
Ответ на: комментарий от drBatty

Без этой фичи, и с возможности передать ссылку на массив, была-бы неоднозначность(неясно что передать, ссылку на массив, или указатель на первый эл-т)

Пример, пожалуйста.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.