|
Определение размера массива на этапе компиляции, Задачка |
|
|
|
Sep 10 2012, 07:02
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Не уверен, в тот ли форум написал - не нашёл специализированного подфорума по программированию, есть этот и ещё в разделе по DSP. Вопрос чисто по программированию на С/С++. Задача. Есть энное количество массивов. Тип элемента массива в данном случае не важен (на практике он может быть любым - в частности, у меня это небольшая структура), поэтому в примере будет просто int. Длины массивов произвольные. Обработка данных из массивов возложена на функцию. Вариант на голом С. CODE int A[] = { 1, 2, 3 }; int B[] = { 4, 5 }; int C[] = { 6 }; int D[] = { 7, 8, 9, 0 }; ... // и т.д.
void f(int *p, size_t size) { ... } вызов (пример): CODE f(A, sizeof(A)); Очевидный недостаток - нужно руками задавать правильный размер массива. При достаточно большом количестве массивов и вызовов, а также при интенсивном редактировании этого кода (особенно, когда обычным спутником такого редактирования является метод copy'n'paste), можно легко передать адрес одного массива, а размер другого, просто не уследив глазами за именами в аргументах. Хочется избавиться от этого недостатка. Очевидное решение в стиле С - использовать макроподстановку препроцессора: CODE #define PASS_ARRAY(a) a, sizeof(a)
f(PASS_ARRAY(A)); Это в некотором смысле получше, но есть свои минусы: препроцессор игнорирует пространства имён - возможен конфликт имён, макросу лучше задавать такое имя, чтобы оно было поуникальнее (а значит, подлиннее, поуродливее, сильнее загромождающее код), но самое главное то, что препроцессор не производит контроль типов и если на вход подать не массив, а указатель, то результат работы функции будет ошибочным при полном отсутствии ругани со стороны компилятора. В общем, основная проблема в низкоуровневом представлении массива на С, который при передаче в функцию даунгрейдится до указателя и внутри функции уже видится просто как адрес на объект своего типа. Хочется обойти этот недостаток - ведь в точке вызова-то у компилятора вся информация о массиве, переданном в качестве аргумента, есть. Вопрос. Имеется ли тут хорошее решение на С или С++. И если имеется, то какое? P.S. Забегая вперёд, скажу, от ответ знаю, но, во-первых, возможно есть и другие, получше, поинтереснее, во-вторых, сама по себе задачка, имхо, очень интересная и достойная того, чтобы поломать немножко над ней голову, тем более, что практическое решение явно полезно, а не просто академическая головоломка.  P.P.S Если кто-то знает решение с ходу, просьба не сообщать его сразу - дайте другим тоже потерзать задачку. Сообщите только, что знаете решение (это, возможно, лучше мотивирует других решателей).
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
 |
Ответов
|
Sep 11 2012, 11:57
|
Местный
  
Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205

