Difficult cast with int64 and int32 pointers - pointers

I have int64_t value1; int32_t value2;. Then I have *(int32_t*)&value1 = value2;
Could you please describe what *(int32_t*)&value1 mean? Does it mean "the lowest 32 bits of value1" so *(int32_t*)&value1 = value2; means "the first 32 bits of value1 are replaced with those of value2"?
Or am I completely wrong?

That is going to depend on the byte-order of the machine it runs on. It is pretty poor practice.
On a little endian system, which is most Intel hardware, the lowest order byte is first, so the 32 bit SIGNED value will be written to the lower 32 bits of the 64 bit integer. On a big endian system, it would be written to the high order bits.
note that the int is signed. If value2 is a negative value, the resulting 64bit number will not be negative (unless it was already negative).
It also won't change the high order bits of the 64bit int.
I'd say...don't do that?
EDIT
To more directly answer your question, yes, you are right, depending on what you mean by the "first 32 bits". First in whatever order the platform uses, yes.
&value1 -> will give the address of value1
(int32_t*)&value1 -> tells the compiler to treat the address of value1 as a pointer to an int32_t
*(int32_t*)&value1 -> then dereference the pointer, so assigning to this will put the assigned value into the address of value1 as if it were an int32_t.

Related

What is the max number that you can take by 27 in 32 bits

I am doing something in coding where it multiplies a number by from 1 to 27. I need to make a fail safe, where no number can be over this. Rounding to 2^32/2^64 would not work. It needs so be 32 bits so it can both support 32 and 64 bit OS's.
If you want to multiply 3 by 5, but know the maximum allowed result is 10, you can easily tell that 3 is too large because 3 > 10/5. That’s all there’s to it :)
Since you insist on using a 32-bit type, and I assume your programming language is C, the maximum value int32_t can represent is INT32_MAX - those two come from #include <stdint.h>.
But you may be mistaken in your assumption about being limited to 32-bit types: int64_t works on most if not all major 32-bit platforms :)
(2^32/27-1) will not give you the correct upper value. As an integer it is 159072861 which is one too low.
The maximum integer value that can be stored in 32 bits is 2^32 - 1 which works out as 4294967295.
So the maximum value is actually (2^32 - 1) // 27 which is 159072862.
Note the use of integer division which I assume is what you want.

how those bit-wise operation work and why wouldn't it use little/small endian instead

i found those at arduino.h library, and was confused about the lowbyte macro
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
at lowByte : wouldn't the conversion from WORD to uint8_t just take the low byte anyway? i know they w & 0x00ff to get the low byte but wouldn't the casting just take the low byte ?
at both the low/high : why wouldn't they use little endians, and read with size/offset
i.e. if the w is 0x12345678, high is 0x1234, low is 0x5678, they write it to memory as 78 56 34 12 at say offset x
to read the w, you read to size of word at location x
to read the high, you read byte/uint8_t at location x
to read the low, you read byte/uint8_t at location x + 2
at lowByte : wouldn't the conversion from WORD to uint8_t just take the low byte anyway? i know they w & 0x00ff to get the low byte but wouldn't the casting just take the low byte ?
Yes. Some people like to be extra explicit in their code anyway, but you are right.
at both the low/high : why wouldn't they use little endians, and read with size/offset
I don't know what that means, "use little endians".
But simply aliasing a WORD as a uint8_t and using pointer arithmetic to "move around" the original object generally has undefined behaviour. You can't alias objects like that. I know your teacher probably said you can because it's all just bits in memory, but your teacher was wrong; C and C++ are abstractions over computer code, and have rules of their own.
Bit-shifting is the conventional way to achieve this.
In the case of lowByte, yes the cast to uint8_t is equivalent to (w) & 0xff).
Regarding "using little endians", you don't want to access individual bytes of the value because you don't necessarily know whether your system is using big endian or little endian.
For example:
uint16_t n = 0x1234;
char *p = (char *)&n;
printf("0x%02x 0x%02x", p[0], p[1]);
If you ran this code on a little endian machine it would output:
0x34 0x12
But if you ran it on a big endian machine you would instead get:
0x12 0x34
By using shifts and bitwise operators you operate on the value which must be the same on all implementations instead of the representation of the value which may differ.
So don't operate on individual bytes unless you have a very specific reason to.

Explain concept of size of integer,character and float pointer in GCC

