If I declare the following variables:
int array[10] = { 34, 43,12, 67, 34, 43,26, 98, 423,1 };
int * p = array;
Then, this loop:
for ( int i = 0; i < 10; i++ )
{
std::cout << &*p++ << " ";
}
gives me different output ( a different set of addresses ), to this code:
for ( int i = 0; i < 10; i++ )
{
std::cout << p++ << " ";
}
Why? Aren't they semantically equivalent?
EDIT:
Well, my apologies to everyone that answered this one, I don't have the original code, it was a test that I did at home and it turns out that I deleted that code from my project. ( my broadband is not yet connected, so I waited till I got to work to post this ). Anyway - I am pretty sure that I was forgetting to initialise p. But the question of "aren't they semantically equivalent?" has been answered. Thanks.
int array[10] = { 34, 43,12, 67, 34, 43,26, 98, 423,1 };
int * p = array;
for ( int i = 0; i < 10; i++ )
{
std::cout << p++ << " ";
}
p = array;
std::cout << '\n';
for ( int i = 0; i < 10; i++ )
{
std::cout << &*p++ << " ";
}
std::cout << '\n';
Gives me the same addresses. Did you accidentally forget p = array; in between?
If you remember to reset p before the second loop, they give the same result.
reset the pointer p's position.
The order of precedence is '++' first, then '*' and finally '&'.
So p++ will output the adresse of array[0] and &*p++ will first increment p, but this is postfix ! So the value of p (and not the value of p+1) will be given to * and then to &, so these are the same
Example:
std::cout << p << std::endl; // Output the adress of p
std::cout << &*p++<<std::endl; // p is increment but it is postfix, so value of p is used and printed
std::cout << &*++p<<std::endl; // p has been increment before and is then incremented again
std::cout << p++ << std::endl; // p has been incremented before, but here p is used first, then incremented
Related
I have two double pointer array, which I want to print
but somehow I am not able to do it..
double *noise_feature = new double[5];
double *basic_feature = new double[39];
noise_feature_extraction(sig, len, noise_feature);
basic_feature_extraction(sig, len, basic_feature);
cout << "\n";
printf("Noice features are");
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
cout << *i << " ";
cout << "\n";
printf("Basic features are");
for (auto i = basic_feature.begin(); i != basic_feature.end(); ++i)
cout << *i << " ";
cout << "\n";
This gives error like this
Pan_Tompkins.cpp:992:29: error: member reference base type 'double *' is not a structure or union
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
~~~~~~~~~~~~~^~~~~~
Pan_Tompkins.cpp:992:57: error: member reference base type 'double *' is not a structure or union
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
I tried printing this way
printf("%g",noise_feature);
printf("%g",basic_feature);
This does not give error but also does not print anything.
How can I print this two double array to see their value?
You request a raw array on the heap and discard the info how many elements it has. Recall that
double *noise_feature = new double[5];
declares nothing but a pointer to double. The fact that you know it's a contiguous array of length 5 can be used in different way. Either you keep that magic number literal in your code;
for (auto value = noise_feature; value != noise_feature + 5; ++value)
// not maintainable, but works: ^^^^^^^^^^^^^^^^^
cout << *value << " ";
Or you go with a raw array on the stack. Here, the length is baked into the type and hence not lost. You could use a range-based for loop to iterate over it, for example.
double noise_features[5];
// ...
for (double value : noise_features)
std::cout << value << ' ';
However, the preferred solution is using either std::vector if the size of your sequence is only known at runtime, or std::array if it's a fixed-length sequence.
You declared two pointers
double *noise_feature = new double[5];
double *basic_feature = new double[39];
Pointers are scalar objects that do not have the member functions begin and end.
So you have to use the magic numbers 5 and 39 to output the allocated arrays pointed to by the pointers.
For example
cout << "\n";
printf("Noice features are");
for ( size_t i = 0; i < 5; ++i )
cout << noise_feature[i] << " ";
cout << "\n";
printf("Basic features are");
for ( size_t i = 0; i < 39; ++i )
cout << basic_feature[i] << " ";
cout << "\n";
The same can be done using pointers as for example
cout << "\n";
printf("Noice features are");
for ( auto p = noise_feature; p != noise_feature + 5; ++p )
cout << *p << " ";
cout << "\n";
printf("Basic features are");
for ( auto p = basic_feature; p != basic_feature + 39; ++p )
cout << *p << " ";
cout << "\n";
Pay attention to that instead of "manually" allocating dynamically arrays you could use the standard container std::vector as for example
#include <vector>
//...
std::vector<double> noise_feature( 5 );
//...
cout << "\n";
printf("Noice features are");
for ( const auto &item : noise_feature )
cout << item << " ";
cout << "\n";
//...
Arrays defined with statements like array_name[element_count] are not objects of any class!
Arrays are actually pointers to continuous memory. So, they don't have any methods and member functions. So your code will fail to compile. So instead of this:
for (auto i = noise_feature.begin(); i != noise_feature.end(); ++i)
Use this:
for (auto i = noise_feature; i != noise_feature + 5; ++i)
Or this:
for (auto i = std::begin(noise_feature); i != std::end(noise_feature); ++i)
Or you can store it in a std::vector<double> object. Also, why you used printf when C++ provides std::cout ?
Sample code:
int main()
{
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *j << endl;
}
will print:
4
5
int main()
{
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *(i + 1) << endl;
}
will print:
4
0
Do not get what is the difference
You are lucky or unlucky to get a value in your second code when using cout << *(i + 1) << endl; The i+1 means to move to next location in memory with a length of int. Since you didn't assign anything on the next location. There is no value at that location. It returns 0 but it could be anything!
You use lots of new here to open memory in heap which is not necessary. Many Java users may have habit to use new, but we need to be thoughtful on when to use new in C++. You also need to use delete to release memory if you use new.
Let's check out your code line by line:
int main() {
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *j << endl;
}
// Let's just say that an int is 32bits or 4bytes
int* i = new int(4);
// Declaring a pointer to type int and initializing it with a value of 4
int* j = i + 1;
// Declaring a pointer to type int at 4 memory address location's past i.
// For example: if i's memory address is 0x0004
// then j would be at memory location 0x0008.
// However j will contain any arbitrary value or garbage.
// before calling your next line `j = new int(5);`
// do this:
std::cout << i << " " << j << "\n";
std::cout << *i << " " << *j << "\n;
// Here you will see the address increase by a value of 4 in hex
// which is a 4 byte width provided the int is 32bits or 4bytes
// You will also see that when dereferencing the pointers that the
// memory location that i is point at does have the value 4,
// but the memory location that j is pointing at
// has garbage or any arbitrary value.
// With your next line of code:
j = new int(5);
// now you are taking j and pointing it to another location and assigning
// to that memory location the value of 5.
// You changed where j was pointing in memory.
std::cout << *i << std::endl; // self explanatory: dereferencing i and print value
std::cout << *j << std::endl; // same as above but for j
int main() {
int* i = new int(4);
int* j = i + 1;
j = new int(5);
cout << *i << endl;
cout << *(i + 1) << endl;
}
Every line above but the last line is the same. Let's check out the last line.
std::cout << *(i + 1) << std::endl;
// Here you are dereferencing the pointer that is 4 bytes past i.
Basically you are trying to print whatever is stored in memory location 4 bytes on a 32bit machine past i's location in the second part of your code.
If the wording is unclear refer to this picture diagram:
I found that the parameter I returned is different in the outer function when it's called than where it was in the local function. I set some printing out in each section of the code but still have no idea why the parameter i is not returned:
int assign_cookie(vector<int>& g, vector<int>& s){
if(s.size()==0 || g.size()==0){
cout << "size = 0, returning 0" << endl;
return 0;
}
cout << "s.size() = " << s.size() << endl;
cout << "g.size() = " << g.size() << endl;
sort(g.begin(), g.end());
sort(s.begin(), s.end());
unsigned int i, j = 0;
while(i<g.size() && j<s.size()){
if(g[i]<=s[j]) i++;
j++;
}
cout << "(assign_cookie) i = " << i << endl;
return i;
}
when I called it in the main function as follows:
int main(){
int g[] = {1,2,3};
int s[] = {1,1};
vector<int> vg (g, g+3);
vector<int> vs (s, s+2);
int result = assign_cookie(vg,vs);
cout << "result = " << result << endl;
}
I got results as follows:
s.size() = 2
g.size() = 3
(assign_cookie) i = 1
(main) result = 0
I was very confused with the result. Anyone has an idea what's going on?
Thanks in advance for your help!
You have undefined behaviour, because here
unsigned int i,j=0;
you only initialize j but not i and then you use i as index in g[i] without ever assigning it a meaningful value. Hence it is UB and anything can happen. Actually this is an interesting case of UB, as when you do
unsigned int i,j=0;
std::cout << "i = " << i << "\n";
it still prints
i = 0
(assign_cookie) i = 1
result = 0
see also here. Even if the compiler seems to initialize i to 0 it still realizes that there is UB and takes the freedom to produce garbage output.
I am working with tutorials point.com example.
int var[MAX] = {10, 100, 200};
int *ptr;
// let us have address of the last element in pointer.
ptr = &var[MAX-1];
for (int i = MAX; i > 0; i--)
{
cout << "Address of var[" << i << "] = ";
cout << ptr << endl;
cout << "Value of var[" << i << "] = ";
cout << *ptr << endl;
// point to the previous location
ptr--;
}
return 0;
So, why &var[MAX - 1] and why not &var[MAX]? If we do not use a reference, would it be possible to solve this problem in a different manner?
Because arrays in C++ are zero-based, i.e. start from 0 and end at n-1. var[MAX] is the element past the end of the array, so is out-of-bounds and accessing it is undefined behaviour.
var { 10, 100, 200 }
index ^0 ^1^ ^2^ ^3?
I'm working on a function to swap pointers and I can't figure out why this isn't working. When I print out r and s in the swap function the values are swapped, which leads me to believe I'm manipulating a copy of which I don't understand because I pass by reference of p and q.
void swap(int *r, int *s)
{
int *pSwap = r;
r = s;
s = pSwap;
return;
}
int main()
{
int p = 7;
int q = 9;
swap(&p, &q);
cout << "p = " << p << "q= " << q << endl;
return 0;
}
Prints: p = 7q = 9
Inside your swap function, you are just changing the direction of pointers, i.e., change the objects the pointer points to (here, specifically it is the address of the objects p and q). the objects pointed by the pointer are not changed at all.
You can use std::swap directly. Or code your swap function like the following:
void swap(int *r, int *s)
{
int temp = *r;
*r = *s;
*s = temp;
return;
}
The accepted answer by taocp doesn't quite swap pointers either. The following is the correct way to swap pointers.
void swap(int **r, int **s)
{
int *pSwap = *r;
*r = *s;
*s = pSwap;
}
int main()
{
int *p = new int(7);
int *q = new int(9);
cout << "p = " << std::hex << p << std::endl;
cout << "q = " << std::hex << q << std::endl << std::endl;
swap(&p, &q);
cout << "p = " << std::hex << p << std::endl;
cout << "q = " << std::hex << q << std::endl << std::endl;
cout << "p = " << *p << " q= " << *q << endl;
return 0;
}
Output on my machine:
p = 0x2bf6440
q = 0x2bf6460
p = 0x2bf6460
q = 0x2bf6440
p = 9 q= 7
The line r=s is setting a copy of the pointer r to the copy of the pointer s.
Instead (if you do not want to use the std:swap) you need to do this
void swap(int *r, int *s)
{
int tmp = *r;
*r = *s;
*s = tmp;
}
You passed references to your values, which are not pointers. So, the compiler creates temporary (int*)'s and passes those to the function.
Think about what p and q are: they are variables, which means they are slots allocated somewhere in memory (on the stack, but that's not important here). In what sense can you talk about "swapping the pointers"? It's not like you can swap the addresses of the slots.
What you can do is swap the value of two containers that hold the actual addresses - and those are pointers.
If you want to swap pointers, you have to create pointer variables, and pass those to the function.
Like this:
int p = 7;
int q = 9;
int *pptr = &p;
int *qptr = &q;
swap(pptr, qptr);
cout << "p = " << *pptr << "q= " << *qptr << endl;
return 0;
You are not passing by reference in your example. This version passes by reference,
void swap2(int &r, int &s)
{
int pSwap = r;
r = s;
s = pSwap;
return;
}
int main()
{
int p = 7;
int q = 9;
swap2(p, q);
cout << "p = " << p << "q= " << q << endl;
return 0;
}
Passing by reference is not the same as passing by value or by pointer. See C++ tutorials on the web for an explanation. My brain is too small to waste cells storing the fine details I can find on the web easily.
If you are into the dark arts of C I suggest this macro:
#define PTR_SWAP(x, y) float* temp = x; x = y; y = temp;
So far this has worked for me.