В строке используется нулевой терминатор, но в этой реализации все возможные значения потенциально допустимы.
Если все значения действительны, значение дозорного не может быть реализовано.Это так просто (вот почему EOF
является целочисленным значением, которое переполняет тип char
).
Функция не знает о размере массива, и я хотел бычтобы сохранить его таким образом ...
Предполагая, что NaN
является недопустимым значением, вы можете использовать макрос isnan()
для проверкизначение часового.
Однако, NaN
является допустимым значением ...
В любом случае мне нужно будет найти конец.
Единственный оставленный вариант - фактически передать длину массива вместе с массивом.
Если вы не можете добавить длину массива в качестве отдельного аргумента, вы можете (вероятно) сохранить длину массивав качестве первого члена - либо с использованием структуры (рекомендуется), либо с использованием типа punning (не пытайтесь сделать это дома, если вы не знаете, что делаете).
то есть
typedef struct float_array_s {
unsigned int len;
float f[];
};
static unsigned int float_array_len(float_array_s * arr) { return arr->len; }
static float float_array_index(float_array_s * arr, unsigned int index) { return arr->f[index]; }
На самом деле нет смысла использовать циклы вычислений, если вы можете просто передать длину действительной длины массива вместе с массивом.
Edit (type punning)
Я настоятельно рекомендую избегать такого подхода, так как длины типов могут привести к трудностям при обнаружении ошибок.Однако ...
Возможно сохранить длину массива в первом float
элементе, используя те же байты (память) для хранения целого числа.
Обратите внимание, что это можетсбой (или, что еще хуже, тихий сбой), если unsigned int
длиннее float
(что может быть, даже если они обычно имеют одинаковый размер в байтах).
т.е.
#include "math.h"
#include "stdint.h"
#include "stdio.h"
/* Returns the member at `index`. */
static float float_array_index_get(float *arr, unsigned int index) {
return arr[index + 1];
}
/* Sets the member at `index` to `val. */
static void float_array_index_set(float *arr, unsigned int index, float val) {
arr[index + 1] = val;
}
/* Returns the array's length. */
static unsigned int float_array_length_get(float *arr) {
if (sizeof(unsigned int) > sizeof(float)) {
fprintf(
stderr,
"ERROR: (%s:%d) type size overflow, code won't work on this system\n",
__FILE__, __LINE__);
}
union {
float f;
unsigned int i;
} pn;
pn.f = arr[0];
return pn.i;
}
/* Sets the array's length. */
static void float_array_length_set(float *arr, unsigned int len) {
if (sizeof(unsigned int) > sizeof(float)) {
fprintf(
stderr,
"ERROR: (%s:%d) type size overflow, code won't work on this system\n",
__FILE__, __LINE__);
}
union {
float f;
unsigned int i;
} pn;
pn.i = len;
arr[0] = pn.f;
}
/* Pushes a member to the array, increasing it's length. */
static void float_array_index_push(float *arr, float val) {
unsigned int len = float_array_length_get(arr);
float_array_index_set(arr, len, val);
float_array_length_set(arr, len + 1);
}
/* Pops a member from the array...
* ... returning nan if the member was nan or if the array is empty.
*/
static float float_array_index_pop(float *arr) {
unsigned int len = float_array_length_get(arr);
if (!len)
return nan("");
float_array_length_set(arr, len);
return float_array_index_get(arr, len);
}
PS
Я надеюсь, что вы будете придерживаться простого func(float * arr, size_t len)
, теперь, когда вы видите, сколько дополнительного кода вам нужно, просто чтобы избежать передачи длины массива.