Question about the efficiency of using an array or individual variables

AI Thread Summary
The discussion centers on the efficiency of using arrays versus individual boolean variables in programming. It suggests that individual variables may offer faster access due to direct addressing, while arrays may benefit from memory caching. The initialization of an array with multiple values is clarified, explaining that using a single initializer only sets the first element, leaving others at zero. Additionally, the conversation highlights the limitations of fixed-size arrays, advocating for dynamic arrays or vectors for user-defined sizes. The complexities of user input handling for dynamic arrays are also addressed, suggesting the use of sentinel values for easier input management.
  • #151
yungman said:
I posted the error message right under the program

Yes, I know. I was trying to get you to actually read it and think about what it is telling you.

yungman said:
isn't the two say exact the same thing?

No.

int *ptr = &var; says "allocate a variable of type pointer to int and store the address of var there".

int *pptr = ptr; says "allocate a variable of type pointer to int and take the pointer that is already stored in the variable ptr and store it there as well".

int *pptr; *pptr = ptr; says "allocate a variable of type pointer to int; at the location the pointer stored in this variable points to, store the pointer that is already stored in the variable ptr".

See the difference?

Note that there are actually two things wrong with the last bit of code. Aside from the fact that it is mismatching types (you are trying to store a pointer in a variable of type int, since that is the type of variable that the pointer pptr points to), it is trying to store to an undefined location, since *pptr means "the int variable that pptr points to", but the pointer variable pptr doesn't point to any int variable yet.
 
  • Like
Likes yungman
Technology news on Phys.org
  • #152
Jarvis323 said:
Try to think about what's in the actual memory. Maybe work it out on paper.

You have an int variable, var (which is occupying 4 bytes somewhere in memory). You have two pointer to an int variables, ptr and pptr (which each are occupying 8 bytes somewhere in memory, assuming you have a 64 bit OS).

int * pptr; (on line 7) declares an uninitialized pointer to an int. Being uninitialized and unset, it has what you would call a garbage value (meaning you have no clue what bits might be there).

*pptr = ptr; (on line 8) dereferences pptr before assigning ptr, in this case meaning it takes the random garbage value that happened to be in those 8-bytes stored by pptr, considers it to contain the memory address of an int, follows it to the corresponding chunk of memory at that address, where it assumes there is some allocated place for a 4 byte signed integer to be, and then it tries to store the value of ptr (an 8 byte memory address) there. The types mismatch (int) vs (int*) and it finds it should throw an error. But if it did compile, it would be a memory corruption bug.

For example, you might have this in memory up to line 7:

