Это возможно?[указатель на массив символов C] - PullRequest
2 голосов
/ 04 мая 2011

Возможно ли это?

size_t calculate(char *s)
{
    // I would like to return 64
}

int main()
{
    char s[64];

    printf("%d", calculate(s));

    return 0;
}

Я хочу написать функцию, которая вычисляет размер массива char, объявленного в main().

Ответы [ 6 ]

6 голосов
/ 04 мая 2011

Ваша функция calculate(), учитывая только аргумент указателя s, не может рассчитать размер массива.Размер массива не закодирован в указателе или недоступен из указателя.Если он предназначен для использования строки с нулевым символом в конце в качестве аргумента, он может определить, какова длина этой строки;это то, что strlen() делает, конечно.Но если он хочет знать, сколько информации он может безопасно скопировать в массив, ему нужно сообщить, насколько большой массив, или предположить, что места достаточно.

Как указали другие,оператор sizeof() может использоваться в функции, где видимо определение массива, чтобы получить размер массива.Но в функции, которая не может видеть определение массива, вы не можете с пользой применять оператор sizeof().Если бы массив представлял собой глобальную переменную, чье определение (а не объявление) находилось в области видимости (видимой), где было написано calculate(), а не, следовательно, параметр функции - тогда calculate() мог бы указывать размер.

Вот почему многие, многие функции C принимают указатель и длину.Отсутствие информации объясняет, почему C в некоторой степени склонен к тому, что люди злоупотребляют ею и выдают ошибки «переполнения буфера», когда код пытается поместить галлон информации в пинту.

5 голосов
/ 04 мая 2011

Для статически объявленных char[] вы можете использовать оператор sizeof, который в этом случае вернет 64.

printf("%d", sizeof(s));

При динамически объявленном char* невозможно получить размер выделенной памяти.

Динамические массивы получены через malloc и друзей. Все остальные статически объявлены , и вы можете использовать sizeof для них, если вы используете его в той же области, в которой был объявлен массив (например, та же функция, в вашем случае).

3 голосов
/ 04 мая 2011

Да, это возможно, если s имеет определенный символ в конце своего массива. Например, у вас может быть s[63] = 125, и, зная, что любой другой символ от 0 до 62 не будет 125, вы можете выполнять цикл for, пока не найдете 125 и не вернете размер массива.

В противном случае это невозможно, поскольку s в параметре функции является просто указателем на ваш массив, поэтому sizeof(s) внутри calculate будет возвращать только размер указателя вашей машины, а не 64, как кто-то мог ожидать.

1 голос
/ 04 мая 2011

Нет.char *x или char x[] просто создает указатель на ячейку памяти.Указатель не содержит никакой информации о размере области памяти.

Однако char *x = "Hello" занимает 6 байтов (включая завершающий ноль), а strlen(x) вернет 5. Это зависит от нуляchar в конце строки, strlen до сих пор ничего не знает о нижележащем буфере.Так что strlen("Hello\000There") все равно будет 5.

1 голос
/ 04 мая 2011

К сожалению, по одному значению указателя невозможно определить, сколько элементов находится в соответствующем массиве.Вам либо нужно какое-то значение часового в массиве (например, терминатор 0, используемый для строк), либо вам нужно отслеживать его отдельно.

То, что вы можете сделать, это получитьколичество байтов или элементов в массиве с использованием оператора sizeof:

char arr[64];

size_t size = sizeof arr;                 // # of bytes in arr
size_t count = sizeof arr / sizeof *arr;  // # of elements in arr

Однако это работает, только если arr является типом массива;если вы попытаетесь сделать это в своей функции

 size_t calculate(char *s)
 {
   return sizeof s;
 }

, она вернет размер в байтах значения указателя , а не соответствующего объекта массива.

0 голосов
/ 04 мая 2011

Обычно это делается с помощью макроса на C, например:

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))

Является ли это хорошей идеей, это совершенно другой вопрос.

...