How to appropriately use pointers in C++ functions? - c++

I'm trying to get the hang of pointers and addresses in C++ and am having trouble with functions with changing parameters.
The code below is writing Loop run #1. in an infinite loop, instead of incrementing the value foo.
My question is: What is the issue with this code here?
#include <iostream>
void Statement(int *foo) {
std::cout << "Loop run #" << *foo << ". ";
foo++;
}
int main() {
int foo = 1;
for (;;) {
Statement(&foo);
}
}

You're incrementing a copy of the pointer itself, not what it points to. You probably meant:
(*foo)++;
This still won't fix the infinite loop though because you have nothing to stop it with.

Your issue is that you're incrementing the pointer, not the pointed-to data.
replace
foo++
with
(*foo)++
to increment the pointed-to value.

If I have understood correctly what you are trying to do then the function should be declared the following way as it is shown in the demonstrative program
#include <iostream>
void Statement(int *foo) {
std::cout << "Loop run #" << *foo << ". ";
++*foo;
}
int main() {
int foo = 1;
for (; ; ) {
Statement(&foo);
}
}
That is in an infinite loop you are trying to output incremented value of foo.
In this case you have increment the value itself pointed to by the pointer like
++*foo
If you want to limit loop iterations then you can use for example an object of the type unsigned char and define the loop the following way
#include <iostream>
void Statement( unsigned char *foo) {
std::cout << "Loop run #" << int( *foo ) << ". ";
++*foo;
}
int main() {
unsigned char foo = 1;
for (; foo ; ) {
Statement(&foo);
}
}

Related

Memory fault when print *pointer

