В языке C, как найти размер массива в пользовательской функции с этим массивом, передаваемым из main () [duplicate]

Если производительность имеет значение, используйте функцию GetComputerNameEx :

  bool IsComputerInDomain () {uint domainNameCapacity = 512;  var domainName = new StringBuilder ((int) domainNameCapacity);  GetComputerNameEx (COMPUTER_NAME_FORMAT.ComputerNameDnsDomain, domainName, ref domainNameCapacity);  return domainName.Length & gt;  0;  } [DllImport ("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern bool GetComputerNameEx (COMPUTER_NAME_FORMAT NameType, StringBuilder lpBuffer, ref uint lpnSize);  enum COMPUTER_NAME_FORMAT {ComputerNameNetBIOS, ComputerNameDnsHostname, ComputerNameDnsDomain, ComputerNameDnsFullyQualified, ComputerNamePhysicalNetBIOS, ComputerNamePhysicalDnsHostname, ComputerNamePhysicalDnsDomain, ComputerNamePhysicalDnsFullyQualified}  

7
задан unj2 6 October 2010 в 03:38
поделиться

6 ответов

Вам нужно также передать размер массива функции. Когда вы передаете массив в свою функцию, вы действительно передаете адрес первого элемента в этом массиве. Таким образом, указатель указывает только на первый элемент в вашей функции.

Поскольку память в массиве непрерывна, вы все равно можете использовать арифметику указателя, такую ​​как (b + 1) , чтобы указать на второй элемент или эквивалентно b [1 ]

  void print_array (int * b, int num_elements) {for (int i = 0; i & lt; num_elements; i ++) {printf ("% d", b [  я]);  }}  

Этот трюк работает только с массивами, а не с указателями:

  sizeof (b) / sizeof (b [0])  

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

16
ответ дан Brian R. Bondy 15 August 2018 в 23:55
поделиться
  • 1
    +1, но вы должны использовать size_t , а не int , для размера массива. – Jonathan Grynspan 6 October 2010 в 03:05
  • 2
    Я почти сделал это, но я не уверен, что это тип на C, и я попытался предоставить ответ, который применим к обоим, поскольку вопрос был помечен как оба. – Brian R. Bondy 6 October 2010 в 03:07
  • 3
    Я попробовал такое же объяснение, как ссылка, которую вы указали в этом ответе: stackoverflow.com/questions/3613302/… очень распространенная ошибка. – kriss 6 October 2010 в 09:58

Для C вам нужно передать длину (количество элементов) массива.

Для C ++ вы можете передать длину, НО, если у вас есть доступ к C ++ 0x, BETTER должен использовать std :: array . Здесь здесь и здесь . Он переносит длину и обеспечивает проверку внеочередного доступа, если вы обращаетесь к элементам с помощью функции члена at () .

2
ответ дан Arun 15 August 2018 в 23:55
поделиться

Почему вы не используете шаблоны функций для этого (C ++)?

  template & lt; class T, int N & gt;  void f (T (& amp; r) [N]) {} int main () {int buf [10];  F (BUF);  }  

EDIT 2:

Теперь у qn появляется C-тег, и тег C ++ удален.

5
ответ дан Chubsdad 15 August 2018 в 23:55
поделиться
  • 1
    Я думаю, что лучший вопрос - почему бы не использовать вектор? – JoshD 6 October 2010 в 02:53
  • 2
    @JoshD: sans C ++ 0x, массивы фиксированного размера очень удобны для того, чтобы вы могли их инициализировать (ala int a [] = {1, 2, 3}; ). избегайте выделения кучи - особенно приятно, если они маленькие, транзитные и в чувствительном к производительности цикле. – Tony Delroy 6 October 2010 в 03:01
  • 3
    Это умное решение, но оно работает только для массивов статического размера. – Greg Hewgill 6 October 2010 в 03:02
  • 4
    @ Тони: Я согласен. Но в этом случае вы можете использовать трюк sizeof (b) / sizeof (b [0]) и передать размер функции, не так ли? Мое впечатление было то, что это указатели на массивы с динамическим размером. Возможно, я неправильно понял. – JoshD 6 October 2010 в 03:09
  • 5
    @ Greg / @ JoshD: проверьте вопрос: жалоба заключалась в том, что int sizeof_b = sizeof (b) / sizeof (b [0]); не может быть выполнено внутри вызываемой функции. Очевидно, что попытка его использования указывает постоянный размер времени компиляции. – Tony Delroy 6 October 2010 в 03:44

В C99 вы можете потребовать, чтобы массив имел как минимум n элементы:

  void print_array (int b  [статические n]);   

6.7.5.3.7 : объявление параметра как '' массив типа '' должно быть скорректировано на «квалифицированный указатель на тип» '', где типом качества (если есть) являются те, которые указаны в [и] вывода типа массива. Если ключевое слово static также появляется внутри [и] вывода типа массива, то для каждого вызова функции значение соответствующего фактического аргумента должно обеспечивать доступ к первому элементу массива с по меньшей мере таким количеством элементов, как указано по выражению размера.

В GCC вы можете передать размер массива неявно следующим образом:

  void print_array (  int n, int b [n]);   
0
ответ дан Matt Joiner 15 August 2018 в 23:55
поделиться
  • 1
    Стоит отметить, что T foo (T myptr [статический 1]) - удобный и переносимый способ выражения понятия, что foo принимает указатель типа T * , который не может быть NULL (или любое другое недопустимое значение указателя, такое как (T *) - 1 ). – R.. 6 October 2010 в 07:07
  • 2
    И я считаю, что void print_array (int n, int b [n]); , который вы дали, является стандартным C, а не расширением gcc. Однако в случае одномерных массивов это совершенно бесполезно. Когда это становится полезным, это когда у вас многомерный массив с переменным размером в размере, отличном от первого. – R.. 6 October 2010 в 07:11

В c ++ вы также можете использовать некоторый тип класса списка, реализованный как массив с методом размера или как структура с членом размера (в c или c ++).

0
ответ дан Roman A. Taycher 15 August 2018 в 23:55
поделиться

Вы можете попробовать это ...

  #include & lt; cstdio & gt;  void print_array (int b [], size_t N) {for (int i = 0; i & lt; N; ++ i) printf ("% d", b [i]);  Е ( "\n");  } template & lt; size_t N & gt;  inline void print_array (int (& amp; b) [N]) {// может иметь цикл здесь, но встроенная пересылка в // одиночную функцию исключает код bloat ... print_array (b, N);  } int main () {int a [] = {1, 2};  int b [] = {};  int c [] = {1, 2, 3, 4, 5};  print_array (а);  // print_array (b);  print_array (с);  }  

... интересно b не работает ...

  array_size.cc: В функции `int main () ': array_size.cc  : 19: ошибка: нет соответствующей функции для вызова `print_array (int [0u]) ' 

JoshD указывает в комментариях ниже массивов размера re 0 размера (расширение GCC) и размер вывода выше.

0
ответ дан Tony Delroy 15 August 2018 в 23:55
поделиться
  • 1
    @Tony: b не работает, потому что его размер равен 1, но есть 0 элементов. – JoshD 6 October 2010 в 02:54
  • 2
    Это немного избыточно, если для 3-х разных массивов созданы 3 функции, не так ли? Вам было бы лучше иметь общую функцию печати и использовать функцию шаблона (inline?) Для вызова общей функции с аргументами массива и размера, не так ли? – Jonathan Leffler 6 October 2010 в 02:56
  • 3
    @Jonathan и @Tony: Даже с интерфейсом вы получите новый тип для каждого значения N. Это серьезный код раздувания. Зачем использовать шаблон, если у вас есть параметр функции? – JoshD 6 October 2010 в 03:04
  • 4
    @JoshD: Новый тип? Нет, вы этого не сделаете, и поскольку нет виртуальных функций, он не будет покрываться RTTI: отсюда и нулевая стоимость. В любом случае обертка для определения размера будет отмечена как встроенная, компилятор будет генерировать точный код, как если бы программист прошел размер, но без возможности типа на сайте вызова. – Ben Voigt 6 October 2010 в 03:07
  • 5
    @Josh: новый тип? Новая функция шаблона, да, но не новый тип, конечно? И если он определен inline ( template & lt; size_t N & gt; void print_array (int (& amp; b ([N]) {print_array (b, N);} ), набухание минимально, поскольку я в первую очередь программист на C, кроме значков, я использовал бы эту функцию и рассчитываю называть ее явным аргументом - как вы предлагаете. – Jonathan Leffler 6 October 2010 в 03:08
Другие вопросы по тегам:

Похожие вопросы: