Is there any disadvantage of converting size_t to long? Because, I am writing an program that maintains linked_list in a file. So I traverse to another node based on size_t and I also keep track of total number of lists as size_t. Hence, obviously there is going to be some conversion or addition of long and size_t. Is there any disadvantage of this? If there is then I will make everything as long instead of size_t, even the sizes. Please advise.

- 6,958
- 2
- 41
- 59

- 1,824
- 4
- 29
- 46
-
4Converting `size_t` to `long` is a problem if you have a `size_t` value that does not fit in `long`. Do you have such a value? Can you have such a value? – Apr 08 '12 at 18:17
-
Hmmmm, Not at the moment, but I might have, if I decide to increase the size of linked List. I am thinking of keeping the count as long itself. Because, the variable that's of type size_t will just keep the count, I guess int or long will do the job, what do you think??? – howtechstuffworks Apr 08 '12 at 18:21
-
Actually, one more situation will be, I am getting the value of ofstream::tellp(), which will return a location and I will add the sizeof(long) to traverse to another location is this fine? – howtechstuffworks Apr 08 '12 at 18:28
-
There's should be no problem if you add size_t with size_t. If you get into adding long with size_t, you've probably choosen the wrong data type to work with. For sizes, use size_t. – m0skit0 Apr 08 '12 at 18:30
-
yeah, size_t is what I am using to store.. – howtechstuffworks Apr 08 '12 at 18:31
-
Concrete example: on a run-of-the mill 32 bit system, the maximum value of a size_t is over twice as large as the maximum value of a long. Tell me, where does the long actually come in? – Mr Lister Apr 08 '12 at 18:52
3 Answers
The "long" type, unfortunately, doesn't have a good theoretical basis. Originally it was introduced on 32 bit unix ports to differentiate it from the 16 bit "int" assumed by the existing PDP11 software. Then later "int" was changed to 32 bits on those platforms (and "short" was introduced) and "long" and "int" became synonyms, which they were for a very long time.
Now, on 64 bit unix-like platforms (Linux, the BSDs, OS X, iOS and whatever proprietary unixes people might still care about) "long" is a 64 bit quantity. But, sadly, not on windows: there was too much legacy "code" in the existing headers that made the sizeof(int)==sizeof(long) assumption, so they went with an abomination called "LLP64" and left long as 32 bits. Sigh.
But "size_t" isn't like that. It has always meant precisely one thing: it's the unsigned type that stores the native pointer size in the address space. If you have an unsigned (! -- use ssize_t or ptrdiff_t if you need signed arithmetic) pointer that needs an integer representation (i.e. you need to store the memory size of an object), this is what you use.

- 11,699
- 1
- 34
- 31
-
Interesting One. I often hear legacy as the reason, when there are things like "its not a bug, but a feature" kinda problems. – howtechstuffworks Apr 08 '12 at 19:00
Is there any disadvantage of converting size_t to long?
Theoretically long can be smaller than size_t. Also, long is signed. size_t is unsigned. So if you start using them both in same expression, compiler like g++ will complain about it. A lot. Theoretically it might lead to unexpected errors due to signed-to-unsigned assignments.
obviously there is going to be some conversion or addition of long
I don't see why there's supposed to be some conversion or addition to long. You can keep using size_t for all arithmetical operations. You can typedef it as "ListIndex" or whatever and keep using it throughout the code. If you mix types (long and size_t), g++/mignw will nag you to death about it.
Alternatively, you could select specific type which has guaranteed size. Newer compilers have cstdint header which includes types like uint64_t (it is extremely unlikely that you encounter file larger than 2^64, for example). If your compiler doesn't have the header, it should be available in boost.

- 26,089
- 6
- 66
- 115
It's not a problem now, but it may be in the future depending on where you'll port your app. That's because size_t is defined to be large enough to store offsets of pointers, so if you have a 64-bit pointer, size_t will be 64 bits too. Now, long may or may not be 64 bits, because the size rules for fundamental types in C/C++ give room to some variations.
But if you're to write these values to a file, you have to choose a specific size anyway, so there's no option other than convert to long (or long long, if needed). Better yet, use one of the new size-specific types like int32_t.
My advice: somewhere in the header of your file, store the sizeof for the type you converted the size_t to. By doing that, if in the future you decide to use a larger one, you can still support the old size. And for the current version of the program, you can check if the size is supported or not, and issue an error if not.

- 15,819
- 5
- 38
- 51
-
You are right, the scenario in my program will be I am trying to maintain a linked list in the file. So I need to note down the fill_offset, for example return value of tellp(),tellg() into somewhere,that is 'long' here. Then, if I need to traverse, then I will have another variable size_t next_offset; where next_offset is computed to reach the next record. SO I will do, (tellp() + next_offset); Here next_offset is computed as(sizeof(int) +sizeof(long) + sizeof(the_rest_of_the_values_in_the_node) and then store it in a file. Is there a better way to do it. PS:I shouldn't use Boost/STL – howtechstuffworks Apr 08 '12 at 18:56
-
http://stackoverflow.com/questions/10065323/how-to-collect-and-store-tellp-tellg-return-types connected question – howtechstuffworks Apr 08 '12 at 19:01
-
2One suggestion I'd give you is to put all that logic you mentioned in a template class, whose parameter (by convention, T) is the type to be used. Al the arithmetic to convert record numbers to offsets should use sizeof(T) inside that class, and all the variable declarations should use T. This way, you'll have the flexibility to use any type without having to change the code. Given that flexibility, you can start supporting 32-bit values (uint32_t) and saving the size in the file header. In the future, if you want to support 64 bits, its just a matter of instantiating the template again. – Fabio Ceconello Apr 08 '12 at 19:06
-
^ wow, I could never think like that... Its just an programming assignment, I should have mentioned earlier.... But thats a piece of advice I would take for my future developments. Thanks.... – howtechstuffworks Apr 08 '12 at 19:11