In GCC(Ubuntu 12 .04) Following code is the program which i need to understand for the concept of size of integer,character and float pointer.
#include<stdio.h>
main()
{
int i=20,*p;
char ch='a',*cp;
float f=22.3,*fp;
printf("%d %d %d\n",sizeof(p),sizeof(cp),sizeof(fp));
printf("%d %d %d\n",sizeof(*p),sizeof(*cp),sizeof(*fp));
}
Here i am getting following output when i run the above code in "UBUNTU 12.04"
Output:
8 8 8
4 1 4
As per this lines,"Irrespective of data types,size of pointer for address it will allow 4 bytes BY DEFAULT"
Then what is the reason behind getting sizeof(p)=8 instead it should be sizeof(p)=4....
Please explain me.
sizeof(x) will return the size of x. A pointer is like any other variable, except that it holds an address. On your 64 bit machine, the pointer takes 64 bits or 8 bytes, and that is what sizeof will return. All pointers on your machine will be 8 bytes long, regardless of what data they point to.
The data they point to may be of a different length.
int x = 5; // x is a 32 bit int, takes up 4 bytes
int *y = &x; // y holds the address of x, & is 8 bytes
float *z; // z holds the address of a float, and an address is still 8 bytes long
You're probably getting confused because you previously have done this on a 32 bit computer. You see, the 32 / 64 bit indicates the size of a machine address. So, on a 32 bit computer, a pointer holds an address that is at most 32 bits long, or four bytes. Your current machine must be a 64 bit machine, which is why the pointer needs to be 8 bytes long.
Read more about this here.
Heck, it's not just the address length. The size of other data types is also platform AND implementation dependent. For example, an int may be 16 bits on one platform & 32 bits on another. A third implementation might go crazy and have 128 bit ints. The only guarantee in the spec is that an int will be at least 16 bits long. When in doubt, always check. The Wikipedia page on C data types would be helpful.
sizeof(p) will return an address, and you are most likely running on a 64-bit machine, so your addresses will be (8*8) or 64 bits in length.
The size of the value dereferenced by p is a 32 bit integer (4*8).
You can verify this by seeing that all:
All pointers have sizeof as 8
Your char value is size 1 (typical of many implementations of c)
Print p and *p (for all variables). You will see the actual address length this way.
I'm not sure which documentation you're using but my guess is that they're talking about pointers in 32bit.
In 64 bit the size of a pointer becomes 8 bytes

Does the 6502 use signed or unsigned 8 bit registers (JAVA)?

I'm writing an emulator for the 6502, and basically, there are some instructions where there's an offset saved in one of the registers (mostly X and Y) and I'm wondering, since branch instructions use signed 8 bit integers, do the registers keep their values as 8 bit signed? Meaning this:
switch(opcode) {
//Bunch of opcodes
case 0xD5:
//Read the memory area with final address being address + x offset
int rempResult = a - readMemory(address + x);
//Comparing some things, setting/disabling flags
//Incrementing program counter and cycles/ticks
break;
//More opcodes
}
Let's say in this situation that x = 0xEE. In regular binary, this would mean that x = 238. In the 6502 however, the branch instruction uses signed offset for jumping to memory addresses, so I'm wondering, is the 238 interpreted as -18 in this case, or is it just regular unsigned 8 bit value?
It varies.
They're not explicitly signed or unsigned for arithmetic, logical, shift, or load and store operations.
The conditional branches (and the unconditional one on the later 6502 descendants) all take the argument as signed; otherwise loops would be extremely awkward.
zero, x addressing is achieved by performing an 8-bit addition of x to the zero page address, ignoring carry, and reading from the zero page. So e.g.
LDX #-126 ; which is +130 if unsigned
LDA 23, x
Would read from address 23+130 = 153. But had it been 223+130 then the end read would have been from (223 + 130) MOD 256 = 97.
absolute, x/y is unsigned and carry works correctly (but costs an extra cycle)
(zero, x) is much like the direct version in that the offset is signed but the result is always within the zero page. Then the real address is read from there.
(zero), y is unsigned with carry working and costing.
The "sign" is simply the value of the most significant (aka bit 7) in an 8-bit byte.
6502 has support for signed values in these ways:
The N bit in .P - but it really just tells you if the last instruction turned on or off bit 7 of a memory location or register. It was common to use BPL/BMI to do stuff based on bit 7 in a memory location for flag or "boolean" like use.
The V bit of .P which is flipped "when the result of adding two positive numbers overflows and ends up negative, and when the result of adding two negative numbers overflows and ends up positive"
And of course obeying the sign bit for relative branch instructions only, e.g. BEQ with a value with bit 7 set will move to a lower memory location, not a higher one.
Beyond that, whether that bit means anything is completely up to you and your program. What really makes numbers signed or unsigned is how you display the numbers.
The linked article above goes into what one's complement and two's complement is and how it makes the mathematics work without the 6502 having to care too much about the sign.

Is there any sense in performing binary AND with a number where all bits are set to 1

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.

Resources