How to pass a pointer to an unknown-size array?

J

Jonathan Bartlett

Now I want to pass a pointer to an array of doubles, the size
of the array must not be fixed though:

Try this:

int func(double *array, int num_elements)
{
int i;
for(i = 0; i < num_elements; i++)
{
array = 1.0;
}
}

int main()
{
double array[100];
func(array, 100);
}

The single pointer will point to the first element of the array. You do
not need double indirection. You need to explicitly pass the size of
the array, as C does not keep that information store.

Jon
 
G

Guest

Hello!

I can pass a "pointer to a double" to a function that accepts
double*, like this:

int func(double* var) {
*var=1.0;
...
}

double var;

n=func(&var);

---

Now I want to pass a pointer to an array of doubles, the size
of the array must not be fixed though:

int func(double[]* array) {
int index;
index=3;
array[index]=1.0;
...
}

double array[100];

n=func(&array);

with the above code the compiler gives me an error. The only
solution that I found so far is this very inelegant one:

int func(void* array) {
int index;
index=3;
*((double*)(array)+index)=1.0;
...
}

double array[100];

n=func(&array);

---

There must be a cleaner way.. but what is it?

I am interested in both C and "C++ only" solutions.

Thanks!
Mike
 
E

Espen Suenson

Now I want to pass a pointer to an array of doubles, the size
of the array must not be fixed though:

int func(double[]* array) {
int index;
index=3;
array[index]=1.0;
...
}

double array[100];

n=func(&array);

The standard way of doing it is like this:

int func(double* array){
array[3]=1.0;
...
}

double array[100];

n=func(array);

The last line is equivalent to this:

n=func(&array[0]);

The reason is that the name of an array is a synonym for the location of
the initial element.

Espen
 
J

john_bode

Hello!

I can pass a "pointer to a double" to a function that accepts
double*, like this:

int func(double* var) {
*var=1.0;
...
}

double var;

n=func(&var);

---

Now I want to pass a pointer to an array of doubles, the size
of the array must not be fixed though:

int func(double[]* array) {
int index;
index=3;
array[index]=1.0;
...
}

double array[100];

n=func(&array);

with the above code the compiler gives me an error. The only
solution that I found so far is this very inelegant one:

int func(void* array) {
int index;
index=3;
*((double*)(array)+index)=1.0;
...
}

double array[100];

n=func(&array);

---

There must be a cleaner way.. but what is it?

I am interested in both C and "C++ only" solutions.

Thanks!
Mike

int func(double *array, size_t arrsize)
{
int index = 3;
if (index < arrsize)
{
array[index]=1.0;
}
...
}

....

double array[100];
int n = func(array, sizeof array);
....

