Является ли следующий правильный код?Использование выделенного пространства для хранения нескольких массивов
Предположим, известно, что все типы указателей объекта имеют одинаковый размер и ориентацию, с размером не больше 8.
// allocate some space to A, and set *A and **A to different regions of that space
char*** A = malloc(92);
*A = (char**)((char*)A + 2*sizeof(char**));
**A = (char*)*A + 4*sizeof(char*);
// initialize the second char** object
A[1] = *A + 2;
// write four strings further out in the space
strcpy(A[0][0],"string-0-0");
A[0][1] = A[0][0] + strlen(A[0][0]) + 1;
strcpy(A[0][1],"string-0-1");
A[1][0] = A[0][1] + strlen(A[0][1]) + 1;
strcpy(A[1][0],"string-1-0");
A[1][1] = A[1][0] + strlen(A[1][0]) + 1;
strcpy(A[1][1],"string-1-1");
Я нахожу такие вещи, как это полезно в тех случаях, когда это может быть не просто, как освободить объект. Например, скажем, A [1] [1] может перенаправляться или перенаправляться на адрес строкового литерала. В любом случае вы просто освободите A. Также количество запросов на malloc минимизировано.
Мое беспокойство в отношении того, что это неправильный код, основано на следующем. Используя черновой вариант стандарта, у меня есть:
7.22.3 Функции управления памятью
- ... Указатель возвращается, если распределение удается соответствующим образом выровнены таким образом, что он может быть назначен указатель на любой тип объекта с фундаментальным требованием выравнивания, а затем используется для доступа к такому объекту или массиву таких объектов в пространстве, выделенное (пока пространство не будет явно высвобождено) ...
Я я гарантируется возможность использования пространства в виде массива одного типа. Я не могу найти никакой гарантии, что я могу использовать ее как массив из двух разных типов (char * и char **). Обратите внимание, что использование некоторых массивов пространства как char уникально, учитывая, что к любому объекту можно получить доступ как массив символов.
Правила для эффективного типа согласуются с этим подходом, поскольку ни один отдельный байт не используется как часть двух разных типов.
Хотя выше показывает, как представляется, нет явного нарушения стандарта, стандарт не явно разрешить поведение либо, и мы имеем пункт 2 главы 4 (курсив мой):
Если Требование '' должно '' или '' не должно '', которое появляется за пределами ограничения или ограничения времени выполнения, поведение не определено. Неопределенное поведение иначе указано в этом Международном стандарте словами «неопределенное поведение» или отсутствием какого-либо явного определения поведения. В этих трех различиях нет разницы; все они описывают «поведение, которое не определено».
Это немного расплывчато, когда сама модель памяти настолько расплывчата. Использование пространства, возвращаемого malloc() для хранения массива любого (одного) типа, по-видимому, нуждается в явном разрешении, которое я приводил выше. Поэтому можно утверждать, что использование этого пространства для непересекающихся массивов разных типов также требует явного учета и без него остается неопределенным поведением в главе 4.
Так что, если конкретный пример кода верен , что не так с аргументом, что он явно не определен и поэтому не определен, в части главы 4 из стандарта, который указан выше?
'char *** A = malloc (90);' неправильный размер указателя 8 – 4386427
@ 4386427, спасибо, я немного поспешил на мою арифметику. – Kyle
@ 4386427, я получаю 6 указателей размера 8 имеют размер 6 * 8 = 48 и 4 строки длины 10 составляют 44, 48 + 44 = 92. – Kyle