bytes 1 - 4 : stores the value of var, which is 23
bytes 2 - 10 : stores the value of ptr, which is 1 (the address of var)
bytes 11-18 : stores the value of pptr, which is garbage (who knows what's there) but let's say it is 27
...
byte 27: some memory we don't know much about

Line 8 says: treat bytes 11:18 as if they encode an address to an int variable, go to that address and put the value of ptr (an int*) there. e.g. it is something like:

(int )(bytes 27-30) = (int*)(bytes 2-10)

In the first/correct version, the example goes like this:

bytes 1 - 4 : stores the value of var, which is 23
bytes 2 - 10 : stores the value of ptr, which is 1 (the address of var)
line 7 says: allocate an int * and store the value of ptr there. Then,
bytes 11-18 : stores the value of ptr, which is 1
Thank you so much, I am still reading this, I'll be back.

I kept reading the word "dereferencing", what is this mean? I read in the book, but it never explain this.

In the sentence highlighted in RED above, int *pptr declare it's a pointer pointing to an integer. Then it is NOT TRUE that pptr pointing to ptr as ptr is an address that is 8 byte!

Bottom line is address is 8bytes, int is 4 bytes, trying to store address in the space of an int will bomb the computer, so compiler will flag error. I'll be back.
 
Last edited:
  • #153
yungman said:
Bottom line is address is 8bytes, int is 4 bytes

That's not the primary issue. The primary issue is that "int" and "pointer to int" are different types. The compiler would give an error even if the in-memory size of both types were the same.
 
  • Like
Likes yungman
  • #154
PeterDonis said:
That's not the primary issue. The primary issue is that "int" and "pointer to int" are different types. The compiler would give an error even if the in-memory size of both types were the same.
thanks, I am getting it...slowly.
 
  • #155
yungman said:
I kept reading the word "dereferencing", what is this mean?

If the variable pptr stores a pointer to an int variable, then *pptr means "the int that the pointer pptr points to". The general idea of "look at the thing the pointer points to" is called dereferencing.
 
  • Like
Likes yungman
  • #156
PeterDonis said:
If the variable pptr stores a pointer to an int variable, then *pptr means "the int that the pointer pptr points to". The general idea of "look at the thing the pointer points to" is called dereferencing.
Thanks so much. I guess the meaning WRONG so far, I took it some kind of "de-referencing" which is like "not" referencing. That really throw me off also. I'm glad I asked as the word kept coming up.

So it's NOT true that *pptr =ptr as ptr is 8bytes. int *pptr only declare it points to an integer that is 4 byte.

I am getting it.
 
  • #157
yungman said:
So it's NOT true that *pptr =ptr

It's "not true" in the sense that the compiler will give an error, yes.

yungman said:
as ptr is 8bytes. int *pptr only declare it points to an integer that is 4 byte.

No. The problem is not the different in-memory sizes. The problem is that "int" and "pointer to int" are different types. As I said before, the compiler would give an error even if the in-memory sizes of both types were the same. For example, if you were compiling 32-bit code instead of 64-bit code, the size of a pointer and the size of an int would both be 4 bytes, but you would still get the same compiler error if you tried to assign a pointer to an int variable.
 
  • #158
yungman said:
Thanks so much. I guess the meaning WRONG so far, I took it some kind of "de-referencing" which is like "not" referencing. That really throw me off also. I'm glad I asked as the word kept coming up.

So it's NOT true that *pptr =ptr as ptr is 8bytes. int *pptr only declare it points to an integer that is 4 byte.

I am getting it.
One of the main problems is that while pptr is a variable for storing an address, that variable in this case isn't storing an address, it's storing garbage. Then you dereference it...

Anyways, what you should have done for it to be the same as the first/correct version is just pptr=ptr on line 8.
 
  • #159
Jarvis323 said:
while pptr is a variable for storing an address, that variable in this case isn't storing an address, it's storing a garbage. Then you dereference it

Yes, that's the second problem I referred to in post #151. The first problem is the type mismatch--trying to store a pointer in a variable that is of type int.
 
  • #160
I think it would be a good idea for the OP to take a pause and think about what a high level languange like C++ is for, noting that what it is NOT for is facilitating direct addressing of memory locations in a particlar hardware configuration and runtime instance.

The reason we use high level languages is abstraction. Abstraction enables us to write programs that do complicated things that are easier to write, quicker to debug and cheaper to maintain. With an object-oriented language like C++ we have a particular model of abstraction into classes which exhibit encapsulation, inheritance and polymorphism. This is what you need to learn, not pointers.

Sometimes in C++ it is necessary to use pointers, [Edited: but as soon as we do that we are no longer] but if we use them when we don't have to we are not using the power of a high level language and our code becomes harder to write, harder to debug and more expensive to maintain. We therefore only use pointers as a last resort.

For example in the real world you should almost never see a function that initializes an array that is passed to it as a parameter; this would be implemented with the array as a member variable (property) of an object initialized by a member function (method) of the object's class. I am afraid you have wasted hours of your own, and other peoples', time trying to understand how to do something that is irrelevant.

It is unfathomable to me that you are contemplating 'learning' C++ by skipping the chapters of the book on the high-level features of the language. You would learn much more about HLLs if you had skipped the chapter on pointers and moved on to classes.

There is a an alternative version of Gaddis's book which does exactly that; it has the suffix 'early objects' which is a much better way to learn IMHO.
 
Last edited:
  • #161
pbuk said:
I think it would be a good idea for the OP to take a pause and think about what a high level languange like C++ is for, noting that what it is NOT for is facilitating direct addressing of memory locations in a particlar hardware configuration and runtime instance.

The reason we use high level languages is abstraction. Abstraction enables us to write programs that do complicated things that are easier to write, quicker to debug and cheaper to maintain. With an object-oriented language like C++ we have a particular model of abstraction into classes which exhibit encapsulation, inheritance and polymorphism. This is what you need to learn, not pointers.

Sometimes in C++ it is necessary to use pointers, but as soon as we do that we are no longer using the power of a high level language and our code becomes harder to write, harder to debug and more expensive to maintain. We therefore only use pointers as a last resort.

For example in the real world you should almost never see a function that initializes an array that is passed to it as a parameter; this would be implemented with the array as a member variable (property) of an object initialized by a member function (method) of the object's class. I am afraid you have wasted hours of your own, and other peoples', time trying to understand how to do something that is irrelevant.

It is unfathomable to me that you are contemplating 'learning' C++ by skipping the chapters of the book on the high-level features of the language. You would learn much more about HLLs if you had skipped the chapter on pointers and moved on to classes.

There is a an alternative version of Gaddis's book which does exactly that; it has the suffix 'early objects' which is a much better way to learn IMHO.
I don't know, I mean polymorphism requires using pointers in C++. Writing copy constructors and such usually requires dereferencing a pointer. Interfacing with C libraries requires using pointers. Any kind of data structures course would require using them heavily (implementing lists, trees, etc.)
 
Last edited:
  • Like
Likes pbuk
  • #162
Jarvis323 said:
I don't know, I mean polymorphism requires using pointers in C++. Writing copy constructors and such usually requires dereferencing a pointer. Interfacing with C libraries requires using pointers. Any kind of data structures course would require using them heavily (implementing lists, trees, etc.)
Perhaps I did rather overstate my case against the importance of pointers and I have edited it accordingly, however I stand by my point that they are relatively less important than the concepts of OOP.

Jarvis323 said:
polymorphism requires using pointers in C++.
C:
#include <iostream>

class Shape {
  public:
    virtual float area() =0;
};

class Square: public Shape {
  private:
  float _side = 0;
  public:
  // Constructor.
  Square(float side) {
    _side = side;
  }
  float area() {
    return _side * _side;
  }
};

class Triangle: public Shape {
  private:
    float _base;
    float _height;
  public:
  // Constructor.
  Triangle(float base, float height) {
    _base = base;
    _height = height;
  }
  float area() {
    return 0.5 * _base * _height;
  }
};

int main() {
  std::cout << Triangle(1, 1).area() << std::endl;
  std::cout << Square(1).area() << std::endl;
}

Jarvis323 said:
Writing copy constructors and such usually requires dereferencing a pointer.
Yes, but before you write a copy constructor you need to learn what a constructor is!

Jarvis323 said:
Interfacing with C libraries requires using pointers.
Yes, but not all C++ programs call C libraries.

Jarvis323 said:
Any kind of data structures course would require using them heavily (implementing lists, trees, etc.)
Yes, but I don't need to know how and why to implement a red-black tree to use std::map.
 
Last edited:
  • #163
pbuk said:
C:
#include <iostream>

class Shape {
  public:
    virtual float area() =0;
};

class Square: public Shape {
  private:
  float _side = 0;
  public:
  // Constructor.
  Square(float side) {
    _side = side;
  }
  float area() {
    return _side * _side;
  }
};

class Triangle: public Shape {
  private:
    float _base;
    float _height;
  public:
  // Constructor.
  Triangle(float base, float height) {
    _base = base;
    _height = height;
  }
  float area() {
    return 0.5 * _base * _height;
  }
};

int main() {
  std::cout << Triangle(1, 1).area() << std::endl;
  std::cout << Square(1).area() << std::endl;
}
I'm not sure you can really call this an example of using polymorphism? I was thinking more in terms of this type of functionality, which supports passing a Triangle or Square to the same function, storing them both in the same container, etc.
C:
int main() {
Triangle t(1,1);
Shape * t = &t;
  std::cout << t->area() << std::endl;
}
I get your point and agree about the importance of abstraction though. I still like The Structure and Interpretation of Computer Programs as an introductory programming book because of how well it teaches abstraction, even though the use of a functional language makes it difficult for beginners.

https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-4.html
 
Last edited:
  • #164
I totally forgot to mention, I also get now that it's not just the size like trying to store 8bytes address in a 4 bytes integer space. It's the type difference also.

Ha ha, I even try
long int var;
*pptr = var;

It gave me an error because the TYPE is wrong.

Regarding of whether pointers are useful or not, I am just follow one chapter at a time. I don't judge, I am not at the stage to give an opinion. Just learn in order of the chapters. I just know this is the first confusing chapter that I need to stop and think, the others are quite easy and straight forward including strings in chapter 10 that I studied quite a portion from the other book. Just a lot of new names.

I know that high level languages are more abstract. BUT in my opinion as a hardware design engineer, You can NEVER forget what the programs are running on. I don't know whether you guys ever play with programming FPGA which you might think it's very similar to other programming languages. Man! Will you be screwed (pardon for my language) having the idea of removing from hardware. In VHDL or AHDL, if you don't know hardware, don't even touch it even though it looks to be a higher level language. I put this very strongly because I was the one that had to go in and fix it.
 
  • Like
Likes PeterDonis
  • #165
I still have question
C++:
#include <iostream>
using namespace std;
void getRNum(int**);
int main()
{
    int x = 20;
    int* pNumber;
    pNumber = &x;
    cout << " Before getRNum, address of pNumber = " << &pNumber << "\n\n";
    getRNum(&pNumber);
    cout << "     Return from function, &pNumber = " << &pNumber << "       *pNumber = " << *pNumber << "\n\n";
    return 0;
}
void getRNum(int** pArr)
{
    int y = 10;
    int* ptr = &y;
    cout <<" Address of y = " << &y << "    Address of ptr = " << ptr << "    *ptr = " << *ptr << "     y = " << y << "\n\n";
    pArr = &ptr;
    cout << " *pArr = " << *pArr << "    Address of ptr = " << ptr << "\n\n";
    cout << " pArr = " << pArr;
}
Compile error Listing 7.2.jpg


I made a copy of the output. you can see the address of pArr did not pass back from function getRNum to main. also I printed out *pNumber in main, it still have the value of 20 from the original x, not the value of y = 10 in getRNum.

Is it because when exiting the function getRNum, all the address and y are destroyed? the reason one can pass pointer of array is because array is not passed to function, it's only the reference being passed and the array is not destroy after exiting from function.

Also, I put pptr=&ptr, but pptr is not equal to address of ptr which is 007FFC7C. Why?

Thanks
 
Last edited:
  • #166
yungman said:
the address of pArr did not pass back from function

That's right, because pArr is a local variable inside the function and never gets returned to the caller. So setting its value inside the function does nothing as far as the caller is concerned. If you want to write the value of some local variable into the variable that is pointed to by pArr, you have to put *pArr on the left side of the = in the statement.

You are still confused about what your code is actually doing, vs. what you apparently intend for your code to do. Previously, you wanted the getRNum function to write a pointer to an int into a pointer variable in main; to do that, you needed to pass a pointer to a pointer to an int as a parameter to getRNum.

Now, it appears that you want the getRNum function to write an int into an int variable in main. If that's all you want to do, you don't need the extra layer of pointers. You can just pass an int * parameter to getRNum, so its signature could be getRNum(int *pArr), and the function call could be getRNum(&x);, and inside getRNUm you would do *pArr = y, which writes the value of the local variable y into the int variable that is pointed to by pArr.
 
  • Like
Likes yungman
  • #167
yungman said:
Is it because when exiting the function getRNum, all the address and y are destroyed? the reason one can pass pointer of array is because array is not passed to function, it's only the reference being passed and the array is not destroy after exiting from function.
The y and ptr variables in getRNum() are local variables that are allocated on the stack -- they are created on entry to getRNum(), and are destroyed on exit from this function.

When a function takes an array parameter, what is being passed is the address of the first element of the array.

Because C++ functions can have pointer parameters or reference parameters, it's confusing to use the term "reference" in both situations.

yungman said:
Also, I put pptr=&ptr, but pptr is not equal to address of ptr which is 007FFC7C. Why?
I think Peter already answered your question, but there is no variable named pptr in your program.
 
  • Like
Likes yungman
  • #168
PeterDonis said:
Now, it appears that you want the getRNum function to write an int into an int variable in main. If that's all you want to do, you don't need the extra layer of pointers. You can just pass an int * parameter to getRNum, so its signature could be getRNum(int *pArr), and the function call could be getRNum(&x);, and inside getRNUm you would do *pArr = y, which writes the value of the local variable y into the int variable that is pointed to by pArr.
To elaborate on what @PeterDonis said, here's what he's talking about.
C++:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void getNum(int *);
int main()
{
    int num = 23;
    cout << "Before call to getNum(), var == " << num << endl;
    getNum(&num);    
    cout << "After call to getNum(), num == " << num << endl;    
}

void getNum(int * pVal)
{
    cout << "Enter an integer value: ";
    cin >> *pVal;
}
The argument of getNum() is the address of num in main(). The input statement in getNum() dereferences pVal, thereby storing the value that was entered into the memory location of num. The output statements in main() show the values of num before and after the call to getNum().

pVal is an address. By dereferencing pVal (i.e., by prepending an asterisk as in *pVal), we get read or write access to the address that pVal represents.
 
  • Like
Likes yungman
  • #169
PeterDonis said:
That's right, because pArr is a local variable inside the function and never gets returned to the caller. So setting its value inside the function does nothing as far as the caller is concerned. If you want to write the value of some local variable into the variable that is pointed to by pArr, you have to put *pArr on the left side of the = in the statement.

You are still confused about what your code is actually doing, vs. what you apparently intend for your code to do. Previously, you wanted the getRNum function to write a pointer to an int into a pointer variable in main; to do that, you needed to pass a pointer to a pointer to an int as a parameter to getRNum.

Now, it appears that you want the getRNum function to write an int into an int variable in main. If that's all you want to do, you don't need the extra layer of pointers. You can just pass an int * parameter to getRNum, so its signature could be getRNum(int *pArr), and the function call could be getRNum(&x);, and inside getRNUm you would do *pArr = y, which writes the value of the local variable y into the int variable that is pointed to by pArr.
Thanks for the reply, I am not confused, I just want to simplify the program and still get to my goal to pass pointer-to-pointer to the function. I just want to verify things.

I actually have a program exactly like what you describe, passing int* as parameter.
C++:
//Passing pointer to function
#include <iostream>
using namespace std;
void getRNum(int*);
int main()
{
    int x;
    int* pNumber;
    pNumber = &x;//initializing pNumber to some address
    cout << " address of x = " << &x << "   Before getRNum, pNumber = " << pNumber << " *pNumber = " << *pNumber << "\n\n";
    getRNum(pNumber);
    cout << " After getRNum, pNumber = " << pNumber << " *pNumber = " << *pNumber << "\n\n";
    return 0;
}
void getRNum(int* pArr)
{
    *pArr = 10;// assign *pArr = 10
    cout << " pArr = " << pArr << "\n\n";
}

This one is exactly what you describe. Yes, for pointer to integer, I don't need int **pptr at all.

It seems that int **pptr is only of limited use, mainly to pass an array from main to function and get the result back. Array is only an address like array Ar[size], Ar is the address of Ar[0]. So when you pass array to function, you really pass &Ar to the function. So if you want pointer to Ar, you have to use int**ptr = &Ar.
 
  • #170
Mark44 said:
To elaborate on what @PeterDonis said, here's what he's talking about.
C++:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void getNum(int *);
int main()
{
    int num = 23;
    cout << "Before call to getNum(), var == " << num << endl;
    getNum(&num);   
    cout << "After call to getNum(), num == " << num << endl;   
}

void getNum(int * pVal)
{
    cout << "Enter an integer value: ";
    cin >> *pVal;
}
The argument of getNum() is the address of num in main(). The input statement in getNum() dereferences pVal, thereby storing the value that was entered into the memory location of num. The output statements in main() show the values of num before and after the call to getNum().

pVal is an address. By dereferencing pVal (i.e., by prepending an asterisk as in *pVal), we get read or write access to the address that pVal represents.
Thank you, I understand now. The difference between yours and my program is you actually pass &num( address of num) to the function. You use the local pointer pVal to change the value of num, which, is in main. So even after exiting getNum function, pVal is destroyed, the change in the content of num still there.

In my case, I try to pass pointer from getNum back to main. But when getNum is closed, pointer is destroy and so is the value of y. So nothing is changed.

thanks.
 
  • #171
It is funny, I have been struggling with the pointers and pointer to pointer for over a day, I was so confused. BUT all of a sudden after going through the response here slowly, it is like crystal clear to me!
1) That you can ONLY assign the SAME TYPE of values to the pointers, that is you can ONLY assign ADDRESS of variable/constant to a pointer eg. int *ptr; ptr = &var; where var can be int, double, const, char etc.