Why do I have a memory fault in the below code? How do I fix it?
I want to read the progress of the outside function.
But I only get the output get_report_progress:100
#include <iostream>
int* int_get_progress = 0;
void get_progress(int* int_get_progress)
{
int n = 100;
int *report_progress = &n;
int_get_progress = report_progress;
std::cout << "get_report_progress:" << *int_get_progress <<std::endl;
}
int main()
{
get_progress(int_get_progress);
std::cout << "main get process:" << *int_get_progress << std::endl;
return 0;
}
Your global int_get_progress variable is a pointer that is initialized to null. You are passing it by value to the function, so a copy of it is made. As such, any new value the function assigns to that pointer is to the copy, not to the original. Thus, the global int_get_progress variable is left unchanged, and main() ends up deferencing a null pointer, which is undefined behavior and in this case is causing a memory fault.
Even if you fix the code to let the function update the caller's pointer, your code would still fail to work properly, because you are setting the pointer to point at a local variable that goes out of scope when the function exits, thus you would leave the pointer dangling, pointing at invalid memory, which is also undefined behavior when that pointer is then dereferenced.
Your global variable (which doesn't need to be global) should not be a pointer at all, but it can be passed around by pointer, eg:
#include <iostream>
void get_progress(int* p_progress)
{
int n = 100;
*p_progress = n;
std::cout << "get_report_progress:" << *p_progress << std::endl;
}
int main()
{
int progress = 0;
get_progress(&progress);
std::cout << "main get process:" << progress << std::endl;
return 0;
}
Alternatively, pass it by reference instead, eg:
#include <iostream>
void get_progress(int& ref_progress)
{
int n = 100;
ref_progress = n;
std::cout << "get_report_progress:" << ref_progress << std::endl;
}
int main()
{
int progress = 0;
get_progress(progress);
std::cout << "main get process:" << progress << std::endl;
return 0;
}
Alternatively, don't pass it around by parameter at all, but return it instead, eg:
#include <iostream>
int get_progress()
{
int n = 100;
std::cout << "get_report_progress:" << n << std::endl;
return n;
}
int main()
{
int progress = get_progress();
std::cout << "main get process:" << progress << std::endl;
return 0;
}

How to get value from declaration only once?

Say I have a function that I want to call multiple times. At the start of this function I have declared an integer for a value of zero, and at the end of it I increased its value by one. Now I want to save the new value so when I call the function again the value of that variable becomes 2. Is there a way to do that besides getting the variable from another function or declare it at the top of line codes out of the functions?
TLDR
Yes, using the static keyword.
It changes the lifetime of the object declared with it, that becomes available for the whole duration of the program.
That said, you should be careful with using static local variables, because you're adding a state to the function execution.
#include <iostream>
using namespace std;
void printX()
{
static int x;
cout << "x: " << x << endl;
++x;
}
int main()
{
for (int i = 0; i < 10; ++i)
printX();
}
https://www.jdoodle.com/iembed/v0/909
There's more to the static keyword and you should look into it.
I'd suggest you read at least a couple of articles about it:
https://en.wikipedia.org/wiki/Static_(keyword)#Common_C
https://www.geeksforgeeks.org/static-variables-in-c/
you can use a static variable declared inside the function, since it is static the initialization to zero will happen only once and the rest of the time you call the function it will retain its value...
here is an example:
#include <iostream>
void foo(int x)
{
static int counter{0};
std::cout<< "this is x: " << x << std::endl;
counter++;
std::cout<< "this is counter: " << counter << std::endl;
}
int main() {
foo(1);
foo(10);
std::cout<< "something else in the app is executed... " << std::endl;
foo(101);
return 0;
}
and here the output:
this is x: 1
this is counter: 1
this is x: 10
this is counter: 2
something else in the app is executed...
this is x: 101
this is counter: 3

calling function depending on index of array array of functions' names

making random actions in a game makes it really look like real...
so if a character has many capabilities like move, work, study... so in programming a function of those is called depending on some conditions. what we want is a more random and real-looking like action where no condition is there but depending on a random condition the character takes a random actions..
I thought to make actions (functions) in an array then declare a pointer to function and the program can randomly generate an index which on which the pointer to function will be assigned the corresponding function name from the array:
#include <iostream>
void Foo() { std::cout << "Foo" << std::endl; }
void Bar() { std::cout << "Bar" << std::endl; }
void FooBar(){ std::cout << "FooBar" << std::endl; }
void Baz() { std::cout << "Baz" << std::endl; }
void FooBaz(){ std::cout << "FooBaz" << std::endl; }
int main()
{
void (*pFunc)();
void* pvArray[5] = {(void*)Foo, (void*)Bar, (void*)FooBar, (void*)Baz, (void*)FooBaz};
int choice;
std::cout << "Which function: ";
std::cin >> choice;
std::cout << std::endl;
// or random index: choice = rand() % 5;
pFunc = (void(*)())pvArray[choice];
(*pFunc)();
// or iteratley call them all:
std::cout << "calling functions iteraely:" << std::endl;
for(int i(0); i < 5; i++)
{
pFunc = (void(*)())pvArray[i];
(*pFunc)();
}
std::cout << std::endl;
return 0;
}
the program works fine but I only is it good or there's an alternative. every comment is welcome
There is absolutely no point in converting function pointers to void* and back. Define an array of function pointers, and use it as a normal array. The syntax for the declaration is described in this Q&A (it is for C, but the syntax remains the same in C++). The syntax for the call is a straightforward () application after the indexer [].
void (*pFunc[])() = {Foo, Bar, FooBar, Baz, FooBaz};
...
pFunc[choice]();
Demo.
Note: Although function pointers work in C++, a more flexible approach is to use std::function objects instead.

STL string comparison functor

I have the following functor:
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
It is supposed to be a strict weak ordering, and it's this long (could be one line only) for debug purposes.
I'm using this functor as a comparator functor for a stl::set. Problem being, it only inserts the first element. By adding console output to the comparator function, I learned that it's actually comparing the file name to itself every time.
Other relevant lines are:
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
and
// (FileSet files_;) <- SimulatedDisk private class member
void SimulatedDisk::addFile(SimulatedDiskFile * file) {
files_.insert(file);
positions_calculated_ = false;
}
EDIT: the code that calls .addFile() is:
current_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
current_request++;
}
Where all_requests is a list, and class Request is such that:
class Request {
private:
string file_name_;
int response_code_;
int response_size_;
public:
void setFileName(string file_name);
string getFileName();
void setResponseCode(int response_code);
int getResponseCode();
void setResponseSize(int response_size);
int getResponseSize();
};
I wish I could offer my hypotesis as to what's going on, but I actually have no idea. Thanks in advance for any pointers.
There's nothing wrong with the code you've posted, functionally speaking. Here's a complete test program - I've only filled in the blanks, not changing your code at all.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class SimulatedDiskFile
{
public:
string getFileName() { return name; }
SimulatedDiskFile(const string &n)
: name(n) { }
string name;
};
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
int main()
{
FileSet files;
files.insert(new SimulatedDiskFile("a"));
files.insert(new SimulatedDiskFile("z"));
files.insert(new SimulatedDiskFile("m"));
FileSet::iterator f;
for (f = files.begin(); f != files.end(); f++)
cout << (*f)->name << std::endl;
return 0;
}
I get this output:
z and a: false
a and z: true
z and a: false
m and a: false
m and z: true
z and m: false
a and m: true
m and a: false
a
m
z
Note that the set ends up with all three things stored in it, and your comparison logging shows sensible behaviour.
Edit:
Your bug is in these line:
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
You're taking the address of a local object. Each time around the loop that object is destroyed and the next object is allocated into exactly the same space. So only the final object still exists at the end of the loop and you've added multiple pointers to that same object. Outside the loop, all bets are off because now none of the objects exist.
Either allocate each SimulatedDiskFile with new (like in my test, but then you'll have to figure out when to delete them), or else don't use pointers at all (far easier if it fits the constraints of your problem).
And here is the problem:
SimulatedDiskFile temp_file(current_request->getFileName(),
current_request->getResponseSize());
disk.addFile(&temp_file);
You are adding a pointer to a variable which is immediately destroyed. You need to dynamically create your SDF objects.
urrent_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(...blah..blah..); ====> pointer to local variable is inserted
disk.addFile(&temp_file);
current_request++;
}
temp_file would go out of scope the moment next iteration in while loop. You need to change the insert code. Create SimulatedDiskFile objects on heap and push otherwise if the objects are smaller then store by value in set.
Agree with #Earwicker. All looks good. Have you had a look inside all_requests? Maybe all the filenames are the same in there and everything else is working fine? (just thinking out loud here)

