2010-11-02 2 views
13

В C: Как вы находите число элементов в массиве структур, после отправки его функции?C: поиск числа элементов в массиве []

int main(void) { 
    myStruct array[] = { struct1, struct2, struct3, struct4, struct5, struct6 }; 
    printf("%d\n", sizeof(array)); 
    printf("%d\n", sizeof(array[0])); 
    f(array); 
} 
void f(myStruct* array) { 
    printf("%d\n", sizeof(array)); 
    printf("%d\n", sizeof(array[0])); 
} 

По какой-то причине printf в основном показывает разные результаты, чем printf в f. Мне нужно знать, сколько элементов в массиве.

+0

Поскольку 'sizeof()' является оператором времени компиляции, а не функцией-членом (как в C++). – ruslik

ответ

18

Вы не можете.

Вы должны пройти размер функции, например:

void f(myStruct* array, size_t siz); 

заметить также, что в f массива является указателем, в то время как в main это массив. Массивы и указатели - это разные вещи.

+1

Зачем использовать 'size_t'? Не могли бы вы просто использовать целое число для длины массива, или это не так безопасно? –

+2

@Christian Mann: Несколько причин, в том числе: тип значения, возвращаемого 'sizeof', -' size_t'; размеры массивов никогда не могут быть отрицательными, поэтому имеет смысл использовать тип unsigned для размера массива; 'size_t' гарантированно будет достаточно большим, чтобы удерживать максимальное количество байтов, которое может быть выделено в любой момент времени, тогда как' int' не является (IOW, если массив из T может содержать 2^64 байта, затем 'size_t' гарантированно будет 64 бита в ширину, но 'int' гарантированно будет иметь ширину не менее 16 бит); –

+0

Альтернативой прохождению вокруг размера является NULL-завершение массива, проверенное временем решение, но это работает только в том случае, если у вас есть массив указателей (что более часто встречается, чем массив массивов на C). –

10

In f array является указателем, в основном array является массивом.

+5

И как только у вас есть указатель, вы не можете определить количество элементов. –

0

Вы не можете указать количество элементов в массиве в C последовательно. Специально, если вы передаете массив вокруг указателей.

Обычно, если вы должны использовать размер массива в функции, передайте его в качестве параметра к нему.

+1

Число элементов в массиве всегда задается 'sizeof array/sizeof array [0]'. Пока массив представляет собой массив от честного до бога, это очень просто :) – pmg

1

Вы должны передать эти данные в качестве отдельного параметра функции. В C и C++, как только массив передается функции, массив вырождается в указатель. Указатели не имеют представления о том, сколько элементов находится в массиве, на который они указывают.

Обычный способ получить размер - объявить массив, а затем сразу получить количество элементов массива, разделив общий размер на размер одного элемента. Например:

struct my_struct my_struct_array[] = { 
{"data", 1, "this is data"}, 
{"more data", 2, "this is more data"}, 
{"yet more", 0, "and again more data"} 
}; 
const size_t my_struct_array_count = sizeof(my_struct_array)/sizeof(my_struct_array[0]); 
0

Когда вы используете sizeof в main, он вычисляет массив и дает размер фактического массива.

При использовании sizeof в f, вы прошли имя массива в качестве аргумента функции, поэтому она заглохла к указателю, так sizeof говорит вам о размере указателя.

Вообще говоря, если вы передаете массив функции, вам нужно либо написать функцию только для работы с одним конкретным размером массива, либо явно передать размер массива для работы с определенным вызовом.

1

В приведенном выше коде функция f() не имеет способа узнать, сколько элементов было в исходном массиве. Это особенность языка, и вокруг этого нет никакого способа. Вам придется пройти всю длину.

1

Как указано в C reference, вы не можете сделать это, если только последний элемент не уникален или вы передаете количество элементов массива функции.

1

Вы должны закончить массив специальным значением, а в вызываемой функции вы должны подсчитать до этого значения, то есть, как работает strlen(), оно подсчитывает значение NULL '\ 0'.

+0

Это, безусловно, одно решение, но оно не единственное. –

+0

вы отправляете функцию указатель (адрес в памяти), как он будет считаться, если он не знает, где он заканчивается. В C нет типа массива, как мы знаем на более высоких языках. Вы можете создать класс массива в C++, который также сохраняет свой размер (или использует все уже определенные) – bkilinc

0

Вы можете использовать формат для своего массива. Я использую строковые элементы, он должен работать для struct.

#define NULL "" 
#define SAME 0 

static char *check[] = { 
     "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", 
     "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", 
     "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", 
     "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", 
     "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", 
     "lzo", "cts", "zlib", NULL 
}; // 38 items, excluding NULL 

в основной()

char **algo = check; 
int numberOfAlgo = 0; 


while (SAME != strcmp(algo[numberOfAlgo], NULL)) { 
    printf("Algo: %s \n", algo[numberOfAlgo++]); 
} 

printf("There are %d algos in the check list. \n", numberOfAlgo); 

Вы должны получить вывод:

Algo: des 
    : 
    : 
Algo: zlib 

There are 38 algos in the check list. 

В качестве альтернативы, если вы не хотите использовать NULL, сделать это вместо:

numberOfAlgo = 0; 

while (*algo) { 
    printf("Algo: %s \n", *algo); 
    algo++;   // go to the next item 
    numberOfAlgo++; // count the item 
} 

printf("There are %d algos in the check list. \n", numberOfAlgo); 
0

В качестве примера для вашего решения:

Учитывая

struct contain { 
char* a;  // 
int allowed; // 

struct suit { 
    struct t { 
      char* option; 
      int count; 
    } t; 

    struct inner { 
      char* option; 
      int count; 
    } inner; 
} suit; 
}; 

// например. инициализируется

 struct contain structArrayToBeCheck[] = { 
    { 
     .a = "John", 
     .allowed = 1, 

     .suit = { 
      .t = { 
       .option = "ON", 
       .count = 7 
      }, 

      .inner = { 
       .option = "OFF", 
       .count = 7 
      } 
     } 
    }, 
    { 
     .a = "John", 
     .allowed = 1, 

     .suit = { 
      .t = { 
       .option = "ON", 
       .count = 7 
      }, 

      .inner = { 
       .option = "OFF", 
       .count = 7 
      } 
     } 
    }, 
    { 
     .a = "John", 
     .allowed = 1, 

     .suit = { 
      .t = { 
       .option = "ON", 
       .count = 7 
      }, 

      .inner = { 
       .option = "OFF", 
       .count = 7 
      } 
     } 
    }, 
    { 
     .a = "John", 
     .allowed = 1, 

     .suit = { 
      .t = { 
       .option = "ON", 
       .count = 7 
      }, 

      .inner = { 
       .option = "OFF", 
       .count = 7 
      } 
     } 
    } 

}; 

в основной()

printf("Number of Struct within struct array: %d \n", sizeof(structArrayToBeCheck)/sizeof(struct contain)); 

дает правильный ответ.

1

Обратите внимание, что в main() массив ссылается на фактический массив, и поэтому sizeof() дает требуемый ответ.

Но когда вы передаете его как параметр функции, вы фактически передаете адрес первого элемента массива, который хранится в переменной-указателе «array».
Итак, теперь sizeof() задает размер переменной указателя, поэтому он отличается от фактического ответа.

Возможное решение может быть

1.Declare массив глобально

2.Pass размер массива в качестве параметра функции Надеюсь, что это помогает!

Смежные вопросы