2) You can ONLY assign address of a POINTER to int**pptr, not even an address of variables. eg. int**pptr; pptr = &ptr;

This little program sum up what my understanding:
C++:
//experiment pointers
#include <iostream>
using namespace std;

int main()
{
    int x = 10;
    int* ptrx;// initiate pointer ptrx
    ptrx = &x;// *ptrx = x = 10
    cout << " ptrx = " << ptrx << "     address of x = " << &x << "    x = " << x << "     *ptrx = " << *ptrx << "\n\n";
    int** pptrx;// initiate pointer to pointer pptrx
    pptrx = &ptrx;//pptrx pointing to ptrx
    cout << " address of pptrx = " << pptrx << "     *pptrx = " << *pptrx << "     **pptrx = " << **pptrx << "\n\n";
    return 0;
}
//    ptrx = 0135F97C     address of x = 0135F97C                    x = 10     *ptrx = 10

//    address of pptrx = 0135F970          *pptrx = 0135F97C                 **pptrx = 10

I copy the output in the cmd and put them in line 16 and line18 to summarize what I learn.

Thanks for all your patience.
 
  • #172
yungman said:
BUT all of a sudden after going through the response here slowly, it is like crystal clear to me!
1) That you can ONLY assign the SAME TYPE of values to the pointers, that is you can ONLY assign ADDRESS of variable/constant to a pointer eg. int *ptr; ptr = &var; where var can be int, double, const, char etc.
No, I don't think it is crystal clear to you. If it were crystal clear, you wouldn't be saying "where var can be int, double, const, char etc."