Remember that in C, the subscripting operation a is *defined* as
*(a+i). Therefore, in *most* expression contexts (sizeof() being one
of two exceptions IINM), the type of a is converted from array of T to
pointer to T, and its value is set to the address of the first element
in the array (&a[0]), so the expression *(a+i) yields the correct
result. Because of this conversion, when you pass an array as a
parameter to a function, what you wind up passing is a pointer to the
base type, and its value is the address of the first element (this is
why I didn't use the address operator & in the function call above).

If you need to know the size of the array in the function, you need to
specify the array size as a separate parameter; a pointer doesn't know
the size of the chunk of memory it's pointing to.

If you wished to pass a pointer to the array object (not just a pointer
to the first element), the code would look like this:

int func(double (*array)[100]) // size must match original
{
int index=3;
(*array)[index] = 1.0;
...
}

....
double array[100];
n = func(&array);

This time, we are passing a pointer to a 100-element array of double.
Since 100-element array of double is a distinct type, this approach
won't work for arrays of different sizes.
 
D

doob

For a detailed discussion on passing arrays to funtions in C, I
recommend you refer to Expert C Programming by Peter van der Linden
which has an entire chapter discussing arrays & their relationships
with pointers. This will certainly clarify any issues you may have.
 
J

john_bode

Aaron said:
Hello!

I can pass a "pointer to a double" to a function that accepts
double*, like this:
[snip]


To pass a pointer to the array, not to the first element do:

int func(double **array) { or func(double **array, unsigned size) }

then you can code:
double array[100];
n = func(&array); { or n = func(&array, 100); }

This is not correct. The type of &array is "pointer to 100-element
array of double", *not* "pointer to pointer to double". The correct
prototype is

int func(double (*array)[100]);

You would pass a pointer to pointer to double if you were passing a
pointer to the first element of a 2-d array of double, like so:

double array[5][10];
n = func(array, 5, 10);

int func(double **a, size_t d0, size_t d1);

Since the type "100-element array of double" is a distinct type from
"101-element array of double", the type "pointer to 100-element array
of double" is a distinct type from "pointer to 101-element array of
double", so you don't have to pass the size as a separate parameter;
the array size is specified in the prototype:

int func(double (*array)[100])
{
size_t count = sizeof *array / sizeof (*array)[0];
...
}

This means func() can *only* be called with 100-element arrays of
double.

However, this defeats the OP's purpose, which is to be able to deal
with arrays of any size; this is why he needs to pass a pointer to the
first element and the array size as parameters.
 
J

john_bode

(e-mail address removed) wrote:

[snip]
double array[100];
int n = func(array, sizeof array);

Dammit, that's a bug. That last line *should* read:

int n = func(array, sizeof array / sizeof array[0]);

Back to your regularly scheduled programming...
 
A

Aaron Gage

Hello!

I can pass a "pointer to a double" to a function that accepts
double*, like this:

int func(double* var) {
*var=1.0;
...
}

double var;

n=func(&var);

---

Now I want to pass a pointer to an array of doubles, the size
of the array must not be fixed though:

int func(double[]* array) {
int index;
index=3;
array[index]=1.0;
...
}

double array[100];

n=func(&array);

with the above code the compiler gives me an error. The only
solution that I found so far is this very inelegant one:

int func(void* array) {
int index;
index=3;
*((double*)(array)+index)=1.0;
...
}

double array[100];

n=func(&array);

---

There must be a cleaner way.. but what is it?

I am interested in both C and "C++ only" solutions.

Thanks!
Mike

To pass a pointer to the array, not to the first element do:

int func(double **array) { or func(double **array, unsigned size) }

then you can code:
double array[100];
n = func(&array); { or n = func(&array, 100); }

But why do you require a pointer to the array, and not pointer to first
element??
 
E

E. Robert Tisdale

cat main.c
#include <stdlib.h>
#include <stdio.h>

int doubleArray_fprintf( // total number of characters
FILE* fp, // file pointer
const
char* format, // format for elements
size_t columns, // number of columns
const
size_t n, // array size
const
double array[n] // the array to be printed
) {
columns = (0 < columns)? columns: 4;
int total = 0; // total number of characters
for (size_t j = 0; j < n; ++j) {
int characters = fprintf(fp, " ");
if (0 < characters) {
total += characters;
characters = fprintf(fp, format, array[j]);
if (0 < characters) {
total += characters;
size_t k = j + 1;
if (0 == k%columns && k < n) {
characters = fprintf(fp, "\n");
if (0 < characters) {
total += characters;
}
else {
total = characters;
break;
}
}
}
else {
total = characters;
break;
}
}
else {
total = characters;
break;
}
}
return total;
}

int main(int argc, char* argv[]) {
const
size_t n = 10;
double array[n];
for (size_t j = 0; j < n; ++j) {
array[j] = j;
}

doubleArray_fprintf(stdout, "%g", 5, n, array);
fprintf(stdout, "\n");

return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
0 1 2 3 4
5 6 7 8 9
 
T

Tim Rentsch

Aaron said:
Hello!

I can pass a "pointer to a double" to a function that accepts
double*, like this:
[snip]


To pass a pointer to the array, not to the first element do:

int func(double **array) { or func(double **array, unsigned size) }

then you can code:
double array[100];
n = func(&array); { or n = func(&array, 100); }

This is not correct. The type of &array is "pointer to 100-element
array of double", *not* "pointer to pointer to double". The correct
prototype is

int func(double (*array)[100]);

That's one correct prototype. Another one is:

int func( double (*array)[] );

Or, perhaps more usefully:

int func( double (*array)[], unsigned index_limit );

This allows arrays of all sizes to be passed. And, it offers a
potentially useful check, in that only arrays can be passed. So, if
we have:

#define FUNC(a) ( func( &(a), sizeof( a ) / sizeof *(a) ) )

then FUNC will work on arrays, but pointers will get (are required to
get?) a diagnostic about "incompatible types".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top