Passing an array as argument to a function
-
thanks Greg for that tip
Under C any pointer is already a pointer to an array it's built into the language along with pointer arithmetic ... you need to just learn that. Literally declare any pointer of anything lets do a float float* p; now you can access it as an array p[0] = 5.0; p[100] = 10.0; It will crash because the pointer isn't really to any memory but it makes the point the pointer is already a pointer to an array There are no exceptions to the rule it doesn't matter if the pointer is to a fundamental type or struct .... so I don't get how you could ever forget that. In the C community the [] use is rare because it's two extra characters to type. It also has implication when declaring variables because it puts that array on the stack not on data memory or constant memory (rodata) if it determines its a constant. So if you get into the habit of using that form you can get some undesirable things happen. Personally you are learning and I would learn to live without it and just learn them as you will most often see them written. The topic is well covered in dummies guide to C but you will note the last statement How to Use Arrays and Functions Together in C Programming - dummies[^]
In vino veritas
-
Further to what Richard has said, you could also do some defensive programming by passing in the length of the array. eg:
void myFunc(int* somedata, size_t data_len)
{
for(size_t i = 0; i < data_len; ++i)
somedata[i] *= 2;
return;
}//...
int myArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
const size_t arrLen = sizeof(myArray)/sizeof(myArray[0]);
myFunc(myArray), arrLen);
// ... etcThis will prevent data overflows, and/or segfaults, when accessing myArray inside the function. Things to note: * we can get the compiler to tell us how many elements in the array using the
sizeof(myArray)/sizeof(myArray[0])
construct. This is calculated at compile time and in release mode, in most cases it will be optimized out, so it does not add to your memory usage, if that's a concern. * Using the constantarrLen
means that if we change the number of elements in myArray, we don't need to go through the code and find all uses of myArray and make sure we're passing in the right number * If we had usedarrLen = sizeof(myArray)/sizeof(int)
, we need to remember to change the definition ofarrLen
if we change the type ofmyArray
. Usingsizeof(myArray[0]
mean that if we change the type of myArray fromint[]
todouble[]
, for example, we don't need to remember to change the definition ofarrLen
as wellKeep Calm and Carry On
-
You can write it like this
void myFunc(char somedata[]) // edited to remove * after char: see Richard's post below
to highlight that it's actually an array rather than just a pointer to a single
char
. Given that it's an array, its size is often provided to avoid the kind of trampling that you pointed out:void myFunc(char somedata[], size_t n)
Robust Services Core | Software Techniques for Lemmings | Articles
-
good pick didn't even notice the * because that form is so foreign to me.
In vino veritas
-
There is also the
_countof()
macro, which gives the number of elements in arrays of any simple or composite type.Best macro ever added into C standard ... wish more people would use it.
In vino veritas
-
Best macro ever added into C standard ... wish more people would use it.
In vino veritas
-
There is also the
_countof()
macro, which gives the number of elements in arrays of any simple or composite type. -
Under C any pointer is already a pointer to an array it's built into the language along with pointer arithmetic ... you need to just learn that. Literally declare any pointer of anything lets do a float float* p; now you can access it as an array p[0] = 5.0; p[100] = 10.0; It will crash because the pointer isn't really to any memory but it makes the point the pointer is already a pointer to an array There are no exceptions to the rule it doesn't matter if the pointer is to a fundamental type or struct .... so I don't get how you could ever forget that. In the C community the [] use is rare because it's two extra characters to type. It also has implication when declaring variables because it puts that array on the stack not on data memory or constant memory (rodata) if it determines its a constant. So if you get into the habit of using that form you can get some undesirable things happen. Personally you are learning and I would learn to live without it and just learn them as you will most often see them written. The topic is well covered in dummies guide to C but you will note the last statement How to Use Arrays and Functions Together in C Programming - dummies[^]
In vino veritas
float* p;
now you can access it as an array
p[0] = 5.0;
p[100] = 10.0;I understand "p[0] = 5.0;" since that`s the first element, but then "p[100] = 10.0;" don`t you need to alocate first "p = new float[101]"
-
I didn't know about
_countof()
. Is it an MS only extension? Trying to compile with gcc under linux produces an implicit declaration warning in C and a not declared in this scope in C++Keep Calm and Carry On
-
Right you are! I forget to remove the
*
.Robust Services Core | Software Techniques for Lemmings | Articles
-
thanks Greg for that tip
I made a mistake. See Richard's post below.
Robust Services Core | Software Techniques for Lemmings | Articles
-
I made a mistake. See Richard's post below.
Robust Services Core | Software Techniques for Lemmings | Articles
noticed
-
Right you are! I forget to remove the
*
.Robust Services Core | Software Techniques for Lemmings | Articles
-
Why not leave the
*
but remove the[]
? The parameter is a pointer to an array, not an actual array.I use brackets to indicate that the underlying is an array, not a pointer to a single
char
. Maybe it's because I was a latecomer to C++ and never used C idioms, another one beingif(p)
, for which I writeif(p != nullptr)
.Robust Services Core | Software Techniques for Lemmings | Articles
-
I use brackets to indicate that the underlying is an array, not a pointer to a single
char
. Maybe it's because I was a latecomer to C++ and never used C idioms, another one beingif(p)
, for which I writeif(p != nullptr)
.Robust Services Core | Software Techniques for Lemmings | Articles
A pointer rarely means a pointer to a single item, it always indicates a pointer to a set of items. If you want to pass a single int, char etc, then why use a pointer? I would agree with you on using the
if(p != nullptr)
construct, it makes it much clearer. -
A pointer rarely means a pointer to a single item, it always indicates a pointer to a set of items. If you want to pass a single int, char etc, then why use a pointer? I would agree with you on using the
if(p != nullptr)
construct, it makes it much clearer.Richard MacCutchan wrote:
If you want to pass a single int, char etc, then why use a pointer?
Because it might inadvertently be
nullptr
, and I find this defensive code jarring:void f(type& t)
{
if(&t ! nullptr)...
}The optimize-everything crowd won't agree, but in my opinion code that invokes the above with a null reference should suffer a
SIGSEGV
before the function is called. But since that's not the case...Robust Services Core | Software Techniques for Lemmings | Articles
-
A pointer rarely means a pointer to a single item, it always indicates a pointer to a set of items. If you want to pass a single int, char etc, then why use a pointer? I would agree with you on using the
if(p != nullptr)
construct, it makes it much clearer.Richard MacCutchan wrote:
f you want to pass a single int, char etc, then why use a pointer?
On occasion you want an "out" or sentinel parameter, so in those cases you have to use a pointer (or a reference if using C++). There's lots of cases where you might have a pointer to a single struct that you either want to fill in, or avoid copying the whole thing to the stack. For the latter, of course, you'd mark it as
const
.Keep Calm and Carry On
-
how do you declare and access an array of pointers? if you want to cycle through pointers of same type in a for loop.
int * somedata[] = new int * [5]; ??
"DreamLand Page" on facebook
-
how do you declare and access an array of pointers? if you want to cycle through pointers of same type in a for loop.
int * somedata[] = new int * [5]; ??
"DreamLand Page" on facebook
In that case you'd use another level of indirection: e.g.
#include <iostream>
void myfn(int **data, size_t len)
{
for(size_t i = 0; i < len; ++i)
*data[i] = i * 2; // assign value to address pointed to by data[i]// alternatively : // for(size\_t i = 0; i < len; ++i) // \*\*data++ = i\*2; // Note: use double de-reference and post increment!
}
int main)_
{
int data[5] = { 1, 2, 3, 4, 5 }; // our original data
const size_t ndata = sizeof(data)/sizeof(data[0]);
int** pdata = new int*[ndata]; // double indirection used for definition of pdata// assign each element of pdata the address of element of data for(size\_t i = 0; i < ndata; ++i) pdata\[i\] = &data\[i\]; // or could use pdata\[i\] = data+i; std::cout << "Before:\\n"; for(size\_t i = 0; i < ndata; ++i) std::cout <^lt; \*pdata\[i\] << std::endl; myfn(pdata, 5); std::cout <\*lt; "\\nAfter:\\n"; for(size\_t i = 0; i < ndata; ++i) std::cout << \*pdata\[i\] << std::endl; delete\[\] pdata; return 0;
}
Keep Calm and Carry On
-
how do you declare and access an array of pointers? if you want to cycle through pointers of same type in a for loop.
int * somedata[] = new int * [5]; ??
"DreamLand Page" on facebook