In your bolded example, var has to be type int. It can't be double, float, long, or any other type that isn't of type int. Also, const isn't a type -- it has to be a modifier of some type.
 
  • #173
Mark44 said:
No, I don't think it is crystal clear to you. You still don't seem to be getting it.
In your bolded example, var has to be type int. It can't be double, float, long, or any other type that isn't of type int. Also, const isn't a type -- it has to be a modifier of some type.
Address is always integers, it's never been a question, it's the type. It's never been clearer.

this is common sense with knowledge of hardware. That's the reason I feel it's so important to put hardware into perspective, not just treating as a high level language. You don't have a fraction of an address line in hardware.
 
  • #174
yungman said:
Address is always integers, it's never been a question, it's the type. It's never been clearer.
You've been told this several times. An address, currently, is an integer, but its type is not int! Until you come to terms with this, you aren't going to understand pointers.

Also, and I've said this before, addresses in the past were not integers.
yungman said:
this is common sense with knowledge of hardware. That's the reason I feel it's so important to put hardware into perspective, not just treating as a high level language.
Hardware and high-level language are two entirely different things.
 
  • #175
yungman said:
I am not confused

Yes, you are. If you weren't, you wouldn't have asked the questions you asked in post #165.
 
  • #176
Mark44 said:
You've been told this several times. An address, currently, is an integer, but its type is not int! Until you come to terms with this, you aren't going to understand pointers.