Unknown crash in a C++ Memory Pointers Exercise

I recently wrote a program to help me understand the basics of memory pointers in C++, I chose a simple prime number finder.
I finally got it to work. (yay for debugging!)
And I let it run to see how far it goes, it gets to prime #815389 with my verbose tells me is the 65076th prime, I get an app crash. The one thing I could think of was my ints overflowing so I changed them to longs, it gets stuck at the same place.
Would someone be able to help explain what limitation is causing this?
comp: WinVista 64-bit Home Premium, 6GB ram AMD 4800+ X2
program crashes at 4,664K memory usage
Source:
#include <cstdlib>
#include <iostream>
\\\\(Backslashes added for readability)
using namespace std;
long number;
long numnum;
class num;
class num {
public:
long i;
void check();
bool nxt;
num* nxtnum;
};
void num::check() {
if (number % i != 0) {
if (nxt == true) {
(*nxtnum).check();
} else {
nxtnum = new num();
(*nxtnum).i = number;
numnum++;
cout << numnum << ":" << number << ", ";
nxt = true;
};
};
};
int main(long argc, char *argv[]){
numnum = 1;
cout << numnum << ":" << 2 << ", ";
num two;
two.i = 2;
for (number = 3; 1<=1000001; number++) {
two.check();
};
cout << endl;
system("PAUSE");
return EXIT_SUCCESS;
};
(Nevermind the username it's just an alias I use so I can keep track of all my posts with google)
Stack overflow? I see that check is recursive.
I'd put a guess on the fact that two.nxt isn't initialized. In C, primitive datatypes aren't initialized, meaning they have the value of whatever happened to be in whatever memory it's now occupying. That means that more than likely, in main(), two.nxt = true, which causes check() to be run on an invalid pointer. Try explicitly setting it to false and see if that works for you.
[edit] If this is the issue, the more important initialization would be when you allocate the new num in check().
Sean is right, two.nxt is never initialised. In fact, num.nxt is never initialised for any instance of num. The member nxt is unnecessary if the class is made more robust. The nxt pointer can be used instead:
class num
{
private:
long i;
num *nxtnum;
public:
num (long value) : i (value), nxtnum (0) { }
void check ()
{
if (number % i != 0)
{
if (nxtnum)
{
nxtnum->check ();
}
else
{
nxtnum = new num (number);
cout << ++numnum << ":" << number << ", ";
}
}
};
Of course, the recursive nature is probably the main culprit, the initialisation issue was hidden as you were probably running a debug build. Converting the recursive form to the iterative form is left as an exercise.
Couple of problems I can see:
You're allocating a bunch of nums, but you're not checking for a std::bad_alloc exception. You might simply be running out of memory...
You're not checking anywhere if nxtnum is != 0, even though I think it's safe to do so as the only places where you dereference it are guarding. Nevertheless, it's not that great a practise.
As Sean Edwards mentions, the num class doesn't have a constructor, so the members of a newly created num are filled with pretty much random junk. And that random junk might include nxt being set to a nonzero value. I'd add the following constructor to give it a set of safe defaults:
num::num() : i(0), nxt(false), nxtnum(0) {}
You don't really need the boolean value, I'd just check for nxtnum being non-zero.
As Jeff Yates says, you might suffer from a stack overflow as the recursive function is getting nested too deep, but it doesn't look like it'll recurse that deep.
Incidentally, if you're using a Microsoft compiler, int and long are the same size when targeting x64. You also have an infinite loop in your main function, as 1 will always be <= 1000001.
I've got it working, thank you Skizz
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
long number;
long numnum;
class num;
num *two;
num *nn;
num *bre;
class num
{
private:
long i;
num *nxtnum;
public:
num (long value) : i (value), nxtnum (0) { }
void *check ()
{
if (number % i != 0)
{
if (nxtnum)
{
//nxtnum->check ();
nn = nxtnum;
}
else
{
nxtnum = new num(number);
cout << ++numnum << ":" << number << ", ";
nn = bre;
}
}else{nn=bre;}
}
};
int main(long argc, char *argv[])
{
numnum = 1;
cout << numnum << ":" << 2 << ", ";
two = new num(2);
nn=two;
for (number = 3; 1<=1000001; number++) {
while (nn!=bre){
nn->check();
Sleep(0);
}
nn=two;
};
cout << endl;
system("PAUSE");
return EXIT_SUCCESS;
};
For Those Interested