Code:
/*
* code.c
*/
#include <stdio.h>
void printArray(int iXArray, int iSize);
int main() {
int array1[] = {7, 9, 3, 18};
int *array2[] = {array1 + 0, array1 + 1, array1 + 2, array1 + 3};
printArray(array2, 4);
return 0;
}
// This should print the values in array1
void printArray(int iXArray, int iSize) {
int iCntr;
for (iCntr = 0; iCntr < iSize; iCntr++) {
printf("%d ", *iXArray[iCntr]);
}
printf("\n");
}
My compiler doesn't approve of this code.
- [Warning] passing arg 1 of `printArray' makes integer from pointer without a cast
- printArray(array2, 4);
- [Error] subscripted value is neither array nor pointer
- printf("%d ", *iXArray[iCntr]);
What am I doing wrong, and why? How do I fix this?
Try this:
void printArray(int **iXArray, int iSize) ...
In your example you provide an array of (int*) so reference it as one, you must tell the compiler to expect an array of pointers.
By default passing an array is by reference. If you change the array's content, it changes at the callee's side aswell. The pointer itself is passed by value, so changing the value of the iXArray parameter (iXArray = (int**)123;) will not change the array2 pointer at the callee's side.
If you want to pass the array by value, will need to wrap it in a value type:
typedef struct {
int A[123];
} Array;
Array incrementArray(Array array, int count) {
for (int i=0; i<count; i++) {
array.A[i]++;
}
return array;
}
You are passing an array of pointers to int:
void printArray(int *ixArray[], int iSize)
This works also:
/*
* code.c
*/
#include <stdio.h>
void printArray(int **iXArray, int iSize);
int main() {
int array1[] = {7, 9, 3, 18};
int *array2[] = {array1 + 0, array1 + 1, array1 + 2, array1 + 3};
printArray(array2, 4);
return 0;
}
// This should print the values in array1
void printArray(int **iXArray, int iSize) {
int iCntr;
for (iCntr = 0; iCntr < iSize; iCntr++) {
printf("%d ", *iXArray[iCntr]);
}
printf("\n");
}
Pointer arithmetics works perfectly.
Regarding the "stay untouched". You are passing things by reference so the way to keep them from being edited is to make them const. You have a couple different options based on what part you don't want to change. However, that won't let you change them in you function. What it sounds like is you want a pass-by-value which you can't get in C++ using arrays unless you make your own manual copy.
This seems to work without making array1 editable by printArray.
/*
* code.c
*/
#include <stdio.h>
void printArray(int *iXArray[], int iSize);
int main() {
int array1[] = {7, 9, 3, 18};
int *array2[] = {&array1[0], &array1[1], &array1[2], &array1[3]};
printArray(array2, 4);
return 0;
}
// This should print the values in array1
void printArray(int *iXArray[], int iSize) {
int iCntr;
for (iCntr = 0; iCntr < iSize; iCntr++) {
printf("%d ", *iXArray[iCntr]);
}
printf("\n");
}
Related
With my programm I try to change the order of numbers in the int array. To the first function, I just passed both arrays and printed the array called arraytemp with the changed order. After that I printed in the main function the same array, just to see if the array was filled too. I havented used any pointers in the first function - how did the array got filled? Does the arrays adress get passed to functions anyway?
Then I wanted to pass arrays with the same content to the second function, but this time I used pointers. I have no clue, how to get the same result printed, because I get a stack smashing error. I am kinda comfused with '*' and '&'. So, how should I pass these arrays when using pointers?
#include <stdio.h>
void switchnum (int arraytemp[6], int array[], int laenge) {
printf("\n\nAfter (in function 1):\n");
for(int i = 0 ; i<laenge ; i++) {
arraytemp[i] = array[laenge-1-i];
printf("%d ", arraytemp[i]);
}
return 0;
}
void switchnum2 (int *arraytemp2[6], int array2[], int laenge2) {
printf("\nAfter (in function2):\n");
for(int j = 0 ; j<laenge2 ; j++) {
arraytemp2[j] = array2[laenge2-1-j];
printf("%d ", arraytemp2[j]);
}
return 0;
}
int main() {
int array[] = {4,8,1,3,0,9};
int arraytemp[6];
printf("Before (main):\n");
for(int i = 0 ; i<6 ; i++) {
printf("%d ", array[i]);
}
switchnum(arraytemp, array, 6);
printf("\nAfter (in main):\n");
for(int i = 0 ; i<6 ; i++) {
printf("%d ", arraytemp[i]);
}
int array2[] = {4,8,1,3,0,9};
int arraytemp2[6];
switchnum2(arraytemp2, array2, 6);
return 0;
}
The compiler adjusts a parameter having an array type to pointer to the array element type.
So this function declaration
void switchnum (int arraytemp[6], int array[], int laenge);
is equivalent to the following declaration
void switchnum (int arraytemp[], int array[], int laenge);
and the same way is equivalent to the following declaration
void switchnum (int *arraytemp, int *array, int laenge);
As for this function declaration
void switchnum2 (int *arraytemp2[6], int array2[], int laenge2);
then it is adjusted by the compiler to the declaration
void switchnum2 (int **arraytemp2, int *array2, int laenge2);
So the used argument expression and the function parameter have incompatible pointer types.
Pay attention to that in this call
switchnum(arraytemp, array, 6);
the both arrays are converted to pointers to their first elements of the type int *.
In fact this call is equivalent to
switchnum( &arraytemp[0], &array[0], 6);
How to pass pointer of arrays to functions
In this case you are trying to pass an array of pointers to a function and not a pointer of arrays:
void switchnum2(
int* arraytemp2[6], int array2[], int laenge2)
Maybe it helps to see the output of this example program, as it shows the output of many of your cases
Example
#include <stdio.h>
void test_arr(int*[6]);
int main(void)
{
int array[] = {4, 8, 1, 3, 0, 9};
int* pArr[6] = {0}; // 6 pointers to int
printf("original vector in main(): ");
for (int i = 0; i < 6; i += 1) printf("%d ", array[i]);
printf("\n");
for (int i = 0; i < 6; i++) pArr[i] = &array[i];
test_arr(pArr);
printf("\nIn main() &array[0] = %p\n", &array[0]);
return 0;
}
void test_arr(int* pInt[6])
{
printf("In test_array(): ");
for (int i = 0; i < 6; i += 1)
printf("%d ", *pInt[i]);
printf("\n");
int* myP = *pInt;
printf("*pInt\tpoints to value %d\n", *myP);
myP = pInt[0];
printf("pInt[0]\tpoints to value %d\n", *myP);
int x = *pInt[0];
printf("*pInt[0] = %d\n", x);
printf("\ntest_array() &pInt[0] = %X\n", pInt[0]);
return;
}
output
original vector in main(): 4 8 1 3 0 9
In test_array(): 4 8 1 3 0 9
*pInt points to value 4
pInt[0] points to value 4
*pInt[0] = 4
test_array() &pInt[0] = 197BFB00
In main() &array[0] = 000000CF197BFB00
Your program with some changes in the functions
I changed some lines in your code to get the expected result
#include <stdio.h>
void switch1(const int[],int[],const int);
void switch2(const int[],int*[],const int);
void show_array(const int[6],const char*);
int main(void)
{
int arr_out[] = {0,0,0,0,0,0};
show_array(arr_out, "arr_out in main()");
// call 1st function
printf("switch1() uses int[] as output\n");
switch1((int[6]){6, 5, 4, 3, 2, 1}, arr_out, 6);
show_array(arr_out, "arr_out using 6..1 array as input and 1st function");
// for 2nd function we need an array of pointers
int* pArr[6] = {0}; // 6 pointers to int
for (int i = 0; i < 6; i++) pArr[i] = &arr_out[i];
printf("switch2() uses int*[] as output\n");
switch2((int[6]){1, 2, 3, 4, 5, 6}, pArr, 6);
show_array(arr_out, "arr_out using 1..6 array as input and 2nd function");
return 0;
}
void switch1(const int in[], int out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
out[i] = in[laenge - 1 - i];
}
void switch2(const int in[], int* out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
*out[i] = in[laenge - 1 - i];
}
void show_array(const int array[6], const char* msg)
{
printf("%s:\t", msg);
for (int i = 0; i < 6; i++) printf("%d ", array[i]);
printf("\n");
}
output of the modified code
arr_out in main(): 0 0 0 0 0 0
switch1() uses int[] as output
arr_out using 6..1 array as input and 1st function: 1 2 3 4 5 6
switch2() uses int*[] as output
arr_out using 1..6 array as input and 2nd function: 6 5 4 3 2 1
about the changes
void show_array(const int array[6], const char* msg)
{
printf("%s:\t", msg);
for (int i = 0; i < 6; i++) printf("%d ", array[i]);
printf("\n");
}
This function is a helper to show the array contents and accepts a title. Very convenient here
the 2 functions has no output (printf() calls)
parameters are declared const so we can build the vector at the function call
I am using shorter names and changed the order of arguments to input and then output
void switch1(const int in[], int out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
out[i] = in[laenge - 1 - i];
}
void switch2(const int in[], int* out[], const int laenge)
{
for (int i = 0; i < laenge; i++)
*out[i] = in[laenge - 1 - i];
}
Here you see the difference between the 2 functions: a single asterisk.
But in order of using the second function you need to build the vector of pointers as here
// call 1st function
printf("switch1() uses int[] as output\n");
switch1((int[6]){6, 5, 4, 3, 2, 1}, arr_out, 6);
show_array(arr_out, "arr_out using 6..1 array as input and 1st function");
// for 2nd function we need an array of pointers
int* pArr[6] = {0}; // 6 pointers to int
for (int i = 0; i < 6; i++) pArr[i] = &arr_out[i];
printf("switch2() uses int*[] as output\n");
switch2((int[6]){1, 2, 3, 4, 5, 6}, pArr, 6);
show_array(arr_out, "arr_out using 1..6 array as input and 2nd function");
Let's consider the following example :
#include <stdio.h>
void change_byte(int *byte);
int main()
{
int byte = 0;
change_byte(&byte);
printf("Byte : %d \r\n", byte);
}
void change_byte(int *byte)
{
*byte= 5;
}
I am simply changing the value of an integer inside a function by passing the integer as a pointer to the function. It yields :
Byte : 5
Everything's fine.
I want to generalize the function to modify an array of integer instead of an integer. Here is the code :
#include <stdio.h>
#define SIZE_ARRAY 10
void change_array(int *array, int size);
int main()
{
int array[SIZE_ARRAY] = {0};
change_array(array, SIZE_ARRAY);
printf("Array : ");
for(int i = 0 ; i < SIZE_ARRAY ; i++)
{
printf("%d ", array[i]);
}
}
void change_array(int *array, int size)
{
for(int i = 0 ; i < size ; i++)
{
array[i] = 5;
}
}
It yields :
Array : 5 5 5 5 5 5 5 5 5 5
I like it because it does not make use of dynamic allocation, but I have trouble understand how it works. From what I understand, array gets converted into a pointer when entering the function change_array. But when I was changing the value of byte in the previous example, I was doing *byte = 5. Here, I am doing array[i] = 5 and not *array[i] = 5.
Finally, I want to change the previous example to modify array based on a global array :
#include <stdio.h>
#define SIZE_ARRAY 10
int global_array[10] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
void change_array(int *array, int size);
int main()
{
int array[SIZE_ARRAY] = {0};
change_array(array, SIZE_ARRAY);
printf("Array : ");
for(int i = 0 ; i < SIZE_ARRAY ; i++)
{
printf("%d ", array[i]);
}
}
void change_array(int *array, int size)
{
array = global_array;
}
It yields :
Array : 0 0 0 0 0 0 0 0 0 0
Why is it so ? What to I need to change to make it work ?
Thanks.
Consider your first program.
#include <stdio.h>
void change_byte(int *byte);
int main()
{
int byte = 0;
change_byte(&byte);
printf("Byte : %d \r\n", byte);
}
void change_byte(int *byte)
{
*byte= 5;
}
In this program the object byte is passed to the function change_byte by reference through a pointer to it
change_byte(&byte);
In C passing by reference means passing an object indirectly through a pointer tp it.
So dereferencing the pointer byte declared as a function parameter
void change_byte(int *byte);
you get a direct access to the pointed object byte of the type int defined in main.
Now let's consider your second program
#include <stdio.h>
#define SIZE_ARRAY 10
void change_array(int *array, int size);
int main()
{
int array[SIZE_ARRAY] = {0};
change_array(array, SIZE_ARRAY);
printf("Array : ");
for(int i = 0 ; i < SIZE_ARRAY ; i++)
{
printf("%d ", array[i]);
}
}
void change_array(int *array, int size)
{
for(int i = 0 ; i < size ; i++)
{
array[i] = 5;
}
}
In main you declared an integer array
int array[SIZE_ARRAY] = {0};
Array designators used in expressions with rare exceptions are converted to pointers to their first elements.
Thus this call
change_array(array, SIZE_ARRAY);
is equivalent to
change_array( &array[0], SIZE_ARRAY);
So dereferencing the pointer within the function you can change the first element of the array defined in main.
But array elements are stored in a continuous extent of memory. So using the pointer arithmetic and having a pointer to the first element of an array you can access all elements of the array.
In fact all elements of the array array are passed to the function change_array by reference through a pointer to the first element of the array.
For example the for loop within the function you could rewrite like
for(int i = 0 ; i < size ; i++)
{
*( array + i ) = 5;
}
Now let's consider your third program.
#include <stdio.h>
#define SIZE_ARRAY 10
int global_array[10] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
void change_array(int *array, int size);
int main()
{
int array[SIZE_ARRAY] = {0};
change_array(array, SIZE_ARRAY);
printf("Array : ");
for(int i = 0 ; i < SIZE_ARRAY ; i++)
{
printf("%d ", array[i]);
}
}
void change_array(int *array, int size)
{
array = global_array;
}
As it was pointed out already the array array passed to the function change_array is converted to a pointer to its first element.
You may imagine the function call and its definition the following way (I will rename the first function parameter that to avoid name ambiguity).
change_array(array, SIZE_ARRAY);
//...
void change_array( /* int *parm_array, int size */)
{
int * parm_array = array;
int size = SIZE_ARRAY;
parm_array = global_array;
}
That is function parameters are its local variables. The parameter parm_array is alive until the function stops its execution.
Thus this statement
parm_array = global_array;
assign the pointer to the first element of the global array global_array to the local variable parm_array of the function. This assignment does not touch in any way the array array defined in main. It only changes the local variable parm_array declared in the function change_array.
To achieve the expected by you result you could define in main a pointer that is initialized by the array array. And in the function change_array you could reassigned the pointer with the array global_array passing it to the function by reference the same way as you passed the object byte in your first program.
Here is a demonstrative program.
#include <stdio.h>
#define SIZE_ARRAY 10
int global_array[10] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
void change_array( int **array_ptr );
int main()
{
int array[SIZE_ARRAY] = {0};
int *array_ptr = array;
change_array( &array_ptr );
printf("Array : ");
for(int i = 0 ; i < SIZE_ARRAY ; i++)
{
printf("%d ", array_ptr[i]);
}
}
void change_array( int **array_ptr )
{
*array_ptr = global_array;
}
The program output is'
Array : 5 5 5 5 5 5 5 5 5 5
For a better understanding (and exercise), edit your function
void change_array(int *array, int size)
{
array = global_array;
}
to
void change_array(int *array, int size)
{
array = global_array;
for (int i=0; i < size; ++i)
printf("%d ", array[i]);
}
Ask yourself, what the output 'means'.
I need to write a function which gets an array, it's size and a pointer, I need to check if the pointer exists in the array and if so, print all the elements after it and i'm not allowed to create local variables or use [].
This is what i did to find whether the pointer exists or not.
void printAfterX(int* arr, int n, int* x)
{
if (x < (arr + n) && x >= arr)
{
}
}
Thank you.
I'll give you two hints:
(1) Function parameters are l-values.
(2) Eventually recursion.
You should try both, even if recusion is an overkill here.
since the pointer exists
for(x; x < (arr + n); x++){
printf("%i\n", *x);
}
should do the job
You can use the operator + for this situation who works exactly like [] on pointers at this situation.
At Pseudo it's look like that:
void printAfterX(int* arr, int n, int* x)
{
if arr < x < arr+n{
print array(x)
}
}
Assuming your main data type is int, and that you want to match the content pointed by the pointer (not the pointer itself), here's a working solution:
#include <stdio.h>
void printAfterX(int*, int, int*);
int main() {
int array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int sizeOfArray = 10;
int *pointerX = &array[4];
printAfterX(array, sizeOfArray, pointerX);
return 0;
}
void printAfterX(int* arr, int n, int* x) {
// Iterates over given array
for (int i = 0; i < n; i++) {
// If contents match
if(*(arr + i) == *x) {
for(int j = i + 1; j < n; j++) {
// Print all elements after found element
// (not-inclusive, i.e. j = i + 1)
printf("%d ", *(arr + j));
}
break; // break outer loop, because job's done
}
}
printf("\n"); // Line feed at end of iteration
}
This should also work:
bool SearchForPointer(int* arr, int n, int* x)
{
if( 0 == n)
return false;
if( arr == x)
{
while( --n)
{
arr++;
::printf( "Pointer: 0x%08X; Value: %d;\r\n", (intptr_t)(arr), *(arr));
}
return true;
}
return SearchForPointer( ++arr, --n, x);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int* p = arr+2;
::printf( "Searching for: p = 0x%08X; value: %d\r\n", (intptr_t)p, *p);
SearchForPointer( arr, 5, p);
return 0;
}
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 8 years ago.
I'm trying to pass an array of pointers to a function, without the need to define the size.
Also the output is a warning "initialization makes pointer from integer without cast.
Mostly interested in passing array of pointers rather than an array because I'm trying to understand how to deal with the instance when Data is a dynamically allocated memory using malloc
Why is this happening, and how can I pass an array of pointers as an argument, without the need to define its size?
Code:
#include <stdio.h>
void printData(int *data[]);
void main (int argc,char *argv[]){
int *Data[] = {4, 8, 15, 16, 23, 42};
printData(Data);
}
void printData(int *data[]){
int **cur_data = data;
int counter = sizeof(data)/sizeof(int);
for(int i = 0; i<counter; i++){
printf("%d. %d\n", i, *cur_data);
cur_data++;
}
}
Warning:
main.c: In function ‘main’:
main.c:9: warning: initialization makes pointer from integer without a cast
main.c:9: warning: initialization makes pointer from integer without a cast
main.c:9: warning: initialization makes pointer from integer without a cast
main.c:9: warning: initialization makes pointer from integer without a cast
main.c:9: warning: initialization makes pointer from integer without a cast
main.c:9: warning: initialization makes pointer from integer without a cast
gcc main.o -o run
Run:
0. 4
You can't, an array decays into a pointer when is passed to a function, pass counter as a parameter to printData:
#include <stdio.h>
void printData(int *data, int counter);
int main(void)
{
int Data[] = {4, 8, 15, 16, 23, 42};
int counter = sizeof(Data) / sizeof(int);
printData(Data, counter);
return 0;
}
void printData(int *data, int counter)
{
for (int i = 0; i < counter; i++){
printf("%d. %d\n", i, data[i]);
}
}
Or you can store the counter into the first element of array:
#include <stdio.h>
void printData(int *data);
int main(void)
{
int Data[] = {0, 4, 8, 15, 16, 23, 42};
Data[0] = sizeof(Data) / sizeof(int) - 1;
printData(Data + 1);
return 0;
}
void printData(int *data)
{
int counter = data[-1];
for (int i = 0; i < counter; i++){
printf("%d. %d\n", i, data[i]);
}
}
Here's the corrected program, when you pass an array to a function, it becomes a pointer and loses its size information, so needs to pass separately
#include <stdio.h>
void printData(int *data, int size);
int main (int argc,char *argv[]){
int Data[] = {4, 8, 15, 16, 23, 42};
printData(Data, sizeof(Data));
return 0;
}
void printData(int *data, int size){
int *cur_data = data;
int counter = size/sizeof(int);
for(int i = 0; i<counter; i++){
printf("%d. %d\n", i, *cur_data);
cur_data++;
}
}
and the output is:
0. 4
1. 8
2. 15
3. 16
4. 23
5. 42
You declared array Data as an array of pointers but initialized it with integral constants instead of addresses.
int *Data[] = {4, 8, 15, 16, 23, 42};
So the compiler issues diagnostic messages.
You can do the task the following way that is by using a sentinal value that in this case is equal to NULL.
#include <stdio.h>
#include <stdlib.h>
void printData( int *data[] );
int main(void)
{
int Values[] = { 4, 8, 15, 16, 23, 42 };
const size_t N = sizeof( Values ) / sizeof( *Values );
int *Data[N+1];
size_t i;
i = 0;
for ( ; i < N; i++ )
{
Data[i] = malloc( sizeof( int ) );
*Data[i] = Values[i];
}
Data[i] = NULL;
printData( Data );
for ( i = 0; i < N + 1; i++ ) free( Data[i] );
return 0;
}
void printData( int *data[] )
{
int **p = data;
size_t i = 0;
for( ; *p != NULL; ++p, ++i )
{
printf("%d. %d\n", i, **p );
}
}
The output is
0. 4
1. 8
2. 15
3. 16
4. 23
5. 42
Take into account that function main shall have return type int
Where-
int *Data[];
where data is a array of pointer to an integer. This array pointer can point to 1D arrays or integer. But you are filling with integer data. For 1D array use
int Data[]={4, 8, 15, 16, 23, 42};
And there is no way to know the size of the array using pointer! Only way is pass the no of element to the function with address of an array!
Try these changes-
#include <stdio.h>
void printData(int *data,int element);
void main (int argc,char *argv[]){
int Data[] = {4, 8, 15, 16, 23, 42};
printData(Data,6);
}
void printData(int *data, int element){
int *cur_data = data;
int counter = (sizeof(data)*element)/sizeof(int);
for(int i = 0; i<counter; i++){
printf("%d. %d\n", i, *cur_data);
cur_data++;
}
}
I wrote the following insertion sort yesterday (I started learning C 3 days ago). For some reason, the sort does not modify the array AT ALL.
#include <stdio.h>
int *insert(int arr[], int index, int item);
int *isort(int arr[]);
int main() {
int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
int *b = isort(a);
for (int i = 0; i < 17; i += 1) {
printf("%d ", b[i]);
}
return 0;
}
int *insert(int arr[], int index, int item) {
--index;
while (index >= 0 && item < arr[index]) {
arr[index + 1] = arr[index];
--index;
}
arr[index + 1] = item;
return arr;
}
int *isort(int arr[]) {
for (int i = 1; i < sizeof(arr) - 1; i++) {
arr = insert(arr, i, arr[i]);
}
return arr;
}
I'm thinking it could be my compiler, as I'm running a compiler that is on a non unix machine: lcc-win, but I'm not sure. Is there some fundamental thing I'm missing here?
int *isort(int arr[]) {
for (int i = 1; i < sizeof(arr) - 1; i++) {
arr = insert(arr, i, arr[i]);
}
return arr;
}
In this function sizeof(arr) actually returns the size of the pointer and not the size of the array.
In C a special rule says an array parameter is actually adjusted to a parameter of the corresponding pointer type.
That is:
int *isort(int arr[]) { /* ... */ }
is equivalent to this:
int *isort(int *arr) { /* ... */ }
To fix this, add a new parameter in your function that takes the size of the array:
int *isort(int arr[], size_t size) { /* ... */ }
The first problem, as has been pointed out, is that the isort function uses the sizeof operator on a pointer. The way C treats arrays is a little strange at first glance. The name of an array is a pointer to its first element. So when you call isort like this:
int *b = isort(a);
you are simply pushing a pointer to the array onto the stack. In the definition of isort,
int *isort(int arr[])
declares arr to be a pointer to int just like
int *isort(int *arr)
C is even more confusing in this respect: if you had said:
int *isort(int arr[17])
the arr variable is still just a pointer to int ... the "17" here is discarded! Even with this syntax, sizeof(arr) will still be the size of a pointer to int.
On a 32-bit system (ILP32), sizeof(arr) will always be 4, however big the array is.
Therefore, you need to pass the size of the array to isort. A good general way to do this is to define a macro like this:
#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))
This will calculate the number of elements in an array of any type.
Your next problem is more a style one than an actual error:
arr = insert(arr, i, arr[i]);
This calls the insert function with a reference to "arr". The array is modified through this reference, and then a pointer to that array is returned. It will always be the same pointer as you sent in the first place, so this assignment actually does nothing, harmlessly. Like I say, a style problem, not a code error.
The final issue is your isort function stops one short (after you correct the sizeof problem), since you went from 1 to sizeof-1. Here is a fixed version:
#include <stdio.h>
#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))
int *insert(int arr[], int index, int item);
int *isort(int arr[], size_t nitems);
int main() {
int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
int *b = isort(a, NITEMS(a));
for (int i = 0; i < NITEMS(a); i += 1) {
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
int *insert(int arr[], int index, int item) {
--index;
while (index >= 0 && item < arr[index]) {
arr[index + 1] = arr[index];
--index;
}
arr[index + 1] = item;
return arr;
}
int *isort(int arr[], size_t nitems) {
for (int i = 1; i < nitems; i++) {
insert(arr, i, arr[i]);
}
return arr;
}