Also, and I've said this before, addresses in the past were not integers.
Hardware and high-level language are two entirely different things.
This is a language most commonly used in firmware in hardware level.

When I said address is an integer, I meant it is a whole number, not a double. I know *ptr point to an address. I don't mean *ptr = x where x is an integer.

Or else why define int **pptr; and pptr = &ptr ? Maybe I should say address is a whole number like integer.
 
  • #177
PeterDonis said:
Yes, you are. If you weren't, you wouldn't have asked the questions you asked in post #165.
#165 has nothing to do with integer, I just want to verify the data and pointer are destroy after exiting the function.
 
  • #178
yungman said:
This is a language most commonly used in firmware in hardware level.
I don't see how this is relevant to the discussion here about pointers.
yungman said:
When I said address is an integer, I meant it is a whole number, not a double.
That's not what you said in post #171, copied below

yungman said:
you can ONLY assign ADDRESS of variable/constant to a pointer eg. int *ptr; ptr = &var; where var can be int, double, const, char etc.

The only legitimate type for var is int, not double, char, or anything else.
 
  • #179
yungman said:
This is a language most commonly used in firmware in hardware level.

Not at all. Both C++ and C are used for all kinds of projects, many of them having no direct hardware interaction at all. The interpreters for high level languages like Python are written in C.
 
  • #180
yungman said:
#165 has nothing to do with integer, I just want to verify the data and pointer are destroy after exiting the function.

And you did that incorrectly, because you are still confused about how variable types and pointer types work in C and C++, because you are still hung up on actual memory addresses being "integers". Sure, they are "integers" in the sense that they are discrete--there are no fractions of address lines, as you say--but they are not "integers" as far as C and C++ are concerned, because pointers and integers are different types, and pointers to integers are a different type from pointers to floats, which are a different type from pointers to chars, etc.

Do you want to get unconfused or not?
 
  • #181
I am really not good in the terms and all that. Let me just say what I understand. If this still have problem, then I have to learn more:

1) int*ptr is a pointer that can only point to an address of an integer variable. ptr is the address, you can do ptr =&x where x is an integer. for double, const, you use: double dbt; double *ptr=&dbt etc.

2) for pointer to pointer. use int**pptr. pptr can only be address of a pointer. pptr cannot equal to &x. It's ok for pptr=&ptr. eg. int*ptr; int**pptr; pptr=&ptr; &ptr is the address of ptr.

I don't know why they use int**pptr. It is not ok to point to an integer variable. pptr has to be address of a pointer like ptr. Like it is legal to wtite pptr=&ptr.The confusion is I said address is an integer. This is NOT saying address is classified as int as you think in C++. All I am saying is address has to be a whole number, no fraction. It cannot even be -ve integer. You know there is a clear meaning of INTEGER outside of C++, that's what I was using for, not in terms of int in C++. Integer is just a whole number with no fraction, not int in C++.Don't read the other posts as I might said things wrong in terms of using names. If there is anything wrong with what I said here, let me know. to me, this is crystal clear now.
 
  • #182
yungman said:
int*ptr is a pointer that can only point to an address of an integer variable.

Yes.

yungman said:
for pointer to pointer. use int**pptr

No. For pointer to pointer to an int variable, use int** pptr. For a pointer to a pointer to a different type of variable, you would have to use the different type instead of int; so, for example, for a pointer to a pointer to a double variable, it would be double** pptr.

yungman said:
I don't know why they use int**pptr.

Because that is how to say "pointer to pointer to int" in C/C++. Each asterisk represents "pointer to". For a pointer to a pointer to some other type, you would say it differently, as above.

yungman said:
All I am saying is address has to be a whole number, no fraction.

We all know that. Continuing to belabor it as thought it were something the rest of us haven't grasped adds nothing whatever to the discussion; all it does is make us think that you haven't yet grasped the difference between "whole number, not a fraction" and "the C/C++ integer type".
 
  • Like
Likes yungman
  • #183
@yungman, there's no need to feel down
I said @yungman, pick yourself off the ground
I said @yungman, pointers won't make you frown
There's no need to be un-hap-py

It's fun to code using G-N-U C
It's fun to code using G-N-U C

Sorry. Needed to get that out of my system.
 
  • Like
Likes yungman
  • #184
PeterDonis said:
Yes.
No. For pointer to pointer to an int variable, use int** pptr. For a pointer to a pointer to a different type of variable, you would have to use the different type instead of int; so, for example, for a pointer to a pointer to a double variable, it would be double** pptr.
Because that is how to say "pointer to pointer to int" in C/C++. Each asterisk represents "pointer to". For a pointer to a pointer to some other type, you would say it differently, as above.
We all know that. Continuing to belabor it as thought it were something the rest of us haven't grasped adds nothing whatever to the discussion; all it does is make us think that you haven't yet grasped the difference between "whole number, not a fraction" and "the C/C++ integer type".
Ah, I see. If *ptr is an int. The pointer to pointer **pptr that point to ptr HAS to be int**pptr;. NOT THAT it is pointing to an int, just to acknowledge that it is pointing to a pointer that points to an int.

Thank you. That makes a whole lot of sense now. Again, the chapter say nothing about this and leave me hanging. this chapter is almost as bad as the other book I used to use.

I just want to clarify about what I said "integer". I knew very well address is an address. I just described address as whole number and the best fit term is just integer as common integer.
 
  • #185
Vanadium 50 said:
@yungman, there's no need to feel down
I said @yungman, pick yourself off the ground
I said @yungman, pointers won't make you frown
There's no need to be un-hap-py

It's fun to code using G-N-U C
It's fun to code using G-N-U C

Sorry. Needed to get that out of my system.
I was pulling hair for a day or so, but now I am happy and have fun again. Just kept at it, last night, it was a lightbulb moment, it's just that simple. Thanks to the people here, no thanks to the book.

What is G-N-U C?
 
  • #186