|
Опять не понял Код #include <iostream>
template <typename T, int N> int len(T (& a)[N]) { return N; }
const int a[] = {1,1,1,1,2,3,4,5,6}; // 9 элементов const int b[] = {1,1,1,5,6}; // 5 элементов
volatile int d;
int foo(const int arr[]) { std::cout << "len:" << len(arr) << "\n"; }
int main() { foo(a); foo(b); } Цитата mike@mike-work:/tmp$ LC_ALL=C g++ test.cpp test.cpp: In function 'int foo(const int*)': test.cpp:15:33: error: no matching function for call to 'len(const int*&)' test.cpp:15:33: note: candidate is: test.cpp:4:5: note: template<class T, int N> int len(T (&)[N])
|
|
|
|
|
Sep 11 2012, 15:22
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (kurtis @ Sep 11 2012, 18:57)  Опять не понял Что тут не понятного? Вы слепили свою функцию, скормили ей массив, внутри функции массив уже не виден, а виден только указатель на него - и что, вы хотите, чтобы компилятор восстановил из указателя массив? Заведите массив внутри вашей функции и передавайте его функции len(). Массив, а не указатель. Именно тут и проявилась фича метода - невозможно по ошибке передать в функцию указатель - только массив. Такая ошибка гарантировано отлавливается на этапе компиляции.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Sep 11 2012, 19:17
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ViKo @ Sep 11 2012, 20:03)  Такая же особенность будет в простеньком #define a_s(array) arr_sum(array, sizeof(array)/sizeof(array[0])) Это для числа элементов. А для просто размера - пойдем в обход, чтобы выловить передачу не-массива Код #define a_s(array) arr_sum(array, (sizeof(array)/sizeof(array[0])*sizeof(array[0]))  PS Задумался... в "чиста Си" от GCC уже столько костылей плюсовых... ужас - бери и делай закат Солнца.
Сообщение отредактировал _Pasha - Sep 11 2012, 19:20
|
|
|
|
Сообщений в этой теме
dxp Определение размера массива на этапе компиляции Sep 10 2012, 07:02 Сергей Борщ QUOTE (dxp @ Sep 10 2012, 10:02) P.P.S Ес... Sep 10 2012, 08:13 gerber Для работы с массивом на С совсем необязательно зн... Sep 10 2012, 08:40 dxp QUOTE (gerber @ Sep 10 2012, 15:40) Для р... Sep 10 2012, 09:05  gerber Цитата(dxp @ Sep 10 2012, 13:05) Вот как... Sep 10 2012, 12:46   _Артём_ Цитата(gerber @ Sep 10 2012, 15:46) Тогда... Sep 10 2012, 12:56   ViKo Цитата(gerber @ Sep 10 2012, 15:46) Элеме... Sep 10 2012, 12:59 _Pasha Не пользовался (юзал только препроцессор), но в GC... Sep 10 2012, 11:56 dxp QUOTE (_Pasha @ Sep 10 2012, 18:56) Не по... Sep 10 2012, 12:26  MrYuran Цитата(dxp @ Sep 10 2012, 16:26) А как в ... Sep 10 2012, 13:14  _Pasha Цитата(dxp @ Sep 10 2012, 15:26) А как в ... Sep 10 2012, 13:41   dxp QUOTE (_Pasha @ Sep 10 2012, 20:41) Ответ... Sep 10 2012, 15:54    _Pasha Цитата(dxp @ Sep 10 2012, 18:54) Наскольк... Sep 10 2012, 18:35 ig_z QUOTE (dxp @ Sep 10 2012, 10:02) Вопрос. ... Sep 10 2012, 12:59 kurtis 1. В нулевом элементе хранить размер массива.
2. Е... Sep 10 2012, 14:40 dxp QUOTE (gerber @ Sep 10 2012, 19:46) Элеме... Sep 10 2012, 15:13 Xenia Всё это - палиативные решения. Окажется массив дву... Sep 10 2012, 15:29 kurtis Так какой правильный ответ? Sep 10 2012, 15:36 amaora С макросами я бы делал как-то вот так.
Код#define... Sep 10 2012, 16:12 Rst7 QUOTE Двумерных массивов в С/С++ не бывает.
Шутит... Sep 10 2012, 17:02 ViKo Я бы пользовался макроподстановкой, описанной в пе... Sep 10 2012, 18:16 Xenia Еще бы темплейты задействовать Sep 10 2012, 18:31 dxp QUOTE (Rst7 @ Sep 11 2012, 00:02) Шутить ... Sep 11 2012, 00:59 Rst7 QUOTE Для настоящего (тру Ъ) двумерного массива но... Sep 11 2012, 03:35 dxp QUOTE (Rst7 @ Sep 11 2012, 10:35) Ну, во-... Sep 11 2012, 04:37 Rst7 QUOTE Повторять всё обилие различий не хочется, ту... Sep 11 2012, 05:04 dxp QUOTE (Rst7 @ Sep 11 2012, 12:04) Наприме... Sep 11 2012, 05:31 Rst7 QUOTE Допустим, у нас есть настоящий честный двуме... Sep 11 2012, 07:47 dxp QUOTE (Rst7 @ Sep 11 2012, 14:47) Приведи... Sep 11 2012, 08:31 dxp Наверное, пришло время обнародовать решение, как в... Sep 11 2012, 10:09 kurtis А чем это принципиально отличается от sizeof(a)/si... Sep 11 2012, 11:46 dxp QUOTE (kurtis @ Sep 11 2012, 18:46) А чем... Sep 11 2012, 11:51   dxp QUOTE (ViKo @ Sep 12 2012, 00:03) Такая ж... Sep 12 2012, 01:36    ViKo Цитата(dxp @ Sep 12 2012, 04:36) В том-то... Sep 12 2012, 04:38 MrYuran Закорючка лишняя.
Либо если уж разыменовывать, то ... Sep 11 2012, 12:37 amaora А компиляторы C++ уже способны это оптимизировать?... Sep 11 2012, 14:07 kurtis ЦитатаЗаведите массив внутри вашей функции и перед... Sep 11 2012, 17:20 AHTOXA Цитата(kurtis @ Sep 11 2012, 23:20) Может... Sep 11 2012, 18:30 kurtis Чем это принципиально отличается от sizeof и как м... Sep 11 2012, 19:04 AHTOXA Цитата(kurtis @ Sep 12 2012, 01:04) Чем э... Sep 12 2012, 03:51 kurtis Медлено начинаю понимать...
Код#include <iost... Sep 12 2012, 03:41 kurtis Спасибо. Ситуация начинает проясняться.
Да, в так... Sep 12 2012, 03:57
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|