I'm in a data structures course, our midterm is coming up and our practice midterm asks if each line is valid syntax:
int num = 10;
int *p, *q;
p = #
q = p; //valid
*p = q; //invalid, int* cannot be assigned to int
(*p)++; //valid
&num+1; //valid ********
p++; //valid ********
So the last two lines of code, as I understand it, add 1 to the address of the num variable.
What purpose would this have in coding?
In this case, that would lead to undefined behavior. It would address the int that follows num in memory, but there is no defined way to tell what that would be. Nonetheless, it is valid syntax.
It would make a great deal more sense if your pointer pointed to an element of an array instead of a scalar. In that case, addressing the next int is reasonable. But in both cases the syntax is valid.
A purpose this would have in coding is to write tests such as:
void f ( size_t length, int data[length] )
{
assert( 0 == length % 4 );
for ( int* p = data; p < data + length; p += 4 )
do_stuff_with_subarray( p, 4 );
return;
}
The loop condition p < data + length bounds-checks the pointer by comparing it to the address one past the end of the array. Dereferencing this address would be undefined behavior, but comparing to it is not. (In this simplistic example, though, there will be UB if do_stuff_with_subarray() ever reads past the end of an array whose length is not divisible by 4.)
Related
I am new to c++ and trying out some stuff.
So recently I tried to create an int array on the heap and iterate it with addressation instead the standard way with [x].
Everytime I execute my code I get a heap corruption error.
I tried several things (also searched here on stackoverflow) but could not find any answers.
int* p = new int[5];
for (int i = 0; i <= 4; i++){
/*p[i] = i;
cout << p[i] << endl;*/ //This is the standard way and works
*p = i;
cout << *p << endl;
p = (p + sizeof(*p)); //iterate the pointer through the heap addresses
}
delete[] p;
The application runs and shows me the filled array values {0,1,2,3,4} but then crashes.
I get following error message:
HEAP CORRUPTION DETECTED: after CRT Block (#225) at 0x00C31B68.
CRT detected that application wrote to memory after end of heap buffer...
Thanks in advance
When you do this
p = (p + sizeof(*p));
you are taking sizeof(int) int-sized steps across the array, going beyond its bounds.
You need to take single steps:
p = (p + 1);
or
++p;
But note that after doing that, p no longer points to any place you can call delete[] on. You need to keep a pointer to the original address:
int* arr = new int[5];
int* p = arr;
....
delete[] arr;
But you have no reason to allocate the array with new in the first place.
int arr[5];
int * p = arr;
....
p = (p + sizeof(*p));
results in a jump of 4 with every iteration, as sizeof(int) is equal to 4. Hence, you are going out of bounds.
The standard way, that is :
p[i] = i;
cout << p[i] << endl;
is correct, as i increases by 1 in every iteration.
This statement
p = (p + sizeof(*p));
is wrong.
First of all you are changing the initial value of pointer p that points to the allocated memory.So this statement
delete[] p;
will be wrong for this pointer because initial value of p was changed.
Secondly expression p + sizeof(*p) means that you want to move the pointer right to sizeof( *p ) elements. If for example sizeof( *p ) is equal to 4 then after statement
p = (p + sizeof(*p));
p will point to fifth element of the array (that is with index 4).
Valid code can look the following way
int* p = new int[5];
for ( int i = 0; i < 5; i++){
*( p + i ) = i;
cout << *( p + i ) << endl;
}
delete[] p;
In pointer arithmetics an expression p + i, where p is a pointer to an array's element and i is integer, is equivalent to &(p[i]), that is a pointer to the array's element i positions after the one pointed at by p.
That's why stepping to the next element is performed by p = p+1 (or equvalently p += 1 or simply ++p).
Note however the incrementation does no checking for the array bounds – you're able to safely access the next item(s) provided they belong to the same array. If you step beyond the last item of an array you may get memory access error or just read some garbage.
See for example
http://www.tutorialspoint.com/cplusplus/cpp_pointer_arithmatic.htm
https://www.eskimo.com/~scs/cclass/notes/sx10b.html
i have this code snippets
const int col= 5;const int row= 5;
int a[row][col] = {0};
int (*p)[col] ;
p = a;
And these statements print the same address
cout <<p;
cout << endl;
cout << *p;
in my opinion since p points to an array of 5 ints, dereferencing it
should give the first value which doesn't seem to be the case.
help!
since p points to an array of 5 ints
That much is correct.
dereferencing it should give the first value
No, it's type is "pointer to array"; dereferencing that gives "array", which decays to an int* pointer when you do just about anything with it - including printing it.
If you had a pointer to int
int * p = a;
then *p would indeed give the first array element.
Consider the function :
void swap (int *p,int *q)
{
int temp;
temp=*p;
*p=*q;
*q=temp;
}
swap(4 , 5)
Output:
5 4
I am aware that this is the right way to swap two integers using pointers, as mentioned in the books. But what is actually going on in there? It's very confusing. Consider this function , where the step *p=*q is replaced by p=q i.e., with the indirection operator * removed .
void swap (int *p,int *q)
{
int temp;
temp=*p;
p=q;
*q=temp;
}
Now ,what would happen? In this case the output i get for
swap(4 , 5)
Output:
4 4
Think of an int as a box with a number in it, and think of a pointer as an entry on your clipboard telling you which box to look in.
When you do
*p = *q;
you're looking on your list to find out which box you should use for p, and which box you should use for q; then you're looking what number is in the q box, and copying it into the p box. You still have two separate boxes, and two separate entries on your clipboard; it's just that the two boxes have the same number in.
But when you do
p = q;
you're not touching the boxes at all. You're only changing your clipboard. You're looking up which box you should use for q, and then you're scrubbing out the entry for p on your clipboard and replacing it with the same entry that you found under q. Now you have two boxes, with different numbers in; but your clipboard contains two entries that are the same, and both direct you to the same box. One of your boxes is now unreachable (you don't have an entry on your clipboard pointing you to it), and whenever you look up p or q, you'll end up looking in the same box.
(It's worth noting that this clipboard is only used for executing this particular function, and it gets thrown away afterwards. Changes that you make to the pointers that you pass in as arguments to the function won't have any effect after the function has finished executing. But I'd get your head round the other concepts first off, before you start worrying about scope.)
Because you've removed the step where the int 5 is moved to *p, so you're only moving the 4 across to *q via temp.
Note that int *p and int *q are pointers (represent memory addresses!!). So, when you write p=q you end-up with two pointers that point to the same address!!!
void swap (int *p,int *q)
{
int temp;
temp=*p; // temp = 4
p=q; // p points at the same address with q (where 5 is stored)
*q=temp; // store 4 where q points
}
You now understand that both pointers point to a memory location where integer 4 has been stored! Both pointers point to the same memory location.
In general, the best method for understanding what happens in code with pointers is to bring out a pencil and some paper and start drawing.
I used my computer for this, which is much, much slower.
Since swap(4,5) doesn't actually work, I'll assume that we have two variables in the code that calls swap:
int x = 4;
int y = 5;
swap(&x, &y);
The first two lines of swap are identical in both versions, so the first two pictures apply to both.
As you enter swap, it will look something like this:
As you can see, p points at x, and q points at y.
The value of temp is indeterminate.
Now we have followed the p pointer (*p) and copied the value of x into temp.
Version one:
Here, we follow the pointer q (*q), fetching the value of y (i.e. 5) and then we follow the pointer p (*p) and store that value into x.
And lastly, we follow q so we can store the value of temp, i.e. the value that x used to have, in y.
Version two
Here, we copy the value of q into p.
Since p and q are pointers, they now point to the same thing (y).
As you can see, the variable x hasn't changed; we just changed p so it points somewhere else.
This step is exactly the same as in the first version: store the value of temp in y by following q.
Hope this makes it clearer.
your program will crash because you are passing constant value swap(4,5); and there is no address for 4 and 5what p and q gonna point?
void swap(int *p,int *q){
......
}
expecting two variable to whom pointer p and q can point.
Copy this code to your code editor and test run it. Try to understand what this code is doing using comments.
//Start from main() function
#include <iostream>
using namespace std;
// We are here from main function
/*
This function takes two arguments
both are pointer of type int. When declaring
a pointer of type int we write "int *x". Which means
that the vaiable x is pointer and it can only hold
an address of a varible instead of it's value.
However, We now have addresses of p in x and
q in y. We want to exchange values but taking
addresses of them instead. This is a bit confusing.
*/
void swap(int *x, int *y)
{
int temp = 0;
/*
Things are more confusing in the line below.
" * " is a multipurpose operator.
1. When you put this operator in the middle
of two variable (like a*b ) then it works as a
multipliyer.
2. When you put it when declaring a variable
( like int *x ) then it works as if you are
declaring a pointer of type int.
3. When you put it before a pointer variable name but not
declaring the pointer variable then it gives the
value the pointer pointing to.
In our case the third statement is happening. As x has
the address of p, *x means the value of p.
*/
temp = *x; // Here, *x = 10 (because p = 10) so temp = 10.
/*
Here, we are replacing the value of *x (or p, which is 10)
by *y (or q which is 20).
So, after the execution of the line below
we will have *x = 20 or p = 20. It means we are losing
the previous value of p. This is the reason we kept the value
of p in temp.
*/
*x = *y; // Now p = 20 and q = 20
/*
The line below sets *y (or q ) to the value of temp
(which is 10).
*/
*y = temp; //Now p = 20 and q = 10
}
int main()
{
int p = 0;
int q = 0;
cout << "Enter p : ";
cin >> p; // Say you have entered 10. Now p = 10
cout << "Enter q : ";
cin >> q; // Say you have entered 20. Now q = 20
/*
This line takes you to the swap function above.
We are not sending p, q here. We are sending pointer
or addresses of p and q.
*/
swap(&p, &q); // This line takes you to the swap function above.
cout << "p : " << p << endl;
cout << "q : " << q << endl;
return 0;
}
The function which works correctly:
void swap (int *p,int *q)
{
int temp; //You take an integer variable
temp=*p; //You store the value pointed to by p to temp which is 4
*p=*q; //You copy the value pointed to by q to p which is 5, hence p points to 5
*q=temp; //You store the value in temp as the value pointed by q, hence q points to 4 as temp holds 4
}
Now the code with your changes:
void swap (int *p,int *q)
{
int temp;
temp=*p; //You store the value pointed to by p to temp which is 4
p=q; //p and q are addresses, you equate them so the value pointed becomes equal, if you make change in one the other changes automatically. So basically the value of 'p' in the calling function doesn't change, the change is a local change as the arguments to the called function are passed by reference. So the calue pointed to by p is not altered in 'swap' function.
*q=temp; //Now to make the value pointed to by q as 4
}
You can use the xor swap algorithm:
#include <stdio.h>
int main(int argc, char** argv)
{
int i = 1;
int j = 2;
int *p = &i;
int *q = &j;
printf("BEFORE: %d - %d\n", *p, *q);
if (*p != *q)
{
/* swap */
*p ^= *q;
*q ^= *p;
*p ^= *q;
}
printf("AFTER: %d - %d\n", *p, *q);
return 0;
}
reference:
http://en.wikipedia.org/wiki/XOR_swap_algorithm
Why is the j at the end of the execution an "1"?
Compiled with following flags gcc -m32 xxx.c on a 64 bit Unix machine.
#include <stdio.h>
int main(int argc, char **argv)
{
int *q = (int *)2;
char *r = (char *)1;
int j;
q++;
r++;
j = (int *)q - (int *)r;
printf("j = %d\n", j);
return 0;
}
Code is only for academic purposes! ;)
First of all, in theory this is all undefined behavior, since you are using pointers to not allocated memory, comparing stuff that do not belong to the same array etc.
Now, putting this aside, once you have clear the mechanics of pointer arithmetic it's quite easy:
int *q = (int *)2;
char *r = (char *)1;
int j;
// a pointer is incremented in steps of the size of its "base type"; this
// allows to move to the next element if you are pointing inside an array
q++; // q=(int*)(2+sizeof(int))=(int *)6
r++; // r=(char *(1+sizeof(char))=(int *)2;
// again, the difference between two pointers is computed in units of the
// base type; in an array, this gives you how many places are two elements
// apart
j = (int *)q - (int *)r; // (6-2)/sizeof(int)=1
(here sizeof(int) is 4 since you are compiling with gcc and -m32, and sizeof(char) is 1 by definition of sizeof)
Note: You are invoking undefined behavior, there's nothing saying that the alignment of int is 2 or less; nor are q and r members of the same array, or the same object.. you should never do what you are doing in your snippet.
Ignoring the obvious undefined behavior
One should never take undefined behavior lightly, the result of your code is highly implementation specific, and can do pretty much anything. But theoretically the code will be interpreted as described below, but there is no such guarantee.
j will be the distance between q and r (both interpreted as int*).
Incrementing a pointer to int will move it sizeof(int) bytes forward, while incrementing a pointer to char will move it sizeof(char) byte forward.
Subtracting one pointer from another yields the number of elements between them, not the number of bytes.
A few assumptions, and a detailed description
Assuming that the underlying implementation has sizeof(int) = 4, we will have the following pseudo-code:
int_ptr q = 2
char_ptr r = 1
/* ++q -> */ value_of(q) += 4; // sizeof(int) = 4, value_of(q) = 6
/* ++r -> */ value_of(r) += 1; // sizeof(char) = 1, value_of(r) = 2
int j = int_ptr(q) - int_ptr(r); // j = 1
// (value_of(q) - value_of(r))/sizeof(int)
The answer: j = 1
There is a pointer-to-an-Array of Arrays i.e. NameList in the code. I want the contents of each of the Arrays in the Pointer(NameList) to get printed one by one. The below code is not able do the task. Pls. help.
int Data1[] = {10,10};
int Data2[] = {20,20};
int Data3[] = {30,30};
int *NameList[] = {Data1, Data2, Data3};
main()
{ Function(NameList); }
Function(int *ArrayPointer)
{
int i, j, index=0;
for (i=0; i < 3; i++)
{
for (j=0; j < 2; j++)
{
//It does not print the data
printf("\nName: %s", ArrayPointer[index++]);
}
index=0; //Counter reset to 0
ArrayPointer++; //Pointer is incremented by one to pick next array in the pointer
}
}
print("code sample");
Another note from the original poster of the question:
I have completed a pacman game in Turbo C. I was polishing some graphics routines so that it can be reused again easily. This is only a small sample created for the purpose of help and understanding the concept. All data in the code actually are char arrays for sprites. Now i simply want to call a function passing the pointer so that each arrays in the pointer are drawn to the screen. How can this code be modified to handle this? Im actually stuck up here.
Darn it litb, once again you beat me to the punch by mere minutes. (If only I didn't have kids who keep waking up...)
Ahh, what the hell. Perhaps this will still be useful to somebody.
Oh, and just to nail this thing down:
Arrays, such as int a[4] allocate memory space for their data.
Pointers, such as int * p allocate just enouch memory space for a pointer to another spot in memory.
That's why we can use sizeof on arrays and get the full memory footprint, but not on pointers.
Other than that little distinction, there really isn't a big difference between int[] and int*. (Consider how many folks declare *main(int argc, char **argv) vs main(int argc, char * argv[]).)
ATTENTION: All memory addresses here are fictional. I'm just making them up to illustrate a point.
Given:
int Data1[] = {10,11};
int Data2[] = {20,22};
int Data3[] = {30,33};
We now have 3 blocks of memory. Say:
0xffff0000-0xffff0003 with a value of (int)(10)
0xffff0004-0xffff0007 with a value of (int)(11)
0xffff0008-0xffff000b with a value of (int)(20)
0xffff000c-0xffff000f with a value of (int)(22)
0xffff0010-0xffff0013 with a value of (int)(30)
0xffff0014-0xffff0017 with a value of (int)(33)
Where:
Data1 == & Data1 [0] == 0xffff0000
Data2 == & Data2 [0] == 0xffff0008
Data3 == & Data3 [0] == 0xffff0010
NO, I'm not going to get into big-endian vs little-endian byte ordering here!
Yes, in this case, Data1[2] == Data2[0]. But you can't rely on your compiler laying things out in memory the same way I've laid them out here.
Next:
int *NameList[] = {Data1, Data2, Data3};
So we now have another block of memory. Say:
0xffff0018-0xffff001b with a value of (int*)(0xffff0000)
0xffff001c-0xffff001f with a value of (int*)(0xffff0008)
0xffff0020-0xffff0023 with a value of (int*)(0xffff0010)
Where:
NameList == & NameList [0] == 0xffff0018
Note that NameList is of int ** type, and NOT int* type!
We can then write:
void Function(int **ArrayPointer)
{
for ( int i=0; i < 3; i++ )
for ( int j=0; j < 2; j++)
printf("Name: %d\n", ArrayPointer[i][j] );
}
int main() { Function(NameList); }
ArrayPointer resolves to (int**)0xffff0018.
ArrayPointer[0] == *( (int**) 0xffff0018 ) == (int*)(0xffff0000) == Data1.
ArrayPointer[0][1] == *( ( * (int**) 0xffff0018 ) + 1 ) == (int) * ( (int*)0xffff0000 + 1 ) == (int) * (int*) 0xffff0004 == Data1[1].
You may want to review pointer arithmetic: array[N] == *( array + N )
main has to return a type. You forget to put "int" as a return type (implicit int in C++ is banned).
Having said that, i'm not sure what you mean by
// It does not print the data
printf("\nName: %s", ArrayPointer[index++]);
ArrayPointer[index++] would, as it is defined in the parameter list, return an int. How is that supposed to store a name ? It will store an integer!
Once again, that said, you can't call that Function (pun intended) with that particular argument. Let's view your types:
int Data1[] = {10,10};
int Data2[] = {20,20};
int Data3[] = {30,30};
int *NameList[] = {Data1, Data2, Data3};
Data1 Data2 Data3 NameList
int[2] int[2] int[2] int*[3]
Contrary to what you said, NameList is not a pointer to an array of arrays. I feel i need to show you what that would be:
int (*NameList)[N][M] = Some3DimensionalArray;
That wouldn't make sense at all. So what do you have?
Data1 = array of 2 int
Data2 = array of 2 int
Data3 = array of 2 int
NameList = array of poiners to int
That is what you got. And you pass NameList to a Function that wants a pointer to an int. It must fail already at the time you call Function in main! I've got no idea what you mean by name in that line in Function. But if you want to print out the integers that are stored in the arrays pointed to (by pointers to their first element), you can do it like this (keeping your code as much as i can):
// don't forget the return type, mate. Also see below
void Function(int **ArrayPointer)
{
int i, j, index=0;
for (i=0; i < 3; i++)
{
for (j=0; j < 2; j++)
{
// It does not print the data. It is not a string,
// but an int!
printf("\nName: %d\n", ArrayPointer[i][index++]);
}
index=0; //Counter reset to 0
// no need to increment the pointer. that's what the indexing by i
// above does
// ArrayPointer++;
}
}
I keep preaching people asking questions the difference between a pointer and an array. It's crucial to write correct code. I hope i could help. At the end, just a little though about the difference between int[] and int*. The first is an incomplete array type, while the second is a complete type (pointer to int):
typedef int Single[]; // array of indeterminate size.
typedef int *Pointer; // pointer to int
Single s1 = { 1, 2, 3, 4 }; // works!
Pointer s2 = { 1, 2, 3, 4 }; // no no, doesn't work. s2 wants an address
s2's type now has a type different from int[], because you initialized the array which would have incomplete type, the array s1 become complete after defined. It has type of int[4]. In parameter lists, however, there exist a special rule, which will cause any array type (even complete ones!) to be equivalent to a pointer to their first argument. Thus:
void f(int *a) <=> void f(int a[]) <=> void f(int a[42]);
void f(int (*a)[42]) <=> void f(int a[][42]) <=> void f(int a[13][42])
// ...
That's because you can't pass arrays by value. The compiler abuses that to make array types equivalent to pointers to their first element. Same deal with functions:
void f(int a()) <=> void f(int (*a)())
Because you can't pass functions by value (huh, doesn't even make sense at all to me), the compiler abuses it to make a function type in a parameter list equivalent to a pointer to that function type.
int Data1[]
has the type of
int *
and
int *NameList[]
has the type of
int **
You have a two-dimensional array there. Most likely you meant:
Function(int **ArrayPointer)
On that note, ANSI C/C89/C99 functions have an explicit return type (or void), e.g.
int main() { ... }
void Function() { ... }
The value pointed to by ArrayPointer is an int, not a string. Thus
printf("\nName: %s", ArrayPointer[index++]);
Should be written as something else.
A third thing: index == j in your code. Thus index can be removed in favor of j.
i and j are probably not good variable names here because ArrayPointer is not name describing a list of something.
If you need more help, please post what you're looking to do, because you code has several bugs (and oddities) in it.
Judging by your "answer" (you really should have edited your original post and added this information), you probably want something like this:
void draw_all_sprites(Sprite *sprites, size_t num_sprites)
{
Sprite *cur_sprite;
size_t i;
for(i = 0; i < num_sprites; ++i)
{
draw_sprite(cur_sprite);
++cur_sprite;
}
}
A fairly simple for loop to iterate through elements in an array.
Paramod,
is there a function you need to call that takes something along the lines of
void drawSprite(int *data, int rows, int cols)
?
Then you need to have all data in a single chunk of memory. In your example, the compiler allocates a separate chunk for every row, and then another chunk to hold the three pointers to rows. Thus, the array is kept in 4 different places.
What you need is a multidimensional array rather than array of arrays. Initialize your data like this:
int data[3,2] = {{10,10},{20,20},{30,30}};
Then you can call your function like this:
drawSprite(&data[0,0], 3, 2);
Using multidimensional array places all elements in one block of memory. The advantage is, you can pass the piointer to first element, and you know where all other elements are. The disadvantage - all rows are allocated the same size.
I made some corrections in your program please find them and compare. I know its too late for the response. But I saw this today itself.
int Data1[] = {10,10};
int Data2[] = {20,20};
int Data3[] = {30,30};
int *NameList[] = {Data1, Data2, Data3};
main()
{
Function(NameList);
}
Function(int *ArrayPointer)
{
int i, j, index=0;
for (i=0; i < 3; i++)
{
for (j=0; j < 5; j++)
{
//It does not print the data
printf("\nName: %d\n", *((int *)ArrayPointer[i] + index));
index++;
}
index=0; //Counter reset to 0
}
}
Explanation:
When you pass NameList to Function as a pointer to an integer, what gets passed is the address of the first element of the array, which happens to be Data1 (an address to an array). But since this address is held in an array of ints, it will be considered as an integer. To make it behave like an address to an array(or, for that matter pointer to an int) you need to cast it to (int *). Thats what I did in :
printf("\nName: %d\n", *((int *)ArrayPointer[i] + index));