I came across this article http://www.eskimo.com/~scs/cclass/int/sx5.html
but this part confused me: what's the point of returning the array in send_array_3 if we're already modifying it using send_array or send_array_2 for example? We don't need to return it, right?
void send_array(int a[], int n) {
for (int i=0; i<n; i++)
a[i] = i*i;
}
void send_array_2(int* a, int n) {
for (int i=0; i<n; i++)
a[i] = i*i;
}
int* send_array_3(int a[], int n) {
for (int i=0; i<n; i++)
a[i] = i*i;
return a;
}
They say it's not that useful:
Another difference is that the return value of this latest version of
itoa isn't terribly useful. The pointer which this version of itoa
returns is always the same as the pointer you handed it. Even if this
version of itoa didn't return anything as its formal return value, you
could still get your hands on the string it created, since it would be
sitting right there in your own array (the one that you passed to
itoa). In the case of getline, we had a second thing to return as the
formal return value, namely the length of the line we'd just read.
generally you either allocate memory to a pointer and return the array in a function, you pass in the pointer to the array with memory already allocated, and use any return value for error handling, so you can wrap the function in an if statement or whatever.
You could even pass in the address of an array pointer as an int ** (for an int array) allocate the memory, and then not have to return it.
what you got there are just examples how you can handle the problem of "returning" arrays
three different methods are in here and all should work (i would preffer send_array_2)
Related
I am currently reading understanding pointers in c, am at the section were the author talks about passing arrays to functions. Out of all the bellow patterns which is best to use and why ? , does it have anything to do with optimisation ?
#include <stdio.h>
void passAsPointerWithSize(int * arr, int size) {
for ( int i = 0; i < size; i++ ) {
printf("%d\n", arr[i]);
}
}
void passAsPointerWithoutSize(int * arr) {
while ( *arr ) {
printf("%d\n", *arr);
arr++;
}
}
void passWithoutPointerWithSize( int arr [] , int size) {
for ( int i = 0; i <= size; i++ ) {
printf("%d\n", arr[i]);
}
}
void passWithoutPointerUsingWhile(int arr []) {
int i = 1;
while ( arr[i] ) {
printf("%d\n", arr[i++]);
}
}
int main() {
int size = 5;
int arr[5] = { 1, 2, 3, 4 , 5};
passAsPointerWithSize(arr, size);
passAsPointerWithoutSize(arr);
passWithoutPointerWithSize(arr, size);
passWithoutPointerUsingWhile(arr);
}
i compiled it with -std=gnu11 -O3
In the context of function parameters, int arr [] is the same as int *arr because when an array is passed as a function argument to a function parameter, it decays into a pointer to its first element.
So the following declaration:
void foo(int * arr, int size);
is equivalent to:
void foo(int arr[], int size);
When it comes to the question whether you need the size parameter, you need it in order to determine the length of the array, unless:
there is a special value stored in the array that act as an indicator for the end of array (the callee would be responsible for checking against this indicator).
the length of the array is already known to the caller.
Otherwise, how could you possibly know how many elements the array contains?
Out of all the bellow patterns which is best to use and why ?
With the points above in mind, the only thing you can always choose is whether to use the int * syntax or the int [] one for the function parameter.
Although both are equivalent (as explained above), some people may argue that using int * could suggest that there is at most one element, whereas int [] could suggest thet there there is at least one element and there could be more than one.
does it have anything to do with optimization ?
No, or at least, not directly, whether you need the size parameter is actually a matter of whether the size of the array is known by the caller or it can be obtained by means of a stored end-of-array indicator.
First see which one is correct! (based on what you posted)
void passAsPointerWithSize(int * arr, int size) {
for ( int i = 0; i < size; i++ ) {
printf("%d\n", arr[i]);
}
}
This is the one not invoking Undefined Behavior.
The ones using while won't stop unless they get an element having value 0. What if the array has no 0's ? Then it will access way beyond the memory (which is the case here). Perhaps this echos back to a time when strings used to be marked with zeros at their end, in any case, it's bad practice.
The other for loop is looping till index<=size accessing array index out of bounds when index = size, again, undefined behavior.
Now back to your question..
The syntax func(int arr[],..) is the same as func(int* arr,...) on the context of passing a 1D-array to a function. Arrays are passed as pointers - it doesn't matter how you specify the signature.
Looping? - it's just a matter of choice.
Typos and other things...
Typos are the <= or the i=1 initialization in one of the functions. did you not want to print the 0-th element? Well i=1 and then you start looping - it missed the 0-th element.
A compiler, when passed an array, deals with a pointer to the first element of the array no matter how you write it so the form doesn't matter
How do I know the size of the array passed?
In any of the cases - when you pass an array to a function as a pointer - there is no way to know the length of the array unless you have some placeholder which marks the end of the array. If that is not the case then you have to obviously somehow know the length of it - which is what you do when you pass a parameter named size in the function.
Readability + Choice + ...
Writing it as arr[] can be used to convey the meaning that it is an array when we will deal with that pointer. You may skim through the code and get an idea about what it is getting as arguments and what it will possibly do. One may argue that a comment can still serve that purpose - that's where choice comes into the picture.
Yeah, some of them won't work (what do you mean by the condition *arr for instance? are you trying to bring back null terminated strings? don't!)
But, actually the fastest one (barring some crazy compiler optimization which I for one have not seen in practice) if you don't care about order is iterating backwards
void passAsPointerWithSize(int *arr, int size) {
for ( int i = size - 1; i > 0; i-- ) {
printf("%d\n", arr[i]);
}
}
That's because it saves a whole CPU clock cycle every loop, since after you reduce i (i--) the answer of comparing to zero (i > 0) is already stored in the registers
I started learning C language a week ago.
Just for the test I decided to write a tictactoe game.
I have a field.
int field[3][3];
And a function printField
void printField(int field[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
printf("%i", field[i][j]);
}
printf("\n");
}}
It's working in main like this:
int main(){
printField(field);}
BUT if I change
void printField(int field){...}
or
void printField(int field[][]){...}
It gives me a bunch of errors:
subscripted value is neither array nor pointer nor vector
passing argument 1 of ‘printField’ makes integer from pointer without a cast
note: expected ‘int’ but argument is of type ‘int (*)[3]’
Why can't I pass the array like this?
Are there any more ways to pass it?
The function is independent of any call to the function. So the function cannot guess from the rest of the program what the array size is. In the function body you have to have constants or variables to represent all dimensions.
You can use variables for this instead of fixed size:
void printField(int r, int c, int field[r][c])
{
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
printf("%i", field[i][j]);
printf("\n");
}
And to call the function:
printField(3, 3, field);
You can compute the dimensions from the array's name. Using a macro confines the ugly syntax:
#define printField(a) printField( sizeof(a)/sizeof((a)[0]), sizeof((a)[0]) / sizeof((a)[0][0]), (a) )
int f1[3][3] = { 0 };
printField(f1);
int f2[4][5] = { 0 };
printField(f2);
When you write an array as a function, the compiler will silently "adjust" that array and replace it with a pointer to the first element. So when you write void func (int x[3]) the compiler silently replaces this with void func (int* x) where the pointer points at the first item of the array.
The reason why C was designed this way is not avoid having large arrays getting pushed on the stack, which would be slow and memory-consuming.
In your case, the function void printField(int field[3][3]) gets silently adjusted behind the lines to
void printField(int (*field)[3])
which is an array pointer pointing at the first element, which is a int[3] array. Which can still be used as field[i][j], so all is well. You can pretend that it is an array inside the function.
void printField(int field) obviously doesn't make any sense. This is not an array but a single item. You can't use [] on a plain int and that's what the compiler is telling you: "subscripted value is neither array nor pointer nor vector".
void printField(int field[][]){...} doesn't work either, because an empty [] means "declare an array of incomplete type". It can't be used before the array size is defined.
In case of void printField(int field[]) this happens to work because of the above mentioned "array adjustment" rule of functions. The compiler doesn't have to know the array size, because it just replaces the array with int* anyway.
But in the case with two unknown dimensions, the compiler tries to adjust int field[][] to int (*field)[]. This is a pointer to an array of incomplete type and can't be used by the function.
You could however do int field[][3] and it will work just fine.
In C You can pass you array like this
void printField(int **field){...}
it's much better to work with pointeur than to work with static array :)
A function like that:
int * getRandom( ) {
static int r[10];
int i;
/* set the seed */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i) {
r[i] = rand();
printf( "r[%d] = %d\n", i, r[i]);
}
return r;
}
Is this one possible to be used in Vivado HLS? If possible, how can I initialize an array of unknown size because I cannot use static and malloc anymore?
Converting comments into an answer.
You cannot, in standard C, return an array from a function — you can return a pointer OK (so the code shown is permissible, though it clearly has re-entrancy and threading issues). If you can't use static or malloc() et al, then you need to pass the array to the function for it to fill in instead of returning the array. Then it is the caller's responsibility to allocate the space.
See also srand() — why call it only once.
So you mean I can set a global array as function arguments and give value to each element so I can get the array without using static and malloc?
Yes, or a local array, or an any-other-type of array you care to think of. I think the appropriate implementation might be:
void getRandom(int n_vals, int *i_vals)
{
for (int i = 0; i < n_vals; i++)
i_vals[i] = rand();
}
but the possible variations are legion. You can reinstate the printing if you really want it; you can even call srand() if you really want to (but you should only call that once). You can then use it like:
void somefunc(void)
{
int data[20];
getRandom(15, data);
…use data…;
}
or
static int data[20];
void somefunc(void)
{
getRandom(18, data);
…use data…;
}
or other variants (such as not using static in front of the file-scope definition of data — converting it into a global variable). (Yes, you'd probably use 10 as in the question, or 20 as the amount of space in the array — but 15 and 18 are also OK values in their context.)
I am trying to implement INSERTION SORT here in C, which I think I've done successfully. However, I am having problems in passing arrays as arguments.
I want in place sorting, which means that the original array passed into the insertion_sort function should contain the elements in the sorted array itself.
#include<stdio.h>
int * insertion_sort(int *a,int length)
{
int j;
for(j=1;j<length;j++)
{
int i,key=a[j];
for(i=j-1;j>=0;j--)
{
if(a[i]<=key)
break;
a[i+1]=a[i];
}
a[i+1]=key;
}
return *a;
}
int main(void)
{
int a[]={10,12,7,6,9,8};
insertion_sort(a,6);
int i;
for(i=0; i<6; i++)
printf("%d\n", a[i]);
return 0;
}
EDIT
Nothing gets printed in the output screen.
Help me find the bug here. Thanks !!
1.You probably meant to use i in the inner loop:
Change:
for(i=j-1;j>=0;j--)
^^ ^^
to:
for(i=j-1;i>=0;i--)
2.You don't have to return anything as the original array gets modified (which is just as well since you ignore the returned value).
3.Array index starts from 0. Change outer loop to: for(j=0;j<length;j++)
I have tried (sizeof(array)/sizeof(array[0])). Didn't work.
I wrote a simple function:
int length(int array[]){
int i=0;
while(array[i]) i++;
return i;
}
Worked one minute, didn't work the next.
Someone please help! I'm using Xcode as an IDE
The length of an array is not part of the array in C, so when passing an array as a parameter to a function you should pass its length as a parameter too. Here's an example:
#define ARRLEN(a) (sizeof(a)/sizeof (a)[0]) /* a must be an array, not a pointer */
void printarray(int* a, int alen)
{
int i;
for (i = 0; i < alen; i++)
printf("%d\n", a[i]);
}
main()
{
int a[] = { 3, 4, 5 };
printarray(a, ARRLEN(a));
return 0;
}
However, if your array is defined in such a way as to always end with a sentinel that isn't normal data, then you can traverse the elements until you encounter the sentinel. e.g.,
void printstrings(char** a)
{
int i;
for (i = 0; a[i]; i++)
printf("%s\n", a[i]);
}
main()
{
char* a[] = { "This", "should", "work.", NULL };
printstrings(a);
return 0;
}
Passing an array into a function is the same as passing a pointer to the array.
So sizeof(array)/sizeof(array[0]) does not work.
You can define a global macro:
#define A_LEN(a) (sizeof(a)/sizeof(a[0]))
Try this
main()
{
int a[10] ;
printf("%d\n", sizeof(a)/sizeof(int) ) ;
}
output : 10
See Why doesn't sizeof properly report the size of an array when the array is a parameter to a function? from the comp.lang.c FAQ to understand why the sizeof method doesn't work. You probably should read the entire section on arrays.
Regarding your length function, your "simple" function can work only if your array happens to have the semantic that it is terminated with an element that has the value of 0. It will not work for an arbitrary array. When an array has decayed into a pointer in C, there is no way to recover the size of the array, and you must pass along the array length. (Even functions in the C standard library are not immune; gets does not take an argument that specifies the length of its destination buffer, and consequently it is notoriously unsafe. It is impossible for it to determine the size of the destination buffer, and it therefore cannot prevent buffer overflows.)
There are several methods to get the length of array inside a function (can be in the same file or in different source file)
pass the array length as a separate parameter.
make array length as global extern so that function can directly access global data