Simple question, need an answer quickly please!
Take this situation on a 32-bit machine:
Unsigned long long n = 1;
n -= 2;
I know on a 64-bit machine, this would wrap around to the highest unsigned long long. But what would happen on a 32-bit machine, since the long long is stored as two separate words?
Thank you!
If the implementation is conforming, then the same: it will correctly wrap around. I assume this is C; The C standard requires this behavior independently from the implementation details.
A 64 bit integer datatype behaves the same on all architectures, including 32 bit. If not, programming would be quite hard, wouldn't it?
Related
I would like to have a set of dummy addresses as flag values that can never be a valid pointer.
For example, if I knew that pointers 0xffff0000 through 0xffffffff where always invalid I could do something like this in C
enum {
SIZE_TOO_SMALL = 0xffff0001,
SIZE_TOO_LARGE = 0xffff0002,
SIZE_EVEN = 0xffff0003,
};
char* allocate_odd_arry(int size) {
if (size % 2 == 0)
return SIZE_EVEN;
if (size < 100)
return SIZE_TOO_SMALL;
if (size > 1000)
return SIZE_TOO_LARGE;
return malloc(size);
}
A silly example, but potentially powerful since it removes the need of sending an extra flag variable. One way I could do this is to allocate a few bytes myself and use those addresses as flags, but that comes with a small memory cost for each unique flag I use.
I don't expect a portable solution, but is there any guarantee on windows, linux, macos, that the addressable space will not include certain values?
For windows I have found this article which says that on 32 bits systems the virtual address space is 0x00000000 to 0x7fffffff, and for 64 bit systems it is 0x0000000000000000 to 0x00007fffffffffff. I am not sure if other addresses have any reserved meaning, but they ought to be safe for this use case.
Looking at Linux the answer seems a bit more complicated because (like everything else in linux) it is configurable. This answer on unix SE shows how memory is divided between the kernel and user space. 0000_8000_0000_0000 to ffff_7fff_ffff_ffff is listed as non canonical, which I think means it should never be used. Though really the kernel space (ffff_8000_0000_0000 to ffff_ffff_ffff_ffff) seems like it ought to be safe to use as well, but I'm less sure if there could never be a system function that returns such a pointer.
On Mac OS I've found this article which puts the virtual memory range as
0 to 0x0007_FFFF_FFFF_F000 (64 bit) or 0 to 0xFFFF_F000 (32 bit), so outside of these ranges would be fine.
Seems there is a little bit of overlap between all of the unused regions, so if you wanted to target all three platforms with the same address it would be possible. I'm still not 100% confident that these addresses are really truly safe to use on the respective OS, so I'm still holding out for anyone more knowledgeable to chime in.
I saw that when using parse for example, you can do this: parse(Int, "123") (Int exists), but I can't do parse(Float, "12.3") (Float doesn't exist).
Why doesn't Float exist as well then? What is the difference between Int and for example Int64 or some other number after Int anyways (I know it has to do with the size, but how can you know when to use which)?
The reason for this is that machines are either 32 bit or 64 bit. This is the size of pointers on these machines, and since pointers are just integers in hardware, it is also the "natural" integer size. Floating point arithmetic is different. (Almost) all computers have both FLoat32 and Float64, and the choice needs to be made based on application (how much range and accuracy you need). That said, you could always define const Float = Float64 and then just use Float.
I am doing some image processing on an embedded system (BeagleBone Black) using OpenCV and need to write some code to take advantage of NEON optimization. Specifically, I would like to write a NEON optimized thresholding function and then a NEON optimized erosion/dilation function.
This is my first time writing NEON code and I don't have experience writing assmbly code, so I have been looking at examples and resources for the C-style NEON intrinsics. I believe that I can put some working code together, but am not sure how I should structure the vectors. According to page 2 of the "ARM NEON support in the ARM compiler" white paper:
"These registers can hold "vectors" of items which are 8, 16, 32 or 64
bits. The traditional advice when optimizing or porting algorithms
written in C/C++ is to use the natural type of the machine for data
handling (in the case of ARM 32 bits). The unwanted bits can then be
discarded by casting and/or shifting before storing to memory."
What exactly does this mean? Do I need to to restrict my NEON code to using uint32x4_t vectors rather than uint8x16_t? How would I go about loading the registers? Or does this mean than I need to take some special steps when using vst1q_u8 to store the data to memory?
I did find this example, which is untested but uses the uint8x16_t type. Does it adhere to the "32-bit" advice given above?
I would really appreciate it if someone could please elaborate on the above quotation and maybe provide a very simple working example.
The next sentence from the document you linked gives your answer.
The ability of NEON to specify the data width in the instruction and
hence use the whole register width for useful information means
keeping the natural type for the algorithm is both possible and
preferable.
Note, the document is distinguishing between the natural type of the machine (32-bit) and the natural type of the algorithm (in your case uint8_t).
The document is saying that in the past you would have written your code in such a way that it used 32-bit integers so that it could use the efficient machine instructions suited for 32-bit operations.
With Neon, this is not necessary. It is more useful to use the data type you actually want to use, as Neon can efficiently operate on those data types.
It will depend on your algorithm as to the optimal choice of register width (uint8x8_t or uint8x16_t).
To give a simple example of using the Neon intrinsics to add two sets of uint8_t:
#include <arm_neon.h>
void
foo (uint8_t a, uint8_t *b, uint8_t *c)
{
uint8x16_t t1 = vld1q_u8 (a);
uint8x16_t t2 = vld1q_u8 (b);
uint8x16_t t3 = vaddq_u8 (a, b);
vst1q_u8 (c, t3);
}
I'm a fairly new programmer and I was wondering if someone could give me a practical explanation/example on the differences and uses between working with signed, unsigned and 32 bit vs 64 bit?
i.e. I read an article about how Twitter had developers switch to 64 bit last year but I wasn't sure the reasoning and the specific nature to it.
Thank you!
For n bits, you can have 2^n different numbers represented by those bits. So 32 bit unsigned numbers go from 0 to 4,294,967,295 (2^32-1, the -1 is because 0 is a valid number). Signed numbers divide that 4 billion evenly between positive and negative. 32-bit computers use this in their memory addresses, which means a program can natively access 4 GB of memory. 64-bit computers have a limit of 2^64, which is much, much higher.
You also run across that 4 billion limit if you're using 32-bit numbers to represent other things, like for example users, tweets, or seconds since a certain date. So 32-bit works just fine up to a certain scale, then above that, even though there are ways to work around the limit, it makes more sense to go to 64-bit.
The disadvantage is it takes twice as much memory to store your numbers.
Greetings everybody. I have seen examples of such operations for so many times that I begin to think that I am getting something wrong with binary arithmetic. Is there any sense to perform the following:
byte value = someAnotherByteValue & 0xFF;
I don't really understand this, because it does not change anything anyway. Thanks for help.
P.S.
I was trying to search for information both elsewhere and here, but unsuccessfully.
EDIT:
Well, off course i assume that someAnotherByteValue is 8 bits long, the problem is that i don't get why so many people ( i mean professionals ) use such things in their code. For example in SharpZlib there is:
buffer_ |= (uint)((window_[windowStart_++] & 0xff |
(window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_);
where window_ is a byte buffer.
The most likely reason is to make the code more self-documenting. In your particular example, it is not the size of someAnotherByteValue that matters, but rather the fact that value is a byte. This makes the & redundant in every language I am aware of. But, to give an example of where it would be needed, if this were Java and someAnotherByteValue was a byte, then the line int value = someAnotherByteValue; could give a completely different result than int value = someAnotherByteValue & 0xff. This is because Java's long, int, short, and byte types are signed, and the rules for conversion and sign extension have to be accounted for.
If you always use the idiom value = someAnotherByteValue & 0xFF then, no matter what the types of the variable are, you know that value is receiving the low 8 bits of someAnotherByteValue.
uint s1 = (uint)(initial & 0xffff);
There is a point to this because uint is 32 bits, while 0xffff is 16 bits. The line selects the 16 least significant bits from initial.
Nope.. There is no use in doing this. Should you be using a value that is having its importance more than 8 bits, then the above statement has some meaning. Otherwise, its the same as the input.
If sizeof(someAnotherByteValue) is more than 8 bits and you want to extract the least signficant 8 bits from someAnotherByteValue then it makes sense. Otherwise, there is no use.
No, there is no point so long as you are dealing with a byte. If value was a long then the lower 8 bits would be the lower 8 bits of someAnotherByteValue and the rest would be zero.
In a language like C++ where operators can be overloaded, it's possible but unlikely that the & operator has been overloaded. That would be pretty unusual and bad practice though.
EDIT: Well, off course i assume that
someAnotherByteValue is 8 bits long,
the problem is that i don't get why so
many people ( i mean professionals )
use such things in their code. For
example in Jon Skeet's MiscUtil there
is:
uint s1 = (uint)(initial & 0xffff);
where initial is int.
In this particular case, the author might be trying to convert an int to a uint. The & with 0xffff would ensure that it would still convert Lowest 2 Bytes, even if the system is not one which has a 2 byte int type.
To be picky, there is no guaranty regarding a machine's byte size. There is no reason to assume in a extremely portable program that the architecture byte is 8 bits wide. To the best of my memory, according to the C standard (for example), a char is one byte, short is wider or the same as char, int is wider or the same as short, long is wider or the same as int and so on. Hence, theoretically there can be a compiler where a long is actually one byte wide, and that byte will be, say, 10 bits wide. Now, to ensure your program behaves the same on that machine, you need to use that (seemingly redundant) coding style.
"Byte" # Wikipedia gives examples for such peculiar architectures.