yungman said:
If *ptr is an int. The pointer to pointer **pptr that point to ptr HAS to be int**pptr;. NOT THAT it is pointing to an int, just to acknowledge that it is pointing to a pointer that points to an int.

Yes.
 
  • Like
Likes yungman
  • #187
PeterDonis said:
Yes.
I am happy camper now. Now I can move on. BUT, first, I am going to take it easy today, have a nice drink and relax! I was pulling hair for the last day! It's like what's wrong with me, it's right in front of my face and I just cannot connect them together.
 
  • #188
I am still experimenting with pointer to pointer. I don't understand why this program can still maintain the value of the local variable in the function after exiting:
C++:
// passing reference to pointer to function 2
#include <iostream>
using namespace std;void changeRvalue(int*&);

int main()
{
    int var = 23;
    int* ptr;
    ptr = &var;
    cout << " Before passing to function, *ptr = " << *ptr << "\n\n";
    changeRvalue(ptr);
    cout << " After passing to function, *ptr = " << *ptr << "\n\n";
    return 0;
}
void changeRvalue(int*& pp)
{
    int glov = 52;
    pp = &glov;
}

As you see line20, int glov = 52 is local variable in function changeRvalue. But when return to main and display *ptr, I still get *ptr = 52.

I thought the value would be destroyed after exiting the function?

Thanks
 
  • #189
yungman said:
I am still experimenting with pointer to pointer. I don't understand why this program can still maintain the value of the local variable in the function after exiting:

I thought the value would be destroyed after exiting the function?

Thanks

using a reference to a local variable is "undefined behaviour". https://en.wikipedia.org/wiki/Undefined_behavior
There are no guarantees about what will happen at all. non-C compilers won't allow this sort of thing.

After returning from your function the local variable probably won't be overwritten, but you should really not rely on this. If you use another function before you use *ptr you will likely overwrite this value.

I added cout << 1.0f; after the call to changevalue(), and I get *ptr = 9436264 (different values every time)
If you compile in release mode however, you still get 52 out. The compiler sees that you modify the same variable and just sends the number 52 to the output, so there's nothing on the stack to get overwritten.
 
  • Like
Likes yungman
  • #190
willem2 said:
using a reference to a local variable is "undefined behaviour". https://en.wikipedia.org/wiki/Undefined_behavior
There are no guarantees about what will happen at all. non-C compilers won't allow this sort of thing.

After returning from your function the local variable probably won't be overwritten, but you should really not rely on this. If you use another function before you use *ptr you will likely overwrite this value.

I added cout << 1.0f; after the call to changevalue(), and I get *ptr = 9436264 (different values every time)
If you compile in release mode however, you still get 52 out. The compiler sees that you modify the same variable and just sends the number 52 to the output, so there's nothing on the stack to get overwritten.
So just don't count on it. It just so happen the value in glov is not erased only, no guaranty.

Thanks
 
  • #191
I am still working on passing a reference of a pointer to function. I learn there are two ways to do that and are shown in the program below. I just want to verify I am correct:
C++:
#include <iostream>
using namespace std;
void changeRvalueA(int*&);// function receives a pointer of an address
void changeRvalueB(int**);// function receives a pointer to pointer
int main()
{
    int var = 23;
    int* ptrA;// pointer whose address to be passed
    ptrA = &var;// pointer pointing to address of var
    changeRvalueA(ptrA);// passing address of pointer ptrA
    cout << "     ptrA = " << ptrA <<  "\n\n";

    int* ptrB;// declare a pointer ptr
    int** pptrB = &ptrB;
    ptrB = &var; //ptr pointing to address var
    changeRvalueB(pptrB);// passing pointer of pointer pptrB.
    cout << "     pptrB = " << pptrB << "\n\n";
    return 0;
}
void changeRvalueA(int*& ppA)// receiving address for pointer ppA
{    cout << " ppA = " << ppA;    }

void changeRvalueB(int** ppB)// receiving pointer to pointer ppB.
{    cout << " ppB = " << ppB;    }

// ppA = 00FDF854  ptrA = 00FDF854        ppB = 00FDF83C  pptrB = 00FDF83C

As you can see, I have two separate ways, I labelled the first with names ended in "A", the second with names ended in "B". They look the same, but the idea is very different.

In A, The program passes the ADDRESS of the pointer ptrA. This is similar to passing by reference for variables to function.

In B, The program passes the pointer to pointer pptrB to the function. You can skip using pptrB by passing &ptrB instead in main. This is to save a line to declare pptrB = &ptrB.

I copied the result of running of the two in line 26.

Let me know whether I am correct in my analysis. If both are right, I much prefer using method A because it is exactly the same as passing variables by reference where only the address of the variable is passed to the function.

Thanks
 
  • #192
yungman said:
I am still working on passing a reference of a pointer to function. I learn there are two ways to do that and are shown in the program below. I just want to verify I am correct:
C++:
#include <iostream>
using namespace std;
void changeRvalueA(int*&);// function receives a pointer of an address
void changeRvalueB(int**);// function receives a pointer to pointer
int main()
{
    int var = 23;
    int* ptrA;// pointer whose address to be passed
    ptrA = &var;// pointer pointing to address of var
    changeRvalueA(ptrA);// passing address of pointer ptrA
    cout << "     ptrA = " << ptrA <<  "\n\n";

    int* ptrB;// declare a pointer ptr
    int** pptrB = &ptrB;
    ptrB = &var; //ptr pointing to address var
    changeRvalueB(pptrB);// passing pointer of pointer pptrB.
    cout << "     pptrB = " << pptrB << "\n\n";
    return 0;
}
void changeRvalueA(int*& ppA)// receiving address for pointer ppA
{    cout << " ppA = " << ppA;    }

void changeRvalueB(int** ppB)// receiving pointer to pointer ppB.
{    cout << " ppB = " << ppB;    }

// ppA = 00FDF854  ptrA = 00FDF854        ppB = 00FDF83C  pptrB = 00FDF83C

As you can see, I have two separate ways, I labelled the first with names ended in "A", the second with names ended in "B". They look the same, but the idea is very different.

