У меня есть функция, которая преобразует строку без знака int в свой неподписанный int-экземпляр.указатель void и разный размер памяти
Я хочу, чтобы иметь возможность передавать беззнаковый тип ЛЮБОГО размера в качестве контейнера и указать ограничение на то, насколько велика ценность, которую он должен удерживать. Прототип функции заключается в следующем:
str_to_uint(void *tar, const char *str, const uint64_t lim)
uint64_t *tar
то, где целое число без знака будет сохранено, *str
это строка числа и uint64_t lim
является пределом размеру *tar
будет в состоянии держать.
с sizeof(tar)
является переменной, безопасно ли отличать *tar
в uint64_t *
, а затем содержать преобразованную переменную в этом? Я знаю, что он всегда будет меньше фактического типа, так как я проверяю его с помощью переменной lim
.
такое возможно?
в основном это свелось бы к этому
- Я имею переменную без знака типа, где
sizeof(variable)
равно 1, 2, 3 или 4. - я передать переменную в функцию посредством
(void *)&variable
. - В этой функции я передал ее
uint64_t *
и записал в нее обнаруженную переменную. Я убеждаюсь, что обнаруженная переменная может быть записана в переменную, если она меньше или равнаlim
это разрешено?
код:
#include <stdio.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
static int str_to_uint(uint64_t *tar, const char *str, const uint64_t lim) {
char *eptr = NULL;
unsigned long long int temp = 0;
if (str == NULL) {
printf("str is a NULL pointer\n");
return -1;
}
temp = strtoull(str, &eptr, 10);
if (temp == 0 && eptr == str) {
printf("strtoull() conv err, %s\n", str);
return -1;
} else if (temp > lim) {
printf("strtoull() value to big to contain specified limit, %s\n", str);
return -1;
} else {
*tar = temp;
}
return 0;
}
int main() {
int ret;
uint8_t a;
uint16_t b;
uint32_t c;
uint64_t d;
ret = str_to_uint((void *)&a, "22", UINT8_MAX);
if (ret != 0) {
exit(1);
}
ret = str_to_uint((void *)&b, "22", UINT16_MAX);
if (ret != 0) {
exit(1);
}
ret = str_to_uint((void *)&c, "22", UINT32_MAX);
if (ret != 0) {
exit(1);
}
ret = str_to_uint((void *)&d, "22", UINT64_MAX);
if (ret != 0) {
exit(1);
}
printf("a = %"PRIu8"\nb = %"PRIu16"\nc = %"PRIu32"\nd = %"PRIu64"\n", a, b, c, d);
exit(0);
}
Это не будет вести себя так, как вы хотите, на маленькой конечной машине. –
«безопасно ли выставлять * tar на uint64_t *, а затем содержать преобразованную переменную?» Нет, это не так. «tar» не гарантируется, что он правильно выровнен и вызовет неуравновешенную проблему с доступом. Если вы хотите получить значение, используйте ['intprt_t' и' uintptr_t'] (http://en.cppreference.com/w/c/types/integer), в противном случае указатели объектов могут быть только безопасно преобразованы 'void *' –