I know this is a strange questions but I was wondering if it was possible to make a 32 bit pointer in 64 bit compile on Solaris using g++. The final object would need to be 64 bit however one of my pointers offsets is becomming larger on Solaris then it is in windows if I do use 64 bit to compile. This is causing a big problem. I was wondering if it was possible to make a 32bit pointer within my 64 bit compiled object.
Pointer size is a property of your target architecture, so you cannot mix and match 32- and 64-bit pointers. I would strongly suggest re-thinking your design (which smells like usual mistake of casting pointers to integers and back.) You can theoretically work with "limited-reach" offsets, but again please ask yourself why, and what would be a better way of doing it.
You can't change regular pointers, the size of a pointer is sizeof(void *). And if you could, what would you do with an 32bit pointer on an 64bit system?
Do you mean pointers in C or do you maybe mean pointers to a file offset?
If you have pointer type there, then you shouldn't make it 32-bit in 64-bit program. If it is just some offset that not related to memory model, then you could use different type with stable size across platforms, something like uint32_t.
It does not make sense to "need" a 32 bit pointer on a 64 bit machine. I also dont understand this line:
The final object would need to be 64 bit however
I would take a closer look and try to fix the bug on your end. If you post some example code we may be able to help more.
Related
So I got into fundamental data types and I was left with one thing that I'm confused about - if I was going to build a 64-bit program, would I have to use data types specifically made for 64-bit architecture? I did some research and turns out that 64-bit optimized version of integer would be long long int. Or it doesn't matter and I can do fine with those data types I've learned already?
You may find that some types have different sizes than you're used to. For example, a 32-bit Solaris environment has 4-byte long, but a 64-bit Solaris environment has 8-byte long. Meanwhile, this isn't the case in Visual Studio, which retained 4-byte long.
This is why, if you are relying on extreme range for integer types and need to be completely cross-platform, you should favour more specific types like uint64_t. Otherwise, though, you shouldn't need to worry about this.
Similarly, you'll find that pointer types are no longer 32-bit, but 64-bit, so that they can hold all possible addresses on your shiny new 64-bit system. This shouldn't affect you unless you've done something wrong.
Don't worry about "optimisation" unless you have a serious need to eke out every last nanosecond and you can do better than your compiler, which is unlikely. Just write a descriptive, expressive program that signals your intent, as you always have.
For reference, though, you can look up your platform, environment and compiler, to find out what size the fundamental types have there. It can differ across all three.
I'm trying to convert a byte array to and from a Boost number with the cpp_int backend. What is a portable way to do this?
The platforms I'm concerned about are all little endian, but can be 32 or 64 bit and can be compiled with different compilers. Some of the ways I've seen to do this break depending on compiler versions and such, and that's what I want to avoid.
The only real difference between x86 and x64 is the size of pointers. So unless it relies on the size of pointers somehow, there shouldn't be much of a problem. Especially since a byte is always 8bits and you already ruled out endiannes problems.
I would like to use SWIG on Windows for building 64 bit applications. I have a class that has a pointer in it to a buffer, and because I would like to interface with a .NET class, the pointer is declared as intptr_t.
The problem is that the standard SWIG stdint.i assumes that intptr_t is either int (on 32 bit environment) or long (on 64 bit environment). While this is true on Unix, it is false on Windows. Does anyone have either similar experience or any ideas how to create a workaround for this?
I already set up the typemaps needed for the intptr_t => IntPtr conversion and it is working fine in 32 bit environment, but it truncates the pointer in 64 bit environment.
Ok, I will answer my own question. It seems that this is a bug in SWIG on Windows, that it treats long as int64 on 64-bit Windows, while in reality it is an int32. See more about this topic here:
What is the bit size of long on 64-bit Windows?
The other problem with SWIG is that it differentiates 32 and 64 bit code, but the reason I used intptr_t was to avoid bitness issues, as by definition it gives an integer large enough to hold a pointer.
So what I did at the end was to write a script that I run after generating the wrapper to fix the type signatures from int to intptr_t. While this is not elegant, I already have to do this for other reasons for my Python and PHP wrappers.
Here is the following issue:
If I am developing on a 32 bit machine and want my code to be ported to a 64 bit machine here is the senario.
My function internally use a lot of std strings. Now if I want to provide APIs can I ask them to send char * which I can then use internally? Or ask them to send me a __int64 which I convert to a string?
Another reason to use char * in my API was that at least in one type of implementation of unix (a different version of the tool) it picks up data from stdin via argv which is a char *.
In the Windows version I am not sure what to do. I could just ask for __int64 and then convert it into a string...and make it work that way or just use char * as well?
If you're providing a C++ implementation, then your public interface should just use std::string.
If however for compatibility reasons (which it sounds like you may have) you need to provide a C-style interface, then using char* is precisely the way to do it. In your 32-bit library it will be a 32 bit pointer, and in the 64 bit version of the library it will be 64 bits. This will then agree with the client users' expectations regarding the API. You should absolutely convert to a std::string inside your library at the earliest possible point however.
You seem somewhat confused. If the code you are writing is used only within the target machine, recompile will take care of most of the problems. Just don't rely on specific memory layout and you are fine. Using strings (as opposed to wstrings) probably means that the character encoding is UTF-8 (if not, reconsider) and thus limited form of data exhance (e.g. files) between platforms is also fine.
In this case, your interface decision comes to selecting between (const) std::string(&), and (const) char*, integer_type (don't rely on null terminator, please). Deciding factor being whether or not you anticipate need to support other compilers or programming languages.
Now, if you intent to make the interface callable from other machines (i.e. network interface), you have much tougher job. In that case, specify size of everything explicitly.
char is always one byte in size, both on 32-bit and 64-bit systems. However, using the std library is not the worst choice. ;) std should cope with different platforms as it is platform independent for the "most" part...
Converting to/from char* doesn't really help if you can't represent the number on your architecture.
If you are converting a 64bit integer from its decimal (or hexadecimal) textual representation into a value, you still need 64bits to store it.
You would do well to convert to string at the earliest opportunity, it is the recommended/standard for C++, and will help do away with all your char* problems.
There is a few scenarios you can follow to write portable code, see these questions:
What's the funniest user request you've ever had?
How to do portable 64 bit arithmetic, without compiler warnings
You would have problems achieving binary portability between different architectures, C++ provides for source-level portability.
i'm about to port very large scale application to 64 Bits,
i've noticed in that in the web there some articles which shows
many pitfalls of this porting ,
i wondered if there is any tool which can assist in porting to 64 bit , meaning
finding the places in code that needs to be changed.... maybe the gcc with warnnings enabled... is it good enough ? is there anything better ?
EDIT: Guys i am searching for a tool if any that might be a complete to the compiler,
i know GCC can asist , but i doubt it will find all un portable problems that
will be discovered in run-time....maybe static code analysis tool that emphasize
porting to 64 bits ?
thanks
Here's a guide. Another one
Size of some data types are different in 32-bit and 64-bit OS, so check for place where the code is assuming the size of data types. eg If you were casting a pointer to an int, that won't work in 64bit. This should fix most of the issues.
If your app uses third-party libraries, make sure those work in 64-bit too.
A good tool is called grep ;-) do
grep -nH -e '\<int\>\|\<short\>\|\<long\>' *
and replace all bare uses of these basic integer types by the proper one:
array indices should be size_t
pointer casts should be uintptr_t
pointer differences should be
prtdiff_t
types with an assumption of width N
should be uintN_t
and so on, I probably forgot some. Then gcc with all warnings on will tell you. You could also use clang as a compiler it gives even more diagnostics.
First off, why would there be 'porting'?
Consider that most distros have merrily provided 32 and 64 bit variants for well over a decade. So unless you programmed in truly unportable manner (and you almost have to try) you should be fine.
What about compiling the project in 64 bits OS? gcc compiler looks like such tool :)
Here is a link to an Oracle webpage that talks about issues commonly encountered porting a 32bit application to 64bit:
http://www.oracle.com/technetwork/server-storage/solaris/ilp32tolp64issues-137107.html
One section talks how to use lint to detect some common errors. Here is a copy of that section:
Use the lint Utility to Detect Problems with 64-bit long and Pointer Types
Use lint to check code that is written for both the 32-bit and the 64-bit compilation environment. Specify the -errchk=longptr64 option to generate LP64 warnings. Also use the -errchk=longptr64 flag which checks portability to an environment for which the size of long integers and pointers is 64 bits and the size of plain integers is 32 bits. The -errchk=longptr64 flag checks assignments of pointer expressions and long integer expressions to plain integers, even when explicit casts are used.
Use the -errchk=longptr64,signext option to find code where the normal ISO C value-preserving rules allow the extension of the sign of a signed-integral value in an expression of unsigned-integral type. Use the -m64 option of lint when you want to check code that you intend to run in the Solaris 64-bit SPARC or x86 64-bit environment.
When lint generates warnings, it prints the line number of the offending code, a message that describes the problem, and whether or not a pointer is involved. The warning message also indicates the sizes of the involved data types. When you know a pointer is involved and you know the size of the data types, you can find specific 64-bit problems and avoid the pre-existing problems between 32-bit and smaller types.
You can suppress the warning for a given line of code by placing a comment of the form "NOTE(LINTED())" on the previous line. This is useful when you want lint to ignore certain lines of code such as casts and assignments. Exercise extreme care when you use the "NOTE(LINTED())" comment because it can mask real problems. When you use NOTE, also include #include. Refer to the lint man page for more information.