In A, The program passes the ADDRESS of the pointer ptrA. This is similar to passing by reference for variables to function.

In B, The program passes the pointer to pointer pptrB to the function. You can skip using pptrB by passing &ptrB instead in main. This is to save a line to declare pptrB = &ptrB.

I copied the result of running of the two in line 26.

Let me know whether I am correct in my analysis. If both are right, I much prefer using method A because it is exactly the same as passing variables by reference where only the address of the variable is passed to the function.

Thanks

Have you learned about references in C++ yet? I don't think a reference in C++ is good to think of as an ADDRESS. In fact it would be much more correct to think of a pointer as an address. Rather, in (A) you are passing a reference (not address) to a pointer. In (B) you are passing a pointer to a pointer (which can be thought of as passing the address of an address).

This might be confusing because it seems you've been calling pointers references up to now (and there is some room for confusion about the difference in C++ anyways). It may also be confusing about the multiple meanings of symbols * and & in different contexts.

https://en.cppreference.com/w/cpp/language/reference

My feeling is in basic agreement with pbuk's post #160. The stuff you're doing now (the way you're using pointers) is more a C style of programming, and generally considered bad practice/style in C++.

Also as pbuk was alluding to, once you learn about classes and object oriented programming, if you start trying to write good code, you'll probably want to use a completely different approach to allocating memory. I usually follow RAII, which is an idiom to follow in order to better organize your use of manually dynamically allocated memory and to avoid making mistakes and causing bugs.

https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization

Anyway, once you understand pointers and references, then you should probably move on because you really have barely scratched the surface of C++, and mostly haven't even seen the ++ parts of C++ yet.

That's just my 2 cents.
 
Last edited:
  • Like
Likes yungman and pbuk
  • #193
yungman said:
C++:
void changeRvalueA(int*& ppA)// receiving address for pointer ppA
{    cout << " ppA = " << ppA;    }
In A, The program passes the ADDRESS of the pointer ptrA.
No, that's not what you're doing. the function parameter is of type reference to pointer to int. In all the C++ books I've seen over the years, I've never seen a single function with a parameter like this, which is a weird mixture of C notation (pointer parameter) and C++ (reference parameter). Since it's not shown in books, it's probably not a good thing to put in a real program.

Keep in mind that the & operator is used for three different things, so can be easily confused.
  1. Bitwise AND operator
    The expression 1 & 4 evaluates to 0.
  2. Address-of operator
    If var is declared as an int, the expression &var evaluates to the address of the first byte of the memory that contains var.
  3. Reference operator
    If a function's header is void func(int & val), this means that val is another name for whatever actual argument is used in the call to func().
As @Jarvis323 pointed out, your misuse of terminology by referring to pointers as references is preventing you from understanding that they aren't the same thing.

Before messing around with double indirection or combinations of pointers and references, spend some time working with single indirection parameters and reference parameters, separately.

Here's an example that shows the difference between a function with a pointer parameter and another with a reference parameter. Take a close look at the difference in how the two functions are called.
C++:
#include <iostream>
using std::cout;

void FuncPtr(int *);    // Prototype for a function with a pointer parameter
void FuncRef(int &);   // Prototype for a function with a reference parameter

int main()
{
    int x = 3;
    int y = 5;

    FuncPtr(&x);    // Note the difference in the semantics for the two functions
    FuncRef(y);

    cout << "New value for x: " << x << '\n';
    cout << "New value for y: " << y << '\n';
}

void FuncPtr(int* argPtr)
{
    *argPtr = 10;
}

void FuncRef(int & argRef)
{
    argRef = 10;
}
Although the variables x and y start off with different values, they both end up with 10 as their final value.
 
  • Like
Likes yungman
  • #194
Thanks Mark
Your example is exactly what I have been looking at. Yes, I went through the book, & in this case is NOT address, just a symbol for saying it is a reference variable.

But what I point out in my post is still valid even though my reasoning of( int &) is wrong, it's not passing the address.

Still case A in my program is passing by reference, case B is passing the pointer to pointer.

Thanks
 
  • #195
Jarvis323 said:
Have you learned about references in C++ yet? I don't think a reference in C++ is good to think of as an ADDRESS. In fact it would be much more correct to think of a pointer as an address. Rather, in (A) you are passing a reference (not address) to a pointer. In (B) you are passing a pointer to a pointer (which can be thought of as passing the address of an address).

This might be confusing because it seems you've been calling pointers references up to now (and there is some room for confusion about the difference in C++ anyways). It may also be confusing about the multiple meanings of symbols * and & in different contexts.

https://en.cppreference.com/w/cpp/language/reference

My feeling is in basic agreement with pbuk's post #160. The stuff you're doing now (the way you're using pointers) is more a C style of programming, and generally considered bad practice/style in C++.

Also as pbuk was alluding to, once you learn about classes and object oriented programming, if you start trying to write good code, you'll probably want to use a completely different approach to allocating memory. I usually follow RAII, which is an idiom to follow in order to better organize your use of manually dynamically allocated memory and to avoid making mistakes and causing bugs.

https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization

Anyway, once you understand pointers and references, then you should probably move on because you really have barely scratched the surface of C++, and mostly haven't even seen the ++ parts of C++ yet.

That's just my 2 cents.
Thanks

I thought it's beneficial to learn everything out of each chapter and learn all the possibility. I have no way to predict what's in the future chapters.

I understand where you come from. I feel I have milked the pointers close to the end already and I started looking ahead to the next two chapters. Chapter 11 is on Structure, I read a few pages and I almost felt like kicking myself. I spent a lot of effort in the early chapters to make a nice printout so I have names, tittle, numbers and all nicely, I went through hoops to get multiple arrays to sync together to get the printout that looked nice. That's what the Structure is all about...combining different types of things together in one array or whatever you want to call it!

If I knew that, I would not spend so much time before on this. The problem is where do I draw the line? All I can do is learning one chapter at a time and try to get the max out of it. That's the disadvantage of not going to a class that the professor literally tells you what to study and what not.

thanks
 
  • #196
yungman said:
But what I point out in my post is still valid even though my reasoning of( int &) is wrong, it's not passing the address.
For that you should use double indirection; i.e., a pointer to a pointer to some type.
Here's a simple example:
C++:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void passAddr(int **);
int main()
{
    int List[] = { 1, 3, 5, 7, 9 };
    int * ptr = List;                   // Initialize ptr with the address of List, which is itself a kind of pointer.
    
    cout << "Before call to passAddr(), *ptr == " << *ptr << endl;
    passAddr(&ptr);                // Pass the address of the pointer to the first element of the array.
    cout << "After call to passAddr(), *ptr == " << *ptr << endl;
}

void passAddr(int ** pptr)
{
    *pptr += 2;                        // pptr is a pointer to a pointer to an int
}
List is a pointer constant. In essence the type of List is int *.
The 2nd line in main() defines ptr and initializes it to the address that List represents. At this point, ptr contains the address of the first element in the array, 1.
The 4th line calls passAddr(), passing the address of ptr as its parameter.

In the code for passAddr(), we dereference pptr, which gives us access to the address of List, and we increment pptr by 2. The way pointer addition works is that the result is scaled by the type being pointed to (int), which means that we get an address 8 bytes higher (2 * 4 bytes for an int).
After returning to main(), ptr now points to the item at index 2 in the array, namely 5.

Program output:
Code:
Before call to passAddr(), *ptr == 1
After call to passAddr(), *ptr == 5

yungman said:
That's what the Structure is all about...combining different types of things together in one array or whatever you want to call it!
A struct (C and C++ keyword) is not the same as an array. A struct is a user-defined collection of possibly different types. In an array, all of the elements are exactly the same type.
 
  • Like
Likes yungman
  • #198
Mark44 said:
For that you should use double indirection; i.e., a pointer to a pointer to some type.
Here's a simple example:
C++:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

void passAddr(int **);
int main()
{
    int List[] = { 1, 3, 5, 7, 9 };
    int * ptr = List;                   // Initialize ptr with the address of List, which is itself a kind of pointer.
 
    cout << "Before call to passAddr(), *ptr == " << *ptr << endl;
    passAddr(&ptr);                // Pass the address of the pointer to the first element of the array.
    cout << "After call to passAddr(), *ptr == " << *ptr << endl;
}

void passAddr(int ** pptr)
{
    *pptr += 2;                        // pptr is a pointer to a pointer to an int
}
List is a pointer constant. In essence the type of List is int *.
But List[] is declared as int with initial value only, how can it be pointer constant? I don't get List is a pointer as it's not declared as int*List. I thought there's a difference between ptr where it's declare as int*ptr. I know *ptr = List.
Mark44 said:
The 2nd line in main() defines ptr and initializes it to the address that List represents. At this point, ptr contains the address of the first element in the array, 1.
The 4th line calls passAddr(), passing the address of ptr as its parameter.
This is where I am confused. *ptr=List=&List[0] which is the starting address of List[]. ptr is not equal to &List[0]. passAddr() passing the ADDRESS of ptr in line 4 in main. BUT in the function definition: void passAddr(int**); that means it is passing a pointer to pointer variable ( like int**pptr). But in main, it pass as &ptr, the address of ptr. they are not the same type even thought at the end, it is the same. Can you explain?
Mark44 said:
In the code for passAddr(), we dereference pptr, which gives us access to the address of List, and we increment pptr by 2. The way pointer addition works is that the result is scaled by the type being pointed to (int), which means that we get an address 8 bytes higher (2 * 4 bytes for an int).
After returning to main(), ptr now points to the item at index 2 in the array, namely 5.

Program output:
Code:
Before call to passAddr(), *ptr == 1
After call to passAddr(), *ptr == 5

A struct (C and C++ keyword) is not the same as an array. A struct is a user-defined collection of possibly different types. In an array, all of the elements are exactly the same type.
Actually I prefer to pass pointer as reference ( or pass reference pointer, I still not quite sure) to function. This is more in line with passing any variable as reference to function by declaring void func(int&). It is easier than func(int**).

I have not read Structure, I don't know the naming or anything, just know it can put different types together so I don't have to deal and sync all different arrays together.

Thanks
 
  • #199
jtbell said:
In connection with these threads about learning C++, some of you all might be interested in seeing the book that I taught C++ out of, years ago. I've posted about it just now in the textbooks forum:

https://www.physicsforums.com/threads/old-but-good-c-textbook-available-for-free.992947/
I read the first post in your link, that's kind of the reason I spend extra effort in pointers as you said it's relate to data structure in the advanced class. I also put in extra effort in creating and read/write to files stored on hard disk/flash memory, anything to do with data transport and storage. Actually my book by Gaddis does NOT even go into pointer to pointer or reference pointers. It just declare int func() to return the int pointer. I insisted in learning passing pointer as reference and/or pointer to pointer. It's only two extra days, might be worth my time in the long run...at least that's how I think.

I might be wrong here, there is always a clever or dumb way to write a program. A lot of people put a lot of effort in writing clever lines. I believe as long as I get there, so if my program looks dumb, as long as I am there, who cares! BUT, if I don't know how to manage data, display data, manipulate data, I am done. Dumb programming might cause a few extra lines, but so what in the big picture? Important thing to me is how to make it modular, passing parameters cleanly, clean flow and most important...it works.
 
  • #200
yungman said:
I don't get List is a pointer

List has type "array of int", which the compiler treats as a pointer to the initial item in the array, so it's the same type to the compiler as "pointer to int", so it can be assigned to a variable of that type, such as ptr. The difference is that the address List points to can't be changed--it always points to the first int in the array. Whereas the address that ptr points to can be changed, by assigning some other address to it, as long as that address points to an int. So assigning to ptr a pointer to some element in the array of ints other than the first one is fine.
 
  • Like
Likes yungman

Similar threads

Replies
7
Views
2K
Replies
6
Views
2K
Replies
5
Views
2K
Replies
75
Views
6K
Replies
9
Views
2K
Replies
6
Views
4K
Back
Top