Modifying an existing array with a function
I have an array of char representing pixels in a bitmap, which I want to modify. I don't think I can just iterate over the array and pass chars into a function individually, because the function needs to take into account the neighboring pixels, too.
I thought of two ways to do this. The first would be to pass the array to the function as an argument, then have the function change it and return it. The trouble is I'm not exactly sure what happens internally when you pass an array to a function and return it. Is it the same array, modified? Or is it a copy of the array, so now you're using twice as much memory?
Alternatively I guess I could have a function with a void return type and pass a pointer to the array. I'm somewhat new to this, but the way I understand it is that a pointer is like the address of a house, while the array is the actual house. So if I give the function the address, it can go to that address and rearrange the furniture inside the house. Then, after the function returns, I can go to that address myself and see all the rearranged furniture, even though the function has already returned.
Is there a problem with the second way? It seems a bit neater, but maybe I'm understanding pointers wrong.
Re: Modifying an existing array with a function
I note from your location that you are using .net4.0. Is your question regarding c++ or c#?
Re: Modifying an existing array with a function
Ah, sorry about that - this is C++, non-CLR code.
Re: Modifying an existing array with a function
Quote:
Originally Posted by
fiodis
So if I give the function the address, it can go to that address and rearrange the furniture inside the house.
When you "pass arrays" in C++ as you described, you are never really passing an array. You are always passing the address of the first element of the array.
Code:
void foo(char *p);
void foo(char p[]);
Both of these prototypes are exactly the same, regardless of how "array-ish" the second version looks.
Regards,
Paul McKenzie
Re: Modifying an existing array with a function
Passing a pointer works. Keep in mind that the name of the array without specifying an index is a pointer.
Re: Modifying an existing array with a function
Hmm. It seems I'm thinking of pointers in the right way, but I'm having trouble creating an array in the first place. This:
Code:
int main(int argc, char *argv[])
{
const unsigned int res = 512;
unsigned char imageData[res*res*3];
unsigned int landMap[512];
return 0;
}
runs fine, but when I try this:
Code:
int main(int argc, char *argv[])
{
const unsigned int res = 512;
unsigned char imageData[res*res*3];
unsigned int landMap[512*512];
return 0;
}
I get a stack overflow error. Why would that be happening? I didn't think I could run out of memory by having a 512^2-element integer array as opposed to a 512-element one.
Re: Modifying an existing array with a function
You're not running out of memory, you're running out of stack space ("stack overflow"). The stack is limited (I forget the specific amount), and is usually a lot smaller then the heap.
For large arrays, you'll need to use the heap. Or, even better, use a vector.
Viggy
Re: Modifying an existing array with a function
Quote:
Originally Posted by
MrViggy
The stack is limited (I forget the specific amount), [...].
Under Windows (except on Itanium machines) it has a default size of 1 MB, but that can be changed (see http://msdn.microsoft.com/en-us/libr...=vs.100).aspx). But, as you already suggested, it's probably better to leave the stack size as-is and use a std::vector instead.
Re: Modifying an existing array with a function
Quote:
Originally Posted by
fiodis
I get a stack overflow error.
You could avoid this overflow (as has been suggested) by allocating the array on the heap instead. But if the array is to be present during the whole of the program's lifetime there's a third option, static memory. Simply move the array declaration outside of main (and any other function) and it will be in static memory. So apart from stack and heap there's also static memory to consider.
Note that if you switch from an array to a vector (as has been suggested) you must be careful not to end up doing what you were worried about, namely passing a copy of the whole thing. There are two major parameter passing modes to consider: by-reference and by-value. And there are two common ways to avoid passing a copy of a data structure to a function. The first is to pass the data structure by-reference (commonly used for vectors). The second is to pass a pointer to the data structure by-value (commonly used for arrays).
Re: Modifying an existing array with a function
I managed to get the functionality I needed by allocating the array on the heap, thanks guys. :)
But I didn't know about static memory. Why is it called "static"? I can still change the value of variables in static memory, right?
And I looked up passing vectors by reference. I see the syntax for it is vector<Type>& but what is a reference, exactly? Is it a pointer to the start of the vector in memory?
Re: Modifying an existing array with a function
"static" has different meaning depending on how you use it.
at global scope it means a variable (or function) is local to the module only (it is not being exported outside of the compilation unit), so it cannot be referred to from another source file (not even with an extern declaration).
At function scope it means that the variable is visible inside the function only, and in addition the contents will persist across multiple calls to the function so you can do something like this:
Code:
void foo()
{
static int count = 0;
printf("this function has been called %d times.", ++count);
}
The above is a rather silly example, but it has some very interesting uses, such as initialize-once-use-many type stuff. It's also a common approach for some forms of singleton patterns.
static has other uses in other contexts. (imo not always in a good way to use the same keyword for different uses, but it does mean less reserved keywords to deal with)
Re: Modifying an existing array with a function
Not exactly. You can kinda think of it as the vector being passed as a pointer to the vector itself (not the start of the data), if I understand your question. You still access the vector as if it were an object (use '.' not '->'). Passing by reference doesn't make a copy of the data, allowing the function to change the data in the vector (or whatever data type your function takes). Because the compiler doesn't make a copy of the data, a lot of times you'll see vectors being passed as const references, which enforces the notion that the data in the vector should not be changed by the compiler, but you won't have a copy of the vector made.
Code:
void someFuncToReadVector (const std::vector<int> &myConstVec)
{
std::cout << "The vector has " << myConstVec.size() << " items.\n"; // Just reading, not changing.
myConstVec.push_back(42); // This is illegal, and should cause a compiler error, since the vector is const
}
void someFuncToChangeVector (std::vector<int> &myVec)
{
std::cout << "The vector has " << myVec.size() << " items.\n";
myVec.push_back(42); // Perfectly legal, and when returning, the vector passed in will have a new entry
std::cout << "The vector now has " << myVec.size() << " items.\n";
}
Viggy
Quote:
Originally Posted by
fiodis
And I looked up passing vectors by reference. I see the syntax for it is vector<Type>& but what is a reference, exactly? Is it a pointer to the start of the vector in memory?
Re: Modifying an existing array with a function
Quote:
Originally Posted by
fiodis
And I looked up passing vectors by reference. I see the syntax for it is vector<Type>& but what is a reference, exactly? Is it a pointer to the start of the vector in memory?
Passing by value and by reference are fundamental to understanding how parameter passing works in C++, regardless of whether it's vector or not that you're passing.
I would suggest getting a book or tutorial on C++, as those venues are better suited to learning C++ properly than a forum.
Regards,
Paul McKenzie
Re: Modifying an existing array with a function
Quote:
And I looked up passing vectors by reference. I see the syntax for it is vector<Type>& but what is a reference, exactly? Is it a pointer to the start of the vector in memory?
Sidebar: How do you get the quote icon and the name of the person who said it inside the box?
This is only my opinion and I know a lot of people, including the designers of the STL, disagree with me but I think references are vastly overused. In most cases, all they are doing is hiding a pointer so the programmer doesn't have to explicity use * and ->.
I think when I was learning C++ (and coming from a C background was quite comfortable with pointers) I had a bad experience that set me against references and I guess I've never really gotten over it; at the time, the STL was poorly supported and one of my predecessors on a certain project had implemented his own queue. I was debugging a block of code and found something like this:
Code:
if (whatever)
{
Widget * pWidget = new Widget(a, b, c);
queue.Enqueue(*pWidget);
}
I immediately thought I had found a memory leak. Clearly, pWidget was not deallocated anywhere. It turns out the Enque function took its argument by reference, internally took the address of it, and thereby took ownership of the object. I got bit by this a second time when, after enough time had transpired for me to forget about it, I ran across it again.
To my thinking, the intent is far more clear if ownership issues are communicated with pointers and pointers-to-const. In my opinion, std::swap(Type & a, Type & b); should instead be std::swap(Type * pa, Type * pb); I do like references, a lot, when necessary for emulating the semantics of primitive types, as in the code necessary for something like this to work:
Code:
MatrixA = MatrixB;
MatrixC = MatrixA + MatrixD;
String A = StringB + StringC;
There, ownership intentions are still clear and not clouded by references.
Re: Modifying an existing array with a function
Quote:
Originally Posted by GeoRanger
In most cases, all they are doing is hiding a pointer so the programmer doesn't have to explicity use * and ->.
Yes, and expressing the fact that the parameter is not optional, which it might be if it were a pointer parameter (i.e., a null pointer could be a valid argument).
Quote:
Originally Posted by GeoRanger
I had a bad experience that set me against references and I guess I've never really gotten over it
I think you should get over it as your bad experience has to do with questionable design, not overuse of references per se.
Quote:
Originally Posted by GeoRanger
In my opinion, std::swap(Type & a, Type & b); should instead be std::swap(Type * pa, Type * pb);
Why? What benefit do pointer parameters provide here? There is no question of ownership as swap is not an object that might own anything.
Re: Modifying an existing array with a function
Quote:
Originally Posted by
GeoRanger
This is only my opinion and I know a lot of people, including the designers of the STL, disagree with me but I think references are vastly overused. In most cases, all they are doing is hiding a pointer so the programmer doesn't have to explicity use * and ->.
Well, the designers of Java agree with you. In Java there's no by-reference parameter passing at all. It's always by-value (like in C). And the syntax is adapted to this so there's no notion of pointer either. References in C++ were introduced primarily to support operator overloading which is not available in Java.
So the problem is you cannot have the versability of C++ without the complexity. You either must learn to live with it (using a coding standard helps), or you must switch to something simpler like Java.
Re: Modifying an existing array with a function
Quote:
Originally Posted by
fiodis
But I didn't know about static memory. Why is it called "static"? I can still change the value of variables in static memory, right?
There are 4 kinds of different memory in C++: automatic (stack), dynamic (heap), static and thread (as of C++ 11).
What separates these is the property of duration, that is the longevity of entities stored in each kind of memory. An entity in static memory stays for the whole of a program. I guess that's why it's called static. It sticks around from start to finish. It's always there all the time.
Re: Modifying an existing array with a function
Quote:
Originally Posted by
nuzzle
In Java there's no by-reference parameter passing at all. It's always by-value (like in C).
actually, one could say the same thing in C++: one can think at "pass-by-reference" simply as the process of initializing a variable of reference type. This way of thinking is especially useful given the proliferation of "references" due to c++11 ( r-value references, universal references, smart pointers, etc... ). Everything is "passed-by-value" ( or better, copy-initialized (*) ) and usual overloading/deduction/conversion rules are applied.
I think this is a better mindset which reflects all the possible (arbitrarily many) ways in which you can model the idea of a variable holding a "reference" to something, depending on the specific guarantees/semantics one's looking for ( ownership, validity, mutability, etc... ).
(*) in fact, references are not objects, hence have no "value" to "pass".
Re: Modifying an existing array with a function
Quote:
Originally Posted by
superbonzo
actually, one could say the same thing in C++: one can think at "pass-by-reference" simply as the process of initializing a variable of reference type.
Maybe it can be advantageous to think about it that way but that doesn't change the fact that C++ supports both major parameter passing modes: by-value and by-reference. The complexity due to this is still there regardless of how you think about it.
These principally different modes are also useful when contrasting languages; Fortran has by-reference only, C has by-value only, Java has by-value only, Pascal has both, C++ has both, etcetera. With that basic knowledge in mind it's much easier to grasp the details for a specific language and paint a picture of how it "works" in each case.
Re: Modifying an existing array with a function
Quote:
Originally Posted by
nuzzle
These principally different modes are also useful when contrasting languages
this is true, but is it really worth it ? consider the OP's doubts and georanger's reference aversion; I think both come from the fact that when they look at a code like "f(T& x)" they view the "&" as a syntactical intruder used to tell the compiler to avoid the copy of "x". This spurious semantics is unnecessary and wrong; IMO, it's much better to think the "&" as a type modifier as in the pointer case "T*", rather than a sort of variable modifier.
Quote:
Originally Posted by
nuzzle
C has by-value only, Java has by-value only, Pascal has both, C++ has both, etcetera.
so, you claim that C++ supports pass-by-reference and C does not, because in the former you can write "f(T& x);f(x)" whereas in the latter you write "f(T* x);f(&x)", does just adding one less "&" justifies such a claim ? maybe, but similar reasonings could be said for most languages as well, beacuse most languages allow to express the ideas of copying vs referencing things, in one way or the other. For this reason I doubt the actual pedagogical effectiveness of the very idea of "passing modes" ...