473,748 Members | 5,230 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Passing Dynaically-Sized Arrays

I'm sure I'm missing something simple - I do not code in C regularly, and
the breaks are long enough for me to forget.

The situation I have is I need to create an array but I do not know the
dimension until runtime. I pass the pointer to a function which then
determines the size and then creates and populates it. I can walk the array
OK in the function, but the app crashes when I try to do so in the calling
routine.

Here's a small program that recreates the exception:

#include <stdio.h>
#include <stdlib.h>
#include "ArrayManagemen t.h"
#include "Test.h"

void MakeIVector(int *iv, int n1) {
int i;
iv = iVector(n1);
for (i = 0; i < n1; i++) iv[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
return;
}

int main() {
int n1 = 8;
int i, j, k;

int* iv = iVector(n1);
for (i = 0; i < n1; i++) iv[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
Free_iVector(iv );
printf("\n");

int *iv2;
MakeIVector(iv2 , n1);
printf("\n");
for (i = 0; i < n1; i++) iv2[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv2[i]);

exit(0);
}

ArrayManagement is a tried and tested module that creates 1, 2 and 3
dimesioned arrays based on dimensions passed in.

In main a 1 dimensional array (vector) is created, populated and dumped to
console. No problems.

It then calls a function (MakeIVector) which creates, populates and dumps an
array to the console. This also works.

Upon the return from MakeIVector it blows up while trying to assign values
to elements of iv2. If I remove that loop, and only do the printf loop, I
get values to the screen, but it looks like addresses.

What am I doing wrong? I'd like to be able to pass these arrays to and from
functions.

To extend this, would anything change if I needed to pass these through
several layers of functions?

What about if I need to do this with 2 or three dimensional arrays? What
syntax would I need then?

This is ANSI C, and I use gcc.

Thanks in advance!

Jul 10 '08 #1
5 1476
In article <wx************ @fe181.usenetse rver.com>,
CapCity <Ca*@City.comwr ote:
>#include <stdio.h>
#include <stdlib.h>
#include "ArrayManagemen t.h"
#include "Test.h"

void MakeIVector(int *iv, int n1) {
int i;
iv = iVector(n1);
iv is a pointer, so presumably iVector(n1) is allocating memory
and returning the address of that memory, then to be stored into iv
for (i = 0; i < n1; i++) iv[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
return;
An initial value for iv was passed in to MakeIVector but
the new value (the address returned by iVector()) is not being
passed out of the routine. Thus the calling routine has no idea
where the allocated memory is.
>}
>int main() {
int n1 = 8;
int i, j, k;

int* iv = iVector(n1);
for (i = 0; i < n1; i++) iv[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
Free_iVector(iv );
printf("\n");
int *iv2;
MakeIVector(iv2 , n1);
You have not initialized iv2, but you are passing its value into
MakeIVector
printf("\n");
for (i = 0; i < n1; i++) iv2[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv2[i]);

exit(0);
}

Your fundamental problem is that you are expecting that if a routine
changes the value of a parameter that has been passed in, then the
change will also be made in the calling routine. That is never the case in C.
Any value passed in to a C routine is a *copy* of the value, and
changes to the copy never affect the original.

There are two basic solutions:

1) change MakeIVector so that it does not take iv as an input
but returns the *pointer* iv as an output; or

2) Instead of passing in the -value- of (the uninitialized) iv2,
pass in the -address- of that pointer (making the appropriate
adjustment to the type of the parameter), and write the pointer
through that address:

void MakeIVector(int **iv, int n1) {
int i;
*iv = iVector(n1);

for (i = 0; i < n1; i++) (*iv)[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", (*iv)[i]);
return;
}

then later

int *iv2;
MakeIVector(&iv 2, n1);

After which the value of iv2 will have been changed to be the pointer
to the allocated area.

(There are other improvements possible to the program, such as using
size_t instead of int for the sizes, in case the user wants to
allocate more than 32767 int's.)
--
"Whenever there is a hard job to be done I assign it to a lazy
man; he is sure to find an easy way of doing it."
-- Walter Chrysler
Jul 10 '08 #2
CapCity <Ca*@city.comwr ote:
I'm sure I'm missing something simple - I do not code in C regularly, and
the breaks are long enough for me to forget.
The situation I have is I need to create an array but I do not know the
dimension until runtime. I pass the pointer to a function which then
determines the size and then creates and populates it. I can walk the array
OK in the function, but the app crashes when I try to do so in the calling
routine.
Here's a small program that recreates the exception:
#include <stdio.h>
#include <stdlib.h>
#include "ArrayManagemen t.h"
#include "Test.h"
void MakeIVector(int *iv, int n1) {
The function receives a copy of the value of the pointer 'iv2'.
Keep in mind that is a pass-by-value language (in contrast to
e.g. FORTRAN where changes to function arguments also change
the values of the variables used as arguments in the caller).
int i;
iv = iVector(n1);
This seems to assign some memory and sets the local variable
'iv' to that value, overriding the value it initially had (the
copy of whatever was stored in 'iv2' in main()).
for (i = 0; i < n1; i++) iv[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
return;
}
int main() {
int n1 = 8;
int i, j, k;
int* iv = iVector(n1);
for (i = 0; i < n1; i++) iv[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
Free_iVector(iv );
printf("\n");
int *iv2;
MakeIVector(iv2 , n1);
Unfortunately, this doesn't do what you seem to expect. It
passes a copy of whatever address stored in 'iv2' to the
function. MakeIVector() actually never uses this value
(which is reasonable, since it's some random garbage be-
cause 'iv2' is uninitialized). And when MakeIVector() re-
turns nothing has changed about what 'iv2' contains, since
MakeIVector() operated on a local variable that vanished
the moment the function was left.
printf("\n");
for (i = 0; i < n1; i++) iv2[i] = i;
And now you use the still unitialized value of 'iv2' and
that's rather likely to crash your program.
for (i = 0; i < n1; i++) printf("%i\n", iv2[i]);
exit(0);
}
There are two solutions to this problem:

a) Instead of passing the value of 'iv2' to MakeIValue()
pass it a pointer to 'iv2'. Then MakeIValue() is able
to change what it's pointing to. But then you have to
change MakeIForm to

void MakeIVector(int **iv, int n1) {
int i;

*iv = iVector(n1);
for (i = 0; i < n1; i++) (*iv)[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", (*iv)[i]);
}

b) Just have MakeIVector return the value of the pointer it was
using. Then you have to change the code in main() to

int *iv2 = MakeIVector(n1) ;

and the necessary changes to MakeIVector() are:

int * MakeIVector(int n1) {
int i;
int *iv = iVector(n1);

for (i = 0; i < n1; i++) iv[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
return iv;
}
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\______________ ____________ http://toerring.de
Jul 10 '08 #3
On Jul 11, 1:45*am, "CapCity" <C...@City.comw rote:
void MakeIVector(int *iv, int n1) {
*int i;
*iv = iVector(n1);
iv is passed by value. In this function, iv points to the memory
allocated by iVector(persumi ng it as you haven't posted the code) but
on return, the old value is popped from the stack.

*int* iv = iVector(n1);
This thing works as it is capturing the return value.
*int *iv2;
*MakeIVector(iv 2, n1);
This won't work. You will have to pass a pointer to the pointer.
int **iv2;
MakeIVector (iv2, nl);
And code for MakeIVector will have to be changed accordingly.

Jul 11 '08 #4
On Jul 11, 4:45*am, "CapCity" <C...@City.comw rote:
I'm sure I'm missing something simple - I do not code in C regularly, and
the breaks are long enough for me to forget.

The situation I have is I need to create an array but I do not know the
dimension until runtime. I pass the pointer to a function which then
determines the size and then creates and populates it. I can walk the array
OK in the function, but the app crashes when I try to do so in the calling
routine.

Here's a small program that recreates the exception:

#include <stdio.h>
#include <stdlib.h>
#include "ArrayManagemen t.h"
#include "Test.h"

void MakeIVector(int *iv, int n1) {
*int i;
*iv = iVector(n1);
This is wrong.
For simplicity, `iv' is a local scoped variable in function
MakeIVector, so it takes no effect outside MakeIVector to use `iv' as
a left value.
*for (i = 0; i < n1; i++) iv[i] = i*2;

Jul 11 '08 #5

"Walter Roberson" <ro******@ibd.n rc-cnrc.gc.cawrote in message
news:g5******** **@canopus.cc.u manitoba.ca...
In article <wx************ @fe181.usenetse rver.com>,
CapCity <Ca*@City.comwr ote:
>>#include <stdio.h>
#include <stdlib.h>
#include "ArrayManagemen t.h"
#include "Test.h"

void MakeIVector(int *iv, int n1) {
int i;
iv = iVector(n1);

iv is a pointer, so presumably iVector(n1) is allocating memory
and returning the address of that memory, then to be stored into iv
>for (i = 0; i < n1; i++) iv[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
return;

An initial value for iv was passed in to MakeIVector but
the new value (the address returned by iVector()) is not being
passed out of the routine. Thus the calling routine has no idea
where the allocated memory is.
>>}
>>int main() {
int n1 = 8;
int i, j, k;

int* iv = iVector(n1);
for (i = 0; i < n1; i++) iv[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv[i]);
Free_iVector(i v);
printf("\n") ;
>int *iv2;
MakeIVector(iv 2, n1);

You have not initialized iv2, but you are passing its value into
MakeIVector
>printf("\n") ;
for (i = 0; i < n1; i++) iv2[i] = i;
for (i = 0; i < n1; i++) printf("%i\n", iv2[i]);

exit(0);
}


Your fundamental problem is that you are expecting that if a routine
changes the value of a parameter that has been passed in, then the
change will also be made in the calling routine. That is never the case in
C.
Any value passed in to a C routine is a *copy* of the value, and
changes to the copy never affect the original.

There are two basic solutions:

1) change MakeIVector so that it does not take iv as an input
but returns the *pointer* iv as an output; or

2) Instead of passing in the -value- of (the uninitialized) iv2,
pass in the -address- of that pointer (making the appropriate
adjustment to the type of the parameter), and write the pointer
through that address:

void MakeIVector(int **iv, int n1) {
int i;
*iv = iVector(n1);

for (i = 0; i < n1; i++) (*iv)[i] = i*2;
for (i = 0; i < n1; i++) printf("%i\n", (*iv)[i]);
return;
}

then later

int *iv2;
MakeIVector(&iv 2, n1);

After which the value of iv2 will have been changed to be the pointer
to the allocated area.

(There are other improvements possible to the program, such as using
size_t instead of int for the sizes, in case the user wants to
allocate more than 32767 int's.)
Thanks, Walter (and to the rest). That straightened things out for me.

I was aware (to a point) of the pass "by value" as opposed to "by
reference". To have a function change the value of an int or double you pass
in a pointer to the int or double.

But I needed to abstract that concept out a level for the one dimensional
array - I needed the function to change the value of a *pointer* so I needed
to pass in a pointer to the pointer. I was only providing the pointer
itself, thinking that was sufficient.

Thanks for getting me back on track.

--
"Whenever there is a hard job to be done I assign it to a lazy
man; he is sure to find an easy way of doing it."
-- Walter Chrysler


Jul 11 '08 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
4681
by: Dave | last post by:
I'm currently working on a small project (admitedly for my CS class) that compares the time difference between passing by value and passing by reference. I'm passing an array of 50000 int's. However, since in C++ an array is passed by reference by default I need to embed the array into a struct in order to pass it by value. The problem is that I get a segmentation error when doing so. I'm using the Dev-c++ compiler. Any ideas? ...
58
10170
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of code... TCHAR myArray; DoStuff(myArray);
9
2298
by: Just Me | last post by:
PARAFORMAT2 is a structure that SendMessage will return stuff in. Is the "ref" correct or since only a pointer is being passed should it be by value? Suppose I was passing data rather then receiving it, would that change the answer to the above?
8
2117
by: Dennis Myrén | last post by:
I have these tiny classes, implementing an interface through which their method Render ( CosWriter writer ) ; is called. Given a specific context, there are potentially a lot of such objects, each requiring a call to that method to fulfill their purpose. There could be 200, there could be more than 1000. That is a lot of references passed around. It feels heavy. Let us say i changed the signature of the interface method to:
22
25597
by: Arne | last post by:
How do I pass a dataset to a webservices? I need to submit a shoppingcart from a pocket PC to a webservice. What is the right datatype? II have tried dataset as a datatype, but I can't get it to compile. <WebMethod()> _ Public Function VerifySku(ByVal skus As XmlDataDocument) As DataSet Test program : Dim cartSet As DataSet cartSet = ws.VerifySku(cartSet)
6
5996
by: MSDNAndi | last post by:
Hi, I get the following warning: "Possibly incorrect assignment to local 'oLockObject' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local." My code is: using System; using System.Collections.Generic;
12
2683
by: Andrew Bullock | last post by:
Hi, I have two classes, A and B, B takes an A as an argument in its constructor: A a1 = new A(); B b = new B(a1);
12
5400
by: Mike | last post by:
Consider the following code: """ struct person { char *name; int age; }; typedef struct person* StructType;
7
3305
by: TS | last post by:
I was under the assumption that if you pass an object as a param to a method and inside that method this object is changed, the object will stay changed when returned from the method because the object is a reference type? my code is not proving that. I have a web project i created from a web service that is my object: public class ExcelService : SoapHttpClientProtocol {
4
2812
by: Deckarep | last post by:
Hello fellow C# programmers, This question is more about general practice and convention so here goes: I got into a discussion with a co-worker who insisted that as a general practice all objects should be passed by reference using the ref keyword generally speaking because as the writer of code you are conveying your intentions that an Object should/can be modified by your function.
0
8991
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9544
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9372
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9324
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
6074
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4606
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4874
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3313
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2783
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.