igng igng - 15 days ago 4
C Question

Why can't you use scientific notation in kernel

I was trying to write a kernel (4.8.1) module, and if I use

if (hrtimer_cancel(&hr_timer) == 1) {
u64 remaining = ktime_to_ns(hrtimer_get_remaining(&hr_timer));
printk("(%llu ns; %llu us)\n", remaining,
(unsigned long long) (remaining/1e3));
}


it raises this error

error: SSE register return with SSE disabled
printk("\t\t(%llu ns; %llu us)\n",
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
remaining,
~~~~~~~~~~
(unsigned long long) (remaining/1e3));
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


while if I use

if (hrtimer_cancel(&hr_timer) == 1) {
u64 remaining = ktime_to_ns(hrtimer_get_remaining(&hr_timer));
printk("(%llu ns; %llu us)\n", remaining,
(unsigned long long) (remaining/1000));
}


it works without a problem.

So why can't you use scientific notation in the kernel? I mean, I think is much easier and more readable to use
1e3; 1e6; 1e9
instead of
1000; 1000000; 1000000000
.

Is just a matter of portability/robustness?

Or something like (in this case)


You need ns? Use
ktime_to_ns


You need us? Use
ktime_to_us


You need ms? Use
ktime_to_ms



P.S. I tried with a simple .c program and it works without problems

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

void error_handler(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}

unsigned long parse_num(const char *number)
{
unsigned long v;
char *p;
errno = 0;

v = strtoul(number, &p, 10);

if (errno != 0 || *p != '\0')
error_handler("parse_num | strtoul");

return v;
}

int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s number_greater_than_1000\n", argv[0]);
return EXIT_FAILURE;
}

unsigned long number = parse_num(argv[1]);

if (number < 1e3 || number > 1e6)
{
fprintf(stderr, "Need to be a number in range (%lu, %lu)\n", (unsigned long) 1e3, (unsigned long) 1e6);
return EXIT_FAILURE;
}

printf("Original: %lu\tScaled: %lu\n", number, (unsigned long) (number/1e3));

return EXIT_SUCCESS;
}

Answer

1e3 is not equivalent to 1000.

1000 is an integer constant of type int. 1e3 is a floating-point constant of type double, equivalent to 1000.0. That makes remaining/1e3 a floating-point division, which is what the compiler is complaining about.

See also SSE register return with SSE disabled.

Comments