Topic: How to declare C-style array parameters?
Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 1999/08/04 Raw View
Thanks to Francis Glassborow and Siemel Naran for your suggestions to
pass C-style arrays by reference. I had never thought of this!
Siemel suggested:
> Pass by reference instead:
> unsigned CalcVolume(const unsigned (&)[3]);
This gives me all the compiler errors I expect from trying to pass an
invalid array parameter. Great!
Of course the drawback is that it does not accept arrays created on the
heap: calling CalcVolume(new unsigned[3]) won't compile. I guess the
only way to get that working is by explicit typecasting. (What I usually
try to avoid.)
In my first posting, I made a mistake about Borland C++ 5.0:
>
> I found out that Borland C++ 5.0 considers a parameter that is
> declared with brackets to be equivalent to a const pointer.
This is only half true. Borland 5.0 considered "const TYPE param[]"
parameters to be const pointers. But "TYPE param[]" are non-const
pointers, according to this compiler.
So the following won't compile for Borland C++ 5.0:
void MyCopy(int piDest[], const int piSource[], unsigned uNrOfElems)
{
while( uNrOfElems > 0 )
{
*piDest = *piSource;
--uNrOfElems;
++piDest; // Okay. (Incrementing a non-const pointer.)
++piSource; // Compiler error: "Cannot modify a const object."
}
}
Is it according to the Standard to generate a compiler error in this
case? What do newer compilers do? (MSVC++ 5.0, Watcom C/C++ 11.0 and
egcs-1.1b g++ compile MyCopy without complaining.)
Regards from Amsterdam,
Niels Dekker
ndekker "at" nki.nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/05 Raw View
In article <37A7166E.96A609E6@REMOVETHISnki.nl>, Niels Dekker
<ndekker@REMOVETHISnki.nl> wrote:
> Thanks to Francis Glassborow and Siemel Naran for your suggestions to
> pass C-style arrays by reference. I had never thought of this!
>
> Siemel suggested:
> > Pass by reference instead:
> > unsigned CalcVolume(const unsigned (&)[3]);
>
> This gives me all the compiler errors I expect from trying to pass an
> invalid array parameter. Great!
>
> Of course the drawback is that it does not accept arrays created on the
> heap: calling CalcVolume(new unsigned[3]) won't compile. I guess the
> only way to get that working is by explicit typecasting. (What I usually
> try to avoid.)
Nope, you can get this too!
typedef unsigned ArrayType [3]; // for clarity
unsigned CalcVolume( const ArrayType& ); // clearer
ArrayType* array = new ArrayType;
CalcVolume( *array ); // yay!
delete [] array;
// this is tricky since you don't see [] in the new, even though
/ it's really there due to the type being a simple array
Of course, I would just put it all in a struct and lose the quirks of an
array (normal delete, doesn't implicitly convert to pointer, can pass by
value, etc.)
struct ArrayType {
unsigned values [3];
};
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: horst.kraemer@snafu.de (Horst Kraemer)
Date: 1999/08/05 Raw View
On 04 Aug 99 07:45:09 GMT, Niels Dekker <ndekker@REMOVETHISnki.nl>
wrote:
> Thanks to Francis Glassborow and Siemel Naran for your suggestions to
> pass C-style arrays by reference. I had never thought of this!
> Siemel suggested:
> > Pass by reference instead:
> > unsigned CalcVolume(const unsigned (&)[3]);
> This gives me all the compiler errors I expect from trying to pass an
> invalid array parameter. Great!
> Of course the drawback is that it does not accept arrays created on the
> heap: calling CalcVolume(new unsigned[3]) won't compile. I guess the
> only way to get that working is by explicit typecasting. (What I usually
> try to avoid.)
or in a more or less clean way by:
unsigned (*p)[3] = new unsigned[1][3];
CalcVolume(*p);
> In my first posting, I made a mistake about Borland C++ 5.0:
> > I found out that Borland C++ 5.0 considers a parameter that is
> > declared with brackets to be equivalent to a const pointer.
> This is only half true. Borland 5.0 considered "const TYPE param[]"
> parameters to be const pointers. But "TYPE param[]" are non-const
> pointers, according to this compiler.
> So the following won't compile for Borland C++ 5.0:
> void MyCopy(int piDest[], const int piSource[], unsigned uNrOfElems)
> {
> while( uNrOfElems > 0 )
> {
> *piDest = *piSource;
> --uNrOfElems;
>
> ++piDest; // Okay. (Incrementing a non-const pointer.)
> ++piSource; // Compiler error: "Cannot modify a const object."
> }
> }
> Is it according to the Standard to generate a compiler error in this
> case?
No. The 'cannot modify a const object' message is simply a bug and
contradicts the C and C++ Standards.
If you declare
void foo( const int a[] );
The parameter 'array of TYPE' is rewritten as 'pointer to TYPE'. Thus
void foo(const int a[]);
is equivalent to
void foo( const int *a );
and
a[0]=0;
shall produce a diagnostic (error message). This is usually not what
you want. Sometimes you want to change the _elements_ of the array
passed to the function.
But
a=0;
shall not because the TYPE is 'const int'. The declaration shall not
be rewritten as
void foo( const int * const a );
> What do newer compilers do? (MSVC++ 5.0, Watcom C/C++ 11.0 and
> egcs-1.1b g++ compile MyCopy without complaining.)
Every other compiler I know (correctly) compiles it without
complaining.
Regards
Horst
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/08/02 Raw View
In article <37A33109.9E091EE9@REMOVETHISnki.nl>, Niels Dekker
<ndekker@REMOVETHISnki.nl> writes
>Also I would like to get a warning for calling CalcVolume like this:
>
> CalcVolume(NULL); // Array parameter can not be NULL.
> unsigned auDims[] = { 256, 256 };
> CalcVolume(auDims); // Array parameter should have 3 elements.
Consider passing your arrays by reference:
CalcVolume( int (& dims)[3]);
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/08/02 Raw View
On 02 Aug 99 05:18:32 GMT, Niels Dekker <ndekker@REMOVETHISnki.nl> wrote:
>When you declare a pointer to a C-style array as function argument,
>there are a few possibilities. I prefer using brackets:
>
>void MyFunc(int piArray[])
> rather than
>void MyFunc(int* piArray)
>
>But is there a difference, according to the C++ Standard?
>And is there consensus that the first notation is better that the
>second, or is it just a matter of taste?
There's no difference.
In the implementation of MyFunc(int*), you can declare the pointer as
const -- ie,
void MyFunc(int *const piArray) { ... piArray=0; /* error! */ }
>unsigned CalcVolume(const unsigned puDims[3])
>{
> // Please warn me against this bug!
> return puDims[1] * puDims[2] * puDims[3];
>}
Despite the '3', this is the same as
unsigned CalcVolume(const unsigned *);
It really should mean pass the array by value. C++ does not let you
pass arrays by value though. Pass by reference instead:
unsigned CalcVolume(const unsigned (&)[3]);
Now a good compiler will give compile time errors if possible if you
access the array out of bounds. Neither of my two compilers do this
though. Compilers can also give run time errors (eg, if they can't
figure out the index at compile time), but few compilers do this.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 1999/08/02 Raw View
When you declare a pointer to a C-style array as function argument,
there are a few possibilities. I prefer using brackets:
void MyFunc(int piArray[])
rather than
void MyFunc(int* piArray)
But is there a difference, according to the C++ Standard?
And is there consensus that the first notation is better that the
second, or is it just a matter of taste?
I found out that Borland C++ 5.0 considers a parameter that is declared
with brackets to be equivalent to a const pointer.
void MyFunc(int piArray[])
{
int* piTemp = new int[8];
// Compiler error in Borland C++ 5.0, because it
// considers the type of piArray to be "int* const"
piArray = piTemp;
}
I very much appreciate Borland for this. But do newer compilers still
support this idea?
Another related issue is whether it makes sense to specify the number of
elements of the array between the brackets.
Suppose I have a function that calculates a volume, given the specified
3 dimensions:
unsigned CalcVolume(const unsigned puDims[3])
{
// Please warn me against this bug!
return puDims[1] * puDims[2] * puDims[3];
}
In this example, is there any new compiler or lint that warns me against
exceeding the array upperbound?
Also I would like to get a warning for calling CalcVolume like this:
CalcVolume(NULL); // Array parameter can not be NULL.
unsigned auDims[] = { 256, 256 };
CalcVolume(auDims); // Array parameter should have 3 elements.
None of the compilers that I use (MSVC++ 5.0, Watcom C/C++ 11.0, Borland
C++ 5.0, egcs-1.1b g++) give a warning in these two cases.
Do newer compilers do this?
And what does the C++ Standard say about specifying the number of
elements between the brackets?
Regards from Amsterdam,
Niels Dekker
ndekker "at" nki.nl
No spam please.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]