Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Any idea why they would use long long rather than int64_t?


Imagine you just called time(2) and got a time_t value. Something like:

    time_t asdf = time();
And now you want to use printf to print that value to the screen. You can cast to 'long long', which is guaranteed to be at at least 64 bits wide, and ensure no loss of precision occurs:

    printf("%lld", (long long)asdf);
That will work whether time_t is 32 bit or 64 bit.


If they just added a macro to inttypes.h, you could use that for the format specifier. If you want to print a uint32_t, you just use PRIu32.


> you could use that for the format specifier.

And end up with even more horrible and less readable format strings.


So we should use unportable format strings or cast all the values to long long? Is that better?

I personally find inttypes format strings readable.


How do you think the int64_t type is constructed? Few problems are solved by endless stacks of typedefs.


int64_t is a much nicer type than "long long".

"int" makes some sense. Word-size of the machine.

"short", "long", "long long" are all non-sensical. You use them when you want to trade size and range. When you want to make that trade-off, you care what their sizes are.

Instead of lower/upper bounds on their sizes, which aren't very useful, they should just have specific sizes. At which point, you might as well use uint32_t, and uint64_t in place of long and long long.

Prefer the sized int types over the "long"/"long long" ones when you can, for saner coding.

Use uintptr_t and such when you need a ptr-sized int, rather than a specific size.


You need to realize that the size of most types in C have been perverted by history. When possible, it's best to use the few types that are unambiguous in all of C89, LLP64 and LP64.

> int64_t is a much nicer type than "long long".

Yes, except that "long long" has been part of the standard for longer. in64_t was part of C99 but is tricky to include in software up to the mid 2000's due to slow adoption of the standard.

You can use "long long" without headers in most C compilers from the last 20 years. int64_t when present is usually just a typedef to "long long". Keep it simple.

> "int" makes some sense. Word-size of the machine.

Except that it isn't. That was its original intent but for historical reasons, it is a 32 bit integer in almost all cases now, regardless of machine word size.


I fail to see why it's more reasonable to prefer "long long" to "int64_t" just because the former existed for longer. It's not year 2000 today and C99's not a hot new thing not many compilers support. Or OpenBSD do have some policy that their kernel must be able to build with any C89-compliant compiler?


It's not the kernel that's the issue, we're talking about basic, cross-platform userland utilities like "ping" here. Some of those do have a policy that they have to be able to build on Irix 5.8 or whatever.


Is there anything that forbids those utilities from using system-provided headers and time_t? I think they'll build fine on any POSIX.1-compliant system then.

Unless they're doing something really weird with time_t values, I don't think there's any reason they should know whenever it's long long or int64_t or whatever under the hood.


printf("%lld", (int64_t) t); wouldn't build on a system that doesn't have int64_t, so one needs to use long long.


Why cast to `int64_t` here? Just because `time_t` could be `int64_t` under the hood doesn't mean it must be casted to this exact type for string formatting/presentation purposes.

And I thought `%lld` actually means `long long`... So, http://ideone.com/SJJFPs seems like a proper approach to me. That said, if compiler supports %lld (an %I64d or alike might be required for older compilers), so a better cross-compiler approach would be in lines of `printf("test: " TIME_FMT "\n", (TIME_FMT_CAST)t)`. Or, ahem, maybe, `print_time(t)`.


Assuming we don't want to maintain a set of per-platform macros, we need to use an existing, standard format specifier. There isn't one that takes a time_t. So we have to cast time_t to a type big enough to contain it, use the format specifier for that type, and we want this to be as cross-platform as possible, i.e. we use the oldest, most widely-supported type which can definitely hold at least 64 bits and has a standard printf specifier available. i.e. "long long", exactly as in your example code.

So that's why we prefer "long long" rather than "int64_t", which I thought was your original question.


Oh. I thought the discussion was not about what type to cast when using printf (I agree, only `%lld`/`long long` fits perfectly), but what type to use for `time_t` internally. Sorry if I misunderstood and missed the point.


Microsoft's C compiler doesn't have C99 support.


Microsoft don't make a C compiler.


once again, how do the headers conjure up the int64_t type? it's not a keyword.


Here is how stdint.h on Linux conjures up the int64_t type.

  #if __WORDSIZE == 64
  typedef long int int64_t;
  #else
  typedef long long int int64_t;
  #endif


Wait. You just typed long long. You're not allowed to do that.


You're whooshing.

You don't want to use "long long" because that's not necessarily 64-bits. You want to use int64_t which guarantees it is 64-bits.

And then, the correct format specifier for that is PRIi64, and not "%ld" or "%lld" which will break in different platforms.


Please don't be disingenuous. We both know that using #defines, you can get a type which is exactly 64 bits on any modern architecture. The fact that long long and long int are a builtin types and int64_t is implemented in terms of them, rather than the other way around, is just an implementation detail.


int64_t is a userspace libc typedef. long long is ICO C (C99) and guaranteed to be 64 bits or more.



Yes... as a typedef in <stdint.h>. In other words, "a userspace libc typedef" as the previous post said...


sirclueless implied that int64_t was not C99, which is wrong.


I think if you re-read what was written, what you think was implied was not.


<time.h> is userspace. It's at least theoretically possible for long long to be more than 64 bits. Why use long long (potentially, say, 128 bits) rather than int64_t for time_t?

And why wouldn't int64_t be available in kernel space?


long long can be printed in printf with the "%lld" flag.


So stdint.h not available to kernel programmers. Thanks.


I always found this special-casing of headers for kernel vs user unnecessary and complicating. In the many embedded runtimes I maintain, I've moved towards using standard POSIX-y and C(++) standard headers everywhere. I know kernel folks love to believe that their world is special so all the usual C library stuff needs to be done differently, but it's not needed.

It's so much easier to port code between the two worlds when you don't have to litter the #include prelude of every C file with conditionals.


stdint.h may not be available, but int64_t is; it's defined in include/linux/types.h.


The OpenBSD kernel probably doesn't use Linux headers.


A few times I got flamed on this site for complaining that the average HNer can't have reasonable discussions about C. I think the comment that the OpenBSD team should just #include <linux/types.h> pretty well shows that I was right. :-)


Just a silly mistake on my part.


Really going out on a limb there aren't you? ;-)


Yeah, good point.

I'm not familiar with the OpenBSD kernel. Is there any good reason (for OpenBSD or any other kernel) why <stdint.h> shouldn't be available -- or at least why int64_t shouldn't be available in some header?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: