I have a C++ function in which I have two int's, who's purpose is to serve as counters, that are declared outside of the function in my main code. My goal is to update the counter variables with the result from the execution of the function.
I have them declared as such
int cor_letters = 0;
int cor_place = 0;
and then call my function like
res = compare(input, secret_word, &cor_letters, &cor_place);
My compare function header is:
bool compare(string user_input, string secret, int * correct_letters, int * correct_place)
and in my compare code, when I get the final values of the counters, I update them as such:
correct_letters = &cor_l;
correct_place = &cor_p;
I arrived at this solution after carefully reading through my compiler errors, and this seems to work. However, I don't quite understand why this works. In the beginning, I take the address of the two variables and pass them into the function. But the function takes two pointers. So the pointers point to the address of the passed in variables.
Up to this point I seem to grasp what's going on. But its the final assignments that I'm confused by - the pointers (note they're the var names from the function header) are then being updated to the address of the temporary inner function variables that I'm using. Why does this get me the values?
I'm more of a visual learner, and pointers are hard to grasp by just reading some text, so if you wouldn't mind making some quick text diagram to represent what's going on, that would be great. Thank you
I guess you ended up with
correct_letters = &cor_l;
correct_place = &cor_p;
in order to make the compiler stop complaining.
Your analyse about taking the address of local variable is correct.
You probably want to do this
*correct_letters = cor_l;
*correct_place = cor_p;
in order to assign the correct values to the variables
which are outside the function.
A brief memo about reference (&) and dereference (*) operations.
TYPE var_a=..., var_b=...; // some variables of a chosen type
TYPE *ptr=NULL; // a pointer on such a type, but not referencing anything yet
ptr=&var_a; // now ptr memorises the address of var_a (reference operation)
var_b=*ptr; // access the value which is stored at the address memorised
// by ptr (dereference operation) in order to read it
// (here, this has the same effect as var_b=var_a; )
*ptr=var_a+var_b; // access the value which is stored at the address memorised
// by ptr (dereference operation) in order to alter it
// (here, this has the same effect as var_a=var_a+var_b; )
Related
I'm trying to understand a Function/Method in a Library in order to port it to Java however some parameters don't make any sense to me and reading the source code the library is based on is not helping.
Function (Note the API has few comments (We can also ignore the calc handle since it's got a supplier method))
Ssr calc_ssr(CalcHandle *calc, NoteInfo *rows, size_t num_rows, float music_rate, float score_goal) {
std::vector<NoteInfo> note_info(rows, rows + num_rows);
auto skillsets = MinaSDCalc(
note_info,
music_rate,
score_goal,
reinterpret_cast<Calc*>(calc)
);
return skillset_vector_to_ssr(skillsets);
}
NoteInfo Struct
struct NoteInfo
{
unsigned int notes;
float rowTime;
};
MinaSDCalc
// Function to generate SSR rating
auto
MinaSDCalc(const std::vector<NoteInfo>& NoteInfo,
const float musicrate,
const float goal,
Calc* calc) -> std::vector<float>
{
if (NoteInfo.size() <= 1) {
return dimples_the_all_zero_output;
}
calc->ssr = true;
calc->debugmode = false;
return calc->CalcMain(NoteInfo, musicrate, min(goal, ssr_goal_cap));
}
Calc expected input file data (Only care about the #Notes: ...)
Pastebin
Question
What is NoteInfo in calc_ssr, I don't know any C or C++ so the *rows to me just seems like a pointer to a Noteinfo instance, however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me (pairing this with the fact that NoteInfo needs another parameter rowTime which I think is time of Note occurrence in the file which means that value must not be constant otherwise the produced result would be inaccurate)
Github Project: https://github.com/kangalioo/minacalc-standalone (The code alone may not explain enough but it's worth a try; best to look at API.h and discern what's used from there. Though I do warn you a lot of the Code is esoteric)
Sorry if this doesn't make much sense but I've been looking into this since June/July and this API is the closest abstraction from the bare C++ code I could find.
NoteInfo * rows here is pass by pointer. So, rows actually is a pointer to an instance of type NoteInfo. This is one of the ways to pass arrays in c++ to a function. Since arrays are contiguous in memory so we can just increment the pointer by one and get the next element of the array.
for example look at these three ways to do exactly one thing, parameter to pass an array to a function :-
1. void myFunction(int *param) {}
2. void myFunction(int param[10]) {}
3. void myFunction(int param[]) {}
Look into this link for more understanding : https://www.tutorialspoint.com/cplusplus/cpp_passing_arrays_to_functions.htm
Also search for pass by pointer and pass by reference to look into different ways of passing arguments in c++.
2.however the MinaSDCalc methods requires an Array/Vector which using a pointer to a single instance doesn't make sense to me: as to this question of yours, you can now see MinaSDCalc is actually getting an array and not a single instance as passing the pointer is also one of the ways of passing an array in c++.
I am new to C++ and trying to convert string into integer. I was using atoi but there are some restrictions so I start using strtol which works perfectly. However, I would like to learn more on *temp and &temp (I have google and learn that it is a temporary space for storage) but would like to learn the difference and when to use which.
char *temp;
int m = strtol (argv[1],&temp,10);
if (*temp != '\0')
*temp is a pointer to a variable named temp and &temp takes the address of that variable
First of all jessycaaaa welcome to Stackoverflow.
I am new to C++ and trying to convert string into integer.
For me this looks like plain C-code. You can compile this with a C++ compiler though.
I was using atoi but there are some restrictions so I start using strtol which works perfectly.
Since you get an undefined behavior using atoi when argv[1] contains something different than a number, strtol is an approach to go for. If you share us a bit more code, we would help you better on your questions.
However, I would like to learn more on *temp and &temp (I have google and learn that it is a temporary space for storage) but would like to learn the difference and when to use which.
First of all you have to distinguish between use and declaration
char *temp;
Here you declare (*-symbol in declaration) a pointer named temp of type char. A pointer is a variable which stores the memory address (where it is pointing to). Here you did not define an address so it most likely will point a random space, but then
int m = strtol (argv[1],&temp,10);
you pass the address of the pointer (&-symbol, use-case, address-of operator) to strtol, so you get an address pointing to the part of the argv[1] where the number literals end, that is all fine. The function also returns the numerical value of the read string as long and is converted to an int.
if (*temp != '\0')
Here you access the value of what the address is pointing to (*-symbol, use-case, dereference operator). \0 is normally set as indication for a null-terminated string. So you are asking if the previously read end part has the null-termination character.
You know what: in C++ there are more elegant ways to accomplish that using stringstreams:
std::stringstream
Just an idea if you don't want to handle too much string manipulation in C and annoyances with pointers.
Also I would read a good book about C (not C++). C++ has also the references don't get confused by those. If you dominate the pointer-concept of C, I'm pretty sure everything else will be very clear for you.
Best regards
* and & are one of the first hurdles that programmers new to C and C++ have to take.
To really understand these concepts, it helps to know a bit more about how memory works in these languages.
First of all: C++ is just C but with classes and many other additional features. Almost all C programs are valid C++ programs. C++ even started out as a language that was compiled to C first.
Memory is, roughly speaking, divided in two parts, a 'stack' and a 'heap'. There are also other places for the code itself and compile-time constants (and maybe a few more) et cetera but that doesn't matter for now. Variables declared within a function always live on the stack. Let's see this in action with a simple example and analyse how memory is organized to build a mental model.
#include <iostream>
void MyFunction() {
int intOnStack = 5;
int* intPtrOnStack = new int(6); // This int pointer points to an int on the heap
std::cout << intOnStack << *intPtrOnStack;
delete intPtrOnStack;
}
int main() { MyFunction(); }
This program prints 56 when executed. So what happens when MyFunction() gets called? First, a part of the stack is reserved for this function to work with. When the variable intOnStack is declared within the function, it is placed in this part of the stack and it is initialized with (filled with) the int value 5.
Next, the variable intPtrOnStack is declared. intPtrOnStack is of type int*. int*'s point to int's by containing their memory-address. So an int* is placed on the stack and it is initialized with the value that results from the expression new int(6). This expression creates a new int on the heap and returns the memory-address of this int (an int*) to it. So that means that intPtrOnStack now points to the int on the heap. Though the pointer itself lives on the stack.
The heap is a part of memory that is 'shared' by all functions and objects within the program. The stack isn't. Every function has its own part of the stack and when the function ends, its part of the stack is deallocated.
So int*'s are just memory-addresses of int's. It doesn't matter where the int lives. int*'s can also point to int's on the stack:
#include <iostream>
void MyFunction() {
int intOnStack = 5;
int* intPtrOnStack = &intOnStack; // This int pointer points to intOnStack
std::cout << intOnStack << *intPtrOnStack;
}
int main() { MyFunction(); }
This prints 55. In this example we also see the &-operator in action (there are several uses of & like the bit-wise-and, I'm not going into them).
& simply returns the memory-address (a pointer!) of its operand. In this case its operand is intOnStack so it returns its memory-address and assigns it to intPtrOnStack.
So far, we've seen only int* as types of pointers but there exist pointer-types for each type of object that has a memory-address, including pointers. That means that a thing like int** exists and simply means 'pointer to a pointer to an int'. How would you get one? Like this: &intPtrOnStack.
Can pointers only live on the stack? No: new int*(&intPtrOnStack). Or new int*(new int(5)).
I have a function which retrieves an image from a camera.
This function has a function called GetData() which returns a pointer to the data contained by the Image object created by the camera.
The data pointed to by GetData() is locally initialized.
Currently, I'm copying the data pointed to by GetData element by element using a for loop, but is there a way to copy the data without using a for loop? Or, better yet, avoid copying the data and just copy the pointer address and prevent the local data from being terminated.
Code:
void getImage(unsigned char data[]){
// Get the image in 1d array format
fc::Image rawImage;
//Initializes Image object
error = camera.RetrieveBuffer( &rawImage );
//retrieve and return data
unsigned char *temp = rawImage.GetData(); //returns point to data
for(int i = 0; i < IMG_SIZE; i++){
data[i] = temp[i];
}
}
Called simply with
unsigned char data[size];
getImage(data);
The problem lies in the fact that your data is a local object on the stack. Once your function returns, the fc::Image object (and the data it points to) will be destroyed. I only see three possible ways of getting that data out of the function:
Copy the data to the destination array (like you already do, but maybe using memcpy or something along those lines instead of a naked for loop)
Declare your data member to be static (so it sticks around even after the function returns), then simply set the value of the destination pointer to point to the data by data = rawImage.GetData()
Possibly the best one, if you can do it: change your API! Simply accept a pointer or reference to an fc::Image object and pass that as the argument to camera.RetrieveBuffer so your data lands in the right place to begin with. Or another way would be to return your object by value, and take no arguments in that case.
The second one is kind of funky, since the data would only be valid as long as someone else doesn't call the function again, which is a terrible practice to be honest, so I wouldn't suggest number 2.
Also, this API is pretty bad as it is. What's the guarantee that the passed in pointer will have enough capacity? And also, how does the user know how long is the data they received? You don't return a size value or anything.
EDIT:
There's a more appropriate way of doing number 2. You can do something like this:
#include <unordered_map>
// Ideally this would be wrapped in a class or something. Don't use globals.
std::unordered_map<unsigned char*, fc::Image> images;
void getImage(unsigned char data*){
// Get the image in 1d array format
fc::Image rawImage;
//Initializes Image object
error = camera.RetrieveBuffer( &rawImage );
data = rawImage.getData();
images.insert(std::make_pair(data, move(rawImage)));
}
This uses an unordered_map to keep your local objects alive, so you can safely return pointers into them without having to worry about the lifetime of the objects.
But in this case you will have to create a cleanup function as well:
void destroyImage(unsigned char data*){
images.erase(data);
}
Since the map will keep your objects around forever, you will soon start to fill up memory if you keep getting new images. If you use this method, then your users will have to call destroyImage() as soon as they no longer need the data to avoid leaking memory essentially. This kind of goes agains the memory management guidelines in modern C++ which encourage automatic cleanup, while this would depend on your users to call your cleanup function, which is a little unsafe, but it's still the best you can do in my opinion, since you cannot change your API.
If you can expand your API to include such a function, this is definitely a better way to extend the lifetime of your local objects, rather than marking them static.
consider this code:
double *pi;
double j;
pi = &j;
pi[3] = 5;
I don't understand how is that possible that I can perform the last line here.
I set pi to the reference of j, which is a double variable, and not a double [] variable. so how is this possible that I can perform an array commands on it?
consider this code:
char *c = "abcdefg";
std::cout << &(c[3]) << endl;
the output is "defg". I expected that I will get a reference output because I used &, but instead I got the value of the char * from the cell position to the end. why is that?
You have two separate questions here.
A pointer is sometimes used to point to an array or buffer in memory. Therefore it supports the [] syntax. In this case, using pi[x] where x is not 0 is invalid as you are not pointing to an array or buffer.
Streams have an overload for char pointers to treat them as a C-style string, and not output their address. That is what is happening in your second case. Try std::cout << static_cast<const void *>(&(c[3])) << endl;
Pointers and arrays go hand in hand in C (sort of...)
pi[3] is the same as *(pi + 3). In your code however this leads to Undefined Behavior as you create a pointer outside an object bounds.
Also be careful as * and & are different operators depending on in which kind of expression the appear.
That is undefined behavior. C++ allows you to do things you ought not to.
There are special rules for char*, because it is often used as the beginning of a string. If pass a char* to cout, it will print whatever that points to as characters, and stop when it reaches a '\0'.
Ok, so a few main things here:
A pointer is what it is, it points to a location in the memory. So therefore, a pointer can be an array if you whish.
If you are working with pointers (dangerous at times), this complicates things. You are writing on p, which is a pointer to a memory location. So, even though you have not allocated the memory, you can access the memory as an array and write it. But this gives us the question you are asking. How can this be? well, the simple answer is that you are accessing a zone of memory where the variable you have created has absolutely no control, so you could possibly be stepping on another variable (if you have others) or simply just writting on memory that has not been used yet.
I dont't understand what you are asking in the second question, maybe you could explain a little more? Thanks.
The last line of this code...
double *pi;
double j;
pi = &j;
pi[3] = 5;
... is the syntactic equivalent to (pi + 3) = 5. There is no difference in how a compiler views a double[] variable and a double variable.
Although the above code will compile, it will cause a memory error. Here is safe code that illustrates the same concepts...
double *pi = new double[5]; // allocate 5 places of int in heap
double j;
pi[3] = 5; // give 4th place a value of 5
delete pi; // erase allocated memory
pi = &j; // now get pi to point to a different memory location
I don't understand how is that possible that I can perform the last
line here. I set pi to the reference of j
Actually, you're setting your pointer pi, to point to the memory address of j.
When you do pi[3], you're using a non-array variable as an array. While valid c++, it is inherently dangerous. You run the risk of overwriting the memory of other variables, or even access memory outside your process, which will result in the operating system killing your program.
When that's said, pi[3] means you're saying "give me the slot third down from the memory location of pi". So you're not touching pi itself, but an offset.
If you want to use arrays, declare them as such:
double pi[5]; //This means 5 doubles arrayed aside each other, hence the term "array".
Appropos arrays, in c++ it's usually better to not use raw arrays, instead use vectors(there are other types of containers):
vector<double> container;
container.push(5.25); //"push" means you add a variable to the vector.
Unlike raw arrays, a container such as a vector, will keep it's size internally, so if you've put 5 doubles in it, you can call container.size(), which will return 5. Useful in for loops and the like.
About your second question, you're effectively returning a reference to a substring of your "abcdefg" string.
&([3]) means "give me a string, starting from the d". Since c-style strings(which is what char* is called) add an extra NULL at the end, any piece of code that takes these as arguments(such as cout) will keep reading memory until they stumble upon the NULL(aka a 0). The NULL terminates the string, meaning it marks the end of the data.
Appropos, c-style strings are the only datatype that behaves like an array, without actually being one. This also means they are dangerous. Personally I've never had any need to use one. I recommend using modern strings instead. These newer, c++ specific variables are both safe to use, as well as easier to use. Like vectors, they are containers, they keep track of their size, and they resize automatically. Observe:
string test = "abcdefg";
cout<<test.size()<<endl;//prints 7, the number of characters in the array.
test.append("hijklmno");//appends the string, AND updates the size, so subsequent calls will now return 15.
CARD& STACK::peek()
{
if(cards.size == 0)
{
CARD temp = CARD {-1, -1};
return temp;
}
return cards.back();
}
This is the function I am having trouble with.
CARD is just a struct with two int variables, called rank and suit.
STACK is a class that manages an std::vector<CARD>, that is called cards.
The function is supposed to return a reference to the card on top of the stack, or return the reference to a dummy card if the vector is empty.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do I do about it?
Second, I am trying to use this function with another function I created called cardToString
char* cardToString(CARD& c);
It is supposed to use the rank and suit variables in the passed CARD to look up string values in a table, concatenate the two strings together, and return a pointer to the new string.
So the end result looks like:
cout<<cardToString(deck.peek())<<"\n";
but this line of code will execute up to the cardToString function, then just stop for some reason. It is annoying the hell out of me because it just stops, there is no error message and there does not look like there is anything wrong to me.
Can somebody help me out?
Edit: here is the cardToString function
char *cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
{
std::cout<<"returned null";
return NULL;
}
char *buffer = new char[32];
strcpy(buffer, RANKS[c.r]);
strcat(buffer, " of ");
return strcat(buffer, SUITS[c.s]);
}
I specifically want the function STACK.peek() to return the address of the CARD that already exists on the top of the STACK. It seems to make more sense to do that than to create a copy of the card that I want to return.
First of all, I get a warning that says a reference to a local variable temp is returned. What is wrong with that? How will that effect the function? What do i do about it?
A local variable, as it name implies, is local to the function it belongs to, so it's destroyed as the function returns; if you try to return a reference to it, you'll return a reference to something that will cease to exist at the very moment the function returns.
Although in some cases this may seem to work anyway, you're just being lucky because the stack hasn't been overwritten, just call some other function and you'll notice it will stop working.
You have two choices: first of all, you can return the CARD by value instead of reference; this, however, has the drawback of not allowing the caller to use the reference to modify the CARD as is stored in the vector (this may or may not be desirable).
Another approach is to have a static dummy CARD instance stored in the STACK class, that won't have these lifetime problems, and that can be returned when you don't have elements in the vector; however, you should find a method to "protect" its field, otherwise a "stupid" caller may change the values of your "singleton" dummy element, screwing up the logic of the class. A possibility is to change CARD in a class that will encapsulate its fields, and will deny write access to them if it's the dummy element.
As for the cardToString function, you're probably doing something wrong with the strings (and I'm almost sure you're trying to return a local also in this case), but without seeing the body of the function it's difficult to tell what.
By the way, to avoid many problems with strings I suggest you to use, instead of char *, the std::string class, which takes away most of the ugliness and of the low level memory management of the usual char *.
Also, I'd suggest you to change cardToString to take a const reference, because most probably it doesn't need to change the object passed as reference, and it's good practice to clearly mark this fact (the compiler will warn you if you try to change such reference).
Edit
The cardToString function should be working fine, as long as the RANKS and SUITS arrays are ok. But, if you used that function like you wrote, you're leaking memory, since for each call to cardToString you make an allocation with new that is never freed with delete; thus, you are losing 32 bytes of memory per call.
As stated before, my tip is to just use std::string and forget about these problems; your function becomes as simple as this:
std::string cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
return "(invalid card)";
return std::string(RANKS[c.r]) + " of " + SUITS[c.s];
}
And you don't need to worry about memory leaks and memory allocations anymore.
For the reference/value thing: if the caller do not need to use the reference to modify the object stored in the vector, I strongly suggest passing it by value. The performance hit is negligible: two ints instead of one pointer means 8 vs 4 bytes on most 32 bit architectures, and 8 bytes vs 8 bytes on most 64 bit machines (and also accessing the fields via pointer has a small cost).
This kind of micro-optimization should be the last of your concerns. Your top priority is to write correct and working code, and the last thing you should do is to let micro-optimization get in the way of this aim.
Then, if you experience performance problems, you'll profile your application to find where the bottlenecks are and optimize those critical points.
You cannot return a reference to a local variable, because the local variable no longer exists when the function returns.
You need to return by-value, not by-reference (i.e. CARD STACK::peek() { ... }).