printf ptr: can the leading 0x be eliminated? - linux

The Linux printf renders %p arguments as hex digits with a leading 0x. Is there a way to make it not print the 0x? (Needs to work on both 32 and 64 bit.)

You can use the format specifier for uintptr_t from <inttypes.h>:
#include <inttypes.h>
[...]
printf("%"PRIxPTR"\n", (uintptr_t) p);
This works like %x for the uintptr_t type, which is an integer type capable of roundtrip conversion from/to any pointer type.

Use %llx, it will work on 64-bit for sure. Tried and tested.

Use %lx or %08lx. It works for both 32 and 64 bit linux gcc, because long int is always the same width as void *. Doesn't work for MSVC, because long int is always 32 bit in MSVC.
If you want it to work on all compilers, you can use %llx and cast your pointer to unsigned long long int, it's not efficient in 32 bit though.
If you want efficiency as well, define different macro for different cases.

Related

Writing number with a lot of digits into file using MPIR

I'm using MPIR/Ubuntu 14.04.
I have big integer that have a lot of digits, like 2^1920, and don't know how to write it into file *.txt
FILE *result;
result=fopen("Number.txt","a+");
gmp_fprintf(result,"%d",xyz);
fclose(result);
didn't work.
Are there some other options I can use?
The gmp_printf() function (thus subsequently gmp_fprintf() as well) requires special format specifier for mpz_t object (which I guess xyz is). You should use %Zd instead of plain %d, that does not work. To be pedantic it's undefined behavior to use inadequate f.s. in C.
If you don't need "full-featured" formatted output, then you might also take a look at mpz_out_str(), that allows to specify base (like 2 or 10):
size_t mpz_out_str (FILE *stream, int base, const mpz_t op)
Alternatively you might use mpz_out_raw() function that just "dumps" the whole number as it is stored in binary format:
size_t mpz_out_raw (FILE *stream, const mpz_t op)
Output op on stdio stream stream, in raw binary format. The integer is
written in a portable format, with 4 bytes of size information, and
that many bytes of limbs. Both the size and the limbs are written in
decreasing significance order (i.e., in big-endian).

Linux struct msghdr :: msg_iovlen type

No practical reason, just wondering.
Why in Linux in msghdr struct, they use size_t type for msg_iovlen field? I found it a bit confusing, as size_t usually means "how much bytes".
Btw, in FreeBSD they use u_int for that field, and int is in Posix standard.
See size_t:
size_t is the unsigned integer type of the result of the sizeof operator as well as the sizeof... operator and the alignof operator... size_t can store the maximum size of a theoretically possible object of any type (including array). On many platforms (an exception are systems with segmented addressing)

how to make vim handle 64bit int number?

in vim :h Number:
Number A 32 or 64 bit signed number.
the value of max 32/64bit number:
2^31=2147483648
2^63=9223372036854775808
Now if I call str2nr() in vim:
:echo str2nr('2147483648')
-> -2147483648
:echo str2nr('112147483648')
-> 478333952
or eval the expression directly:
echo 2147483648 + 7777
-> -2147482871
So the question is, vim doc tells number is 32 or 64 bit number. How to make vim handle the 64bit number? like 2147483648 + 7777 =2147491425
P.S above test was done on:
Archlinux 64bit
Vim 7.4.135 (from Arch 64bit repo)
According to this https://groups.google.com/forum/#!topic/vim_dev/2pXdRG7yW0Y. You can't.
Bram says that a number is an int and if your platform declares int as having 64 bits you will have a 64 bit int in vim. However int was chosen to be 32 bits (by your compiler), so you only get 32 bits for a number.
In :h limits I find the following.
Range of a Number variable: -2147483648 to 2147483647 (might be more on 64
bit systems)
The might be more is probably telling you that those limits might still be the same on a 64 bit platform. It is totally up to the compiler.
I think the only way you would be able to change this is if you were to go through all of the source code and change how numbers are represented internally or find a compiler that represents int as 64 bits. (I don't know of one off hand)
If you want to find out how many bits your compiler will represent an int as you can run the following code.
#include "limits.h"
#include "stdio.h"
int main() {
printf("sizeof int in bits %lu\n", sizeof(int) * CHAR_BIT);
}
On my 64 bit machine this prints (I suspect your machine will do the same)
sizeof int in bits 32

Question about file seeking position

My previous Question is about raw data reading and writing, but a new problem arised, it seems there is no ending....
The question is: the parameters of the functions like lseek() or fseek() are all 4 bytes. If i want to move a span over 4G, that is imposible. I know in Win32, there is a function SetPointer(...,Hign, Low,....), this pointers can generate 64 byte pointers, which is what i want.
But if i want to create an app in Linux or Unix (create a file or directly write
the raw drive sectors), How can I move to a pointer over 4G?
Thanx, Waiting for your replies...
The offset parameter of lseek is of type off_t. In 32-bit compilation environments, this type defaults to a 32-bit signed integer - however, if you compile with this macro defined before all system includes:
#define _FILE_OFFSET_BITS 64
...then off_t will be a 64-bit signed type.
For fseek, the fseeko function is identical except that it uses the off_t type for the offset, which allows the above solution to work with it too.
a 4 byte unsigned integer can represent a value up to 4294967295, which means if you want to move more than 4G, you need to use lseek64(). In addition, you can use fgetpos() and fsetpos() to change the position in the file.
On Windows, use _lseeki64(), on Linux, lseek64().
I recommend to use lseek64() on both systems by doing something like this:
#ifdef _WIN32
#include <io.h>
#define lseek64 _lseeki64
#else
#include <unistd.h>
#endif
That's all you need.

64 bit portability issues

All this originated from me poking at a compiler warning message (C4267) when attempting the following line:
const unsigned int nSize = m_vecSomeVec.size();
size() returns a size_t which although typedef'd to unsigned int, is not actually a unsigned int. This I believe have to do with 64 bit portability issues, however can someone explain it a bit better for me? ( I don't just want to disable 64bit warnings.)
It depends on the implementation. std::size_t for example has a minimal required size. But there is no upper limit. To avoid these kind of situations, always use the proper typedef:
const std::vector<T>::size_type nSize = m_vecSomeVec.size();
You will be always on the safe side then.
When compiling for a 64-bit platform, size_t will be a 64-bit type. Because of this, Visual Studio gives warnings about assigning size_ts to ints when 'Detect 64-bit Portability Issues' is enabled.
Visual C++ gets this information about size_t through the __w64 token, e.g. __w64 unsigned int.
Refer the below link for more on 64 bit porting issues..
http://www.viva64.com/en/a/0065/
If size_t is typedef:ed to unsigned int, then of course it is an unsigned int, on your particular platform. But it is abstracted so that you cannot depend on it always being an unsigned int, it might be larger on some other platform.
Probably it has not been made larger since it would cost too much to do so, and e.g. vectors with more than 2^32 items in them are not very common.
Depending on the compiler, int may be 32-bits in 64-bit land.

Resources