C++ pointer arithmetic logic [duplicate] - c++

This question already has answers here:
Pointer Arithmetic In C
(2 answers)
Closed 8 years ago.
A project I did last year involved pointer arithmetic. When I did that, I was able to treat pointers like memory addresses and add or subtract from them as I wanted. For example, if int* p == array[0], then you'd know that p + sizeof(int) would find array[1]. That doesn't seem to be the case anymore, as I have a relatively well-known interview question in front of me in which I have to debug the following code:
void
ReverseTheArray( const short *pArrayStart, int nArrayByteLength )
{
short const *pArrayEnd = (pArrayStart + nArrayByteLength);
while(pArrayStart != pArrayEnd)
{
short tmp = *pArrayStart;
*pArrayStart = *pArrayEnd;
*pArrayEnd = tmp;
pArrayStart++;
pArrayEnd--;
}
}
Note the last two lines - I would have bet that these were wrong because simply adding 1 to the pointer wouldn't work, you would need to add sizeof(short). But from testing the code it would seem I'm wrong - "pArrayStart++" adds sizeof(short) to the pointer, not 1.
When did this change? Can anyone give me some insight into what I'm wrong about so that I can not look stupid if I'm asked about this?
Edit: Okay - seems like it's always been that way. My bad.

The type of pointer is merely for this purpose. "Pointer to int" means adding one would skip 4 bytes (if int is 4 bytes on that machine.
Update: (Of course, in addition to explaining what type of data it is pointing to).

Related

Why can't an int variable hold a memory address? C++ [duplicate]

This question already has answers here:
How do I cast a pointer to an int
(6 answers)
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main() {
int a = 5;
int b = &a;
}
Why doesn't this work? If I make b a pointer like int *b = &a then that'll work but if a memory address is just an integer in hexadecimal then why is this not okay?
Well, first off, the sizes may not match; most general purpose computers nowadays use 64 bit addressing, but most compilers provide 32 bit ints (historically, some early 32 bit computers had 32 bit pointers but still provided 16 bit ints; this isn't a new problem).
It's also discouraged because it's usually an error (someone forgot to declare a variable as a pointer).
If you want a variable that is guaranteed to be able to fit a pointer, but acts like an integer, you can use intptr_t or uintptr_t, you just need to cast it to say "yep, I really meant to use this pointer as an integer".
It's not an integer in hexadecimal.
First of all, hexadezimal is just a possible output encoding, and the very same variable is also suitable for any other encoding, be it octal, decimal or binary. The native representation is binary in any case.
Next up, pointers and integral values are differentiated in the language design by choice, as a mix-up usually has bad consequences. Pointer also use pointer-arithmetic, which differs from integer arithmetic. E.g. (int*)(0) + 1 == (int*)( 0 + sizeof(int)).
Finally, that int is only 32bit, while the pointer, depending on the target architecture, requires 64bit, so this won't even fit, even if the compiler did allow that cast.

what does this mean *(int*)&x when typecasting? [duplicate]

This question already has answers here:
John Carmack's Unusual Fast Inverse Square Root (Quake III)
(6 answers)
Closed 6 years ago.
I am looking an example code for invert sqrt used in quake.
I see a variable of type float: float x = 16;
and then an int variable takes the value of this expression: int i = *(int*)&a;
The way I understand it(from right to left) is that it takes the address of the variable a, typecasts it in to an integer pointer and then takes the value of that pointer and assigns it to i.
when I output the variable i in the console it's a big integer value.
can someone explain more in dept of what is going on here please ?
because I expected the variable i to be 16.
&a takes the address of a, a float; (int *) keeps the same address but tells the compiler now to pretend that an int is stored there; int i = * then loads the int from that address.
So you get* an integer with the same bit pattern as the float had. Floats and ints have very different encodings so you end up with a very different value.
The float is likely to be formulated like this but it's not required; your architecture may do something else. Possibly the author is doing a platform-specific optimised version of frexp.
int i = (int)x; would simply convert the float to an int, giving you 16.

sizeof operator macro #define MYSIZEOF(X) ((X*)0 +1) [duplicate]

This question already has answers here:
Pointer Arithmetic [closed]
(7 answers)
Closed 7 years ago.
#include<stdio.h>
#define MYSIZEOF(X) ((X*)0 +1)
int main()
{
printf("%ld", MYSIZEOF(int));
return 0;
}
Can any one please explain how it works ?
thanks in advance
The idea here is simple: arithmetic on a pointer to a type T is performed in multiples of the sizeof(T), so ((X*)0 +1) will - hopefully - be a pointer to an address sizeof(X) bytes into memory.
Unfortunately, the behaviour's undefined as (X*)0 creates a NULL pointer, and the compiler may substitute some non-zero value used as that sentinel on the system it's compiling for. Further, the code assumes %ld is the right format for a pointer, and it may not be. %p would be an improvement if the printf implementation supports it.
Of course, it's silly not to use the sizeof operator directly....

Difference of two addresses in C [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Pointer Arithmetic
The given code
int arr[12];
int * cur = arr;
cur++;
cout<<"cur-arr = "<<cur-arr<<endl;
Outputs 1, but I expected sizeof(int). Can someone please explain the nature of this behavior?
It's a defined behavior of C pointer arithmetic. It uses the size of pointed type as a unit. If you change subtraction in the last line to
(char *)cur - (char *)arr
you get 4 in the output.
This is the number of elements (ints here) between arr and cur (which is arr+1 at the time of subtraction). Compiler takes note that cur is a pointer to an integer and arr is an integer array. To get total number of bytes, try this:
(cur - arr) * sizeof(arr[0]);
cur is a pointer to int, initialized to some value (arr - the semantics of array-to-pointer conversion are irrelevant here), incremented (cur++) and compared to its old value. Unsurprisingly, it grew by one through the increment operation.
Pointer arithmetic with a given type works just like regular arithmetic. While the pointer is advanced by sizeof(int) bytes in this example, the difference between pointers is also calculated in units of sizeof(int), so you see plain simple arithmetics.
Addition and substraction for pointers works in accordance to the pointer type.

C++ array[index] vs index[array] [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
In C arrays why is this true? a[5] == 5[a]
Is the possibility of both array[index] and index[array] a compiler feature or a language feature. How is the second one possible?
The compiler will turn
index[array]
into
*(index + array)
With the normal syntax it would turn
array[index]
into
*(array + index)
and thus you see that both expressions evaluate to the same value. This holds for both C and C++.
From the earliest days of C, the expression a[i] was simply the address of a[0] added to i (scaled up by the size of a[0]) and then de-referenced. In fact, all these were equivalent:
a[i]
i[a]
*(a+i)
====
The only thing I'd be concerned about is the actual de-referencing. Whilst they all produce the same address, de-referencing may be a concern if the types of a and i are different.
For example:
int i = 4;
long a[9];
long x = a[i]; //get the long at memory location X.
long x = i[a]; //get the int at memory location X?
I haven't actually tested that behavior but it's something you may want to watch out for. If it does change what gets de-referenced, it's likely to cause all sorts of problems with arrays of objects as well.
====
Update:
You can probably safely ignore the bit above between the ===== lines. I've tested it under Cygwin with a short and a long and it seems okay, so I guess my fears were unfounded, at least for the basic cases. I still have no idea what happens with more complicated ones because it's not something I'm ever likely to want to do.
As Matthew Wilson discusses in Imperfect C++, this can be used to enforce type safety in C++, by preventing use of DIMENSION_OF()-like macros with instances of types that define the subscript operator, as in:
#define DIMENSION_OF_UNSAFE(x) (sizeof(x) / sizeof((x)[0]))
#define DIMENSION_OF_SAFER(x) (sizeof(x) / sizeof(0[(x)]))
int ints[4];
DIMENSION_OF_UNSAFE(ints); // 4
DIMENSION_OF_SAFER(ints); // 4
std::vector v(4);
DIMENSION_OF_UNSAFE(v); // gives impl-defined value; v likely wrong
DIMENSION_OF_SAFER(v); // does not compile
There's more to this, for dealing with pointers, but that requires some additional template smarts. Check out the implementation of STLSOFT_NUM_ELEMENTS() in the STLSoft libraries, and read about it all in chapter 14 of Imperfect C++.
edit: some of the commenters suggest that the implementation does not reject pointers. It does (as well as user-defined types), as illustrated by the following program. You can verify this by uncommented lines 16 and 18. (I just did this on Mac/GCC4, and it rejects both forms).
#include <stlsoft/stlsoft.h>
#include <vector>
#include <stdio.h>
int main()
{
int ar[1];
int* p = ar;
std::vector<int> v(1);
printf("ar: %lu\n", STLSOFT_NUM_ELEMENTS(ar));
// printf("p: %lu\n", STLSOFT_NUM_ELEMENTS(p));
// printf("v: %lu\n", STLSOFT_NUM_ELEMENTS(v));
return 0;
}
In C and C++ (with array being a pointer or array) it is a language feature: pointer arithmetic. The operation a[b] where either a or b is a pointer is converted into pointer arithmetic: *(a + b). With addition being symetrical, reordering does not change meaning.
Now, there are differences for non-pointers. In fact given a type A with overloaded operator[], then a[4] is a valid method call (will call A::operator ) but the opposite will not even compile.