call by pointers and call by value C - c

How to write this C program pass by pointers and pass by value? I created this program that generates a 10x10 array from -100 to 100 and the main diagonal is read from bottom to top, but I do not know how to create two other programs that are pass by pointers and value
I have to write two more programs with the same input and output only through these two methods. I am a beginner in C and I do not know how to make this.
#include <stdio.h>
#include <stdlib.h>
#define N 10
#define M 10
int my_rand(int max, int min)
{
return (min + rand() / (RAND_MAX / (max - min + 1) + 1));
}
void generate_array(int(*array)[M])
{
printf("Table:");
for (int i = 0; i < N; i++)
{
printf("\n");
for (int j = 0; j < M; j++)
{
array[i][j] = my_rand(-100, 100);
printf("%4d ", array[i][j]);
}
}
}
void print_diagonal(int(*array)[M])
{
printf("\n\nThe main diagonal read from bottom to top:\n");
for (int i = N - 1; i >= 0; i--)
{
printf("%4d ", array[i][i]);
}
}
int *create_array(int(*array)[M])
{
static int new_array[M] = { 0 };
for (int i = 0; i < N; i++)
new_array[i] = array[i][i];
return new_array;
}
void reverseArray(int arr[], int start, int end)
{
int temp;
while (start < end)
{
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
void printArray(int arr[])
{
int i;
for (i = N; i < N; i++)
printf("%4d ", arr[i]);
printf("\n");
}
int main(void)
{
int array1[N][M] = { 0 }, *aux_array;
generate_array(array1);
print_diagonal(array1);
aux_array = create_array(array1);
reverseArray(aux_array, 0, N - 1);
printArray(aux_array);
}
Any help would be much appreciated.

C only supports pass by value. The formal argument in the function definition is always a different object in memory from the actual argument in the function call (assuming the actual argument is itself an object, which it doesn't have to be).
We can fake pass-by-reference semantics by passing a pointer (which is passed by value). Here's a typical example:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
Instead of receiving to integer objects, we receive pointers to two integer objects. We use the unary * operator to dereference the pointers and access the pointed-to objects. If we call that function like so:
int main( void )
{
int x = 1;
int y = 2;
...
swap( &x, &y );
...
return 0;
}
Given the above code, the following are true when we enter the swap function:
a == &x // int *
*a == x == 1 // int
b == &y // int *
*b == y == 2 // int
After we execute the body of the swap function, the following are true:
a == &x // no change
*a == x == 2
b == &y // no change
*b == y == 1
Where things get weird is when you pass array expressions as function arguments. C has a rule that when an array expression is not the operand of the sizeof or unary & operators, or is not a string literal used to initialize a character array in a declaration, the expression is converted ("decays") from an array type to a pointer type, and the value of the expression is the address of the first element.
IOW, given the code
int arr[10];
foo( arr );
Since it's not the operand of the sizeof or unary & operators, the expression arr in the call to foo is automatically converted from type "10-element array of int" to "pointer to int", and the value that gets passed to foo is the address of the first element; IOW, that call is identical to writing
foo( &arr[0] );
and the function definition would be written as
void foo( int *a ) // or int a[], which means the same thing
{
// do something with a[i]
}
IOW, you cannot pass arrays by value in C.
So, looking at your code:
int my_rand(int max, int min)
Both max and min are being passed by value
void generate_array(int(*array)[M])
void print_diagonal(int(*array)[M])
These are receiving a pointer to the first element of a 2D array, so we're faking pass-by-reference.
void reverseArray(int arr[], int start, int end)
We're receiving a pointer to first element of the array (T a[] and T a[N] are both interpreted as T *a in a function parameter declaration), start and end are being passed by value.
void printArray(int arr[])
Again, we're receiving a pointer to the first element of the array.

Related

Getting address boundary error when working with pointers in C

The following code gives me a terminated by signal SIGSEGV (Address boundary error):
void rec(int x, int *arr, int *size) {
if (x < 0) {
rec(-x, arr, size);
return;
}
arr = realloc(arr, sizeof(int) * ++(*size));
*(arr + (*size) - 1) = x % 10;
if (x % 10 != x)
rec(x / 10, arr, size);
}
int main() {
int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));
*size = 0;
rec(20, arr, 0);
}
I already figured our that the arr counter in the main method won't hold the desired result, but I still can't understand why I'm getting an error.
Notice that you are passing NULL as third argument:
rec(20, arr, 0); // 0 is NULL
and you get a segfault dereferencing it:
arr = realloc(arr, sizeof(int) * ++(*size)); // here size is `NULL`
try with
rec(20, arr, size);
For starters these memory allocations
int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));
does not make a sense. They are redundant.
You could just write
int *arr = NULL;
size_t size = 0;
Secondly the variable size is declared but not used because instead of the variable you passed the integer constant 0
rec(20, arr, 0);
So within the function rec
void rec(int x, int *arr, int *size);
the pointer size was initializer by the null pointer constant 0. That is size is a null pointer within the function and using a null pointer to access memory results in undefined behavior.
Also you should pass the pointer to the function by reference. Otherwise passing it to the function does not make a great sense because the pointer in main will not be changed.
The code in main could look like
int *arr = NULL;
size_t size = 0;
rec( 20, &arr, &size );
Pay attention to that you should free all the allocated memory when it will not be used any more.
Correspondingly the function should be declared like
void rec(int x, int **arr, size_t *size);
Use the type size_t instead of the type int because this unsigned integer type is the type of the second argument of the function realloc.
In general to get the result of realloc you should use an intermediate variable because the function can return a null pointer and the current pointer will be lost.
Also pay attention to that the call of the function is unsafe and can result in an infinite recursion due to this if statement
if (x < 0) {
rec(-x, arr, size);
return;
}
when the user passes to the function the value of x equal to INT_MIN.
Consider the following demonstrative program.
#include <stdio.h>
#include <limits.h>
int main(void)
{
int x = INT_MIN;
printf( "x = %d\n", x );
printf( "-x = %d\n", -x );
return 0;
}
Its output might look like
x = -2147483648
-x = -2147483648
As you can see negating the value of the variable x you get the same negative value. So maybe it is better to declare the first function parameter as having the type unsigned int.
Your function can look for example the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
int rec( unsigned int x, unsigned int **arr, size_t *size )
{
const unsigned int Base = 10;
unsigned int *tmp = realloc( *arr, sizeof( int ) * ++*size );
int success = tmp != NULL;
if ( success )
{
*arr = tmp;
*( *arr + *size - 1 ) = x % Base;
if ( x % Base != x )
{
success = rec( x / Base, arr, size );
}
}
return success;
}
int main(void)
{
unsigned int *arr = NULL;
size_t size = 0;
rec( 123456789, &arr, &size );
for ( size_t i = 0; i < size; i++ )
{
printf( "%u", *( arr + i ) );
}
putchar( '\n');
free( arr );
return 0;
}
The program output is
987654321

Passing array of structs with reference - segmentation fault

#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X** a, int size){
for (int i = 0;i < size; i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container = (struct X*)malloc(sizeof(struct X) * n);
read_record(&container, n);
}
I created a 1D array of size n, then I passed it by reference to the function read_record. However, when I execute the program, there is a segmentation fault. What is the problem?
EDIT:
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. That's why I want to send the array as a reference. If I did it in main then I would write:
container = realloc(container, (n + 10) * sizeof(Struct X));
How can I do this in the function?
container is already a pointer, you don't need to pass the address-of the pointer, instead:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X *a, size_t size)
{
for (size_t i = 0; i < size; i++) {
a[i].deg = 0;
}
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
read_record(container, n);
}
also, prefer size_t to store the number of allocated objects.
Nitpick: read_record doesn't seem a good name for a function that modifies the contents of the records.
EDIT: As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
Same approach but returning a reallocated container:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
struct X *read_record(struct X *a, size_t size)
{
struct X *new = realloc(a, sizeof(struct X) * size);
if (new != NULL)
{
for (size_t i = 0; i < size; i++) {
new[i].deg = 0;
}
}
return new;
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
container = read_record(container, n * 2);
if (container == NULL)
{
fprintf(stderr, "Can't read record\n");
exit(EXIT_FAILURE);
}
}
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
The pointer is passed by value, so to save the changes and have them usable outside the function scope, after the function ends, i.e. in main, a pointer to pointer must be the argument, and the address of the pointer must be passed, your overall assessment is correct.
Your implementation, however, is not correct, here's how you shoud do it:
Live demo
void read_record(struct X **a, int size) //double pointer
{
*a = realloc(*a, sizeof **a * (size + 10)); //reallocate memory for 20 ints
if (*a == NULL)
{
perror("malloc");
}
for (int i = 0; i < size + 10; i++) //assing new values
{
(*a)[i].deg = 1;
}
}
int main()
{
int n = 10;
struct X *container = malloc(sizeof *container * n); //original allocation
//the pointer now has space for 10 ints
if (container == NULL)
{ //check allocation errors
perror("malloc");
}
for (int i = 0; i < n; i++) //assign values
{
container[i].deg = 0;
}
read_record(&container, n); //pass by reference
//the pointer now has space for 20 ints
}
Alternatively you can return the pointer instead, refering to David Ranieri's answer.
The first function parameter has the pointer to pointer type struct X**. So dereferencing the parameter a you will get a pointer of the type struct X*. Now you may apply the subscript operator that yields lvalue of the type struct X..
That is the function definition will look like
void read_record(struct X** a,int size){
for (int i=0;i<size;i++){
( *a )[i].deg = 0;
}
}
Or this statement
( *a )[i].deg = 0;
may be substituted for this statement
a[0][i].deg = 0;
On the other hand, there is no great sense to declare the first parameter as having the type struct X**. The function can look simpler as for example
void read_record(struct X* a,int size){
for (int i=0;i<size;i++){
a[i].deg = 0;
}
}
and be called like
read_record( container, n );
When you call read_record you pass a pointer to a pointer to the first element of an array of X structures.
But inside the read_record you treat it as a pointer to the first element of an array of pointers to X structures (i.e. as an array of pointers to X). There's a subtle but very important difference here.
If you want to emulate pass-by-reference for the pointer variable, you need to dereference it inside the read_record to get the original pointer (and remember that then you have an array of objects, not pointers):
(*a)[i].deg = 0;
Double pointer is the problem. The code should be:
void read_record(struct X* a,int size){ // Check the change
for (int i=0;i<size;i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container=(struct X*)malloc(sizeof(struct X)*n);
read_record(container,n); // Check the change
}

how to make a qsort function and sort array of pointers to structs

i'm trying to make a qsort function from scratch that sorts an array of pointers to structs
this is the code i have right now
static void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
void _qsort(void* list, int list_len, int left, int right,
int(*comp)(const struct shpg_item *a, const struct shpg_item *b)) {
void *vt, *v3;
int i, last, mid = (left + right) / 2;
if (left >= right)
return;
void* vl = (char*)(list + (left * list_len));
void* vr = (char*)(list + (mid * list_len));
swap(vl, vr);
last = left;
for (i = left + 1; i <= right; i++) {
// vl and vt will have the starting address
// of the elements which will be passed to
// comp function.
vt = (char*)(list + (i * list_len));
if ((*comp)(vl, vt) > 0) {
++last;
v3 = (char*)(list + (last * list_len));
swap(vt, v3);
}
}
v3 = (char*)(list + (last * list_len));
swap(vl, v3);
_qsort(list,list_len, left, last - 1, comp);
trace_int(1);
_qsort(list, list_len, last + 1, right, comp);
}
void list_sort(struct shpg_item **list, int list_len,
int(*comp)(const struct shpg_item *a, const struct shpg_item *b)) {
_qsort(*list,list_len,0,(list_len-1),comp);
}
but this gives a segmentation fault error , can any one tell me why and help me ?
void * pointer addition
void * pointer addition is undefined behavior. But since the usual UB is OK, this may or may not be OP's trouble.
void _qsort(void* list, int list_len, int left, ...
...
(list + (left * list_len)) // UB
Instead recommend casting before addition.
// void* vl = (char*)(list + (left * list_len));
void* vl = ((char*) list) + (left * list_len);
Other issues may exist
I haven't check the entire code but your swap function seems wrong. Depending on the comment lines in your code;
// vl and vt will have the starting address
// of the elements which will be passed to
// comp function.
if (list + (left * list_len)) and (list + (last * list_len)) are pointers to be swapped (pointers to a string or a struct, for example), your swap function decoration & your caller line should read as:
Swapping two integers, floats, doubles, etc (in general swapping values only):
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
...
int x = 5;
int y = 3;
swap(&x, &y);
If you need to swap two pointers (a char * string or another type of pointer pointing to a struct), you can just swap pointer values without swapping the content pointed in the actual memory:
void swap(void **a, void **b) {
void *t = *a;
*a = *b;
*b = t;
}
...
char *x = "some string";
char *y = "some other string";
swap(&x, &y);
I've included a working example in the middle part of this answer, and also added an example using qsort.
Taking a quick look at the code I see problem here:
void _qsort(void* list, ...
Since list is an array of pointers it should be:
void _qsort(void** list, ...
or
void _qsort(void* list[], ...
With this declaration, pointer arithmetic will not be an issue, for example, list+3 == &list[3] == pointer to the 3rd pointer in the array. There's no need to cast list, as void** list will work fine in the main part of the code. The only code that will do any casting is the caller's compare function.
You can choose to emulate qsort's compare function parameters using type void **: compare(list+i, list+j), but it would be simpler to use type void *: compare(list[i], list[j]).
Swap should use void** as parameters. The call would be
swap(list+i, list+j)
/* ... */
void swap(void **i, void **j){
void * t;
t = *i;
*i = *j;
*j = t;
}
There are some comments about a void pointer possibly having a different size than a struct pointer or any type of data pointer, and that this could cause an issue. If this was true, then the C library function qsort() would not work because the first parameter for qsort is a void pointer, which will result in the caller's pointer being cast to a void pointer. In the caller's compare function, both parameters are const void pointers which the caller's compare function has to cast to the actual pointer types. With qsort() and the caller's compare function, parameters are being cast both to and from void pointers without issue.
C guarantees that a void pointer can be used to hold any type of data pointer, so in essence a void pointer is a generic data pointer (in 16 bit segment or selector environments, a generic "near" data pointer).
This is a working example, using typical Lomuto partition scheme (pivot = a[hi]):
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int data;
char name[32];
}XMPL;
int cmpr(void * pi, void *pj)
{
if(((XMPL *)pi)->data < ((XMPL *)pj)->data)
return -1;
if(((XMPL *)pi)->data > ((XMPL *)pj)->data)
return 1;
return 0;
}
void swap(void **i, void **j){
void * t;
t = *i;
*i = *j;
*j = t;
}
void QuickSort(void **a, int lo, int hi, int(*cmpp)(void *, void *))
{
void *p;
int i, j;
while(lo < hi){
p = a[hi];
i = lo;
for(j = lo; j < hi; ++j){
if((cmpp(a[j], p) < 0)){
swap(a+i, a+j);
++i;
}
}
swap(a+i, a+hi);
if(i - lo <= hi - i){ /* avoid stack overflow */
QuickSort(a, lo, i-1, cmpp);
lo = i+1;
} else {
QuickSort(a, i+1, hi, cmpp);
hi = i-1;
}
}
}
#define COUNT (1024)
int main(int argc, char**argv)
{
XMPL *ax; /* array of structures */
XMPL **pax; /* array of pointers to structures */
int i;
ax = malloc(COUNT * sizeof(XMPL));
pax = malloc(COUNT * sizeof(void **));
for(i = 0; i < COUNT; i++){ /* init structs, array of ptrs */
ax[i].data = rand();
pax[i] = ax+i;
}
QuickSort(pax, 0, COUNT-1, cmpr);
for(i = 1; i < COUNT; i++){
if(pax[i-1]->data > pax[i]->data){
break;
}
}
if(i == COUNT)
printf("passed\n");
else
printf("failed\n");
free(pax);
free(ax);
return(0);
}
Hoare parition scheme will probably be a bit faster. However, in this case, merge sort should be faster than quick sort. Merge sort does more moves but fewer compares than quick sort, and in this case, only pointers are being moved, while the compare involves an indirection via a pointer and a call to a compare function via a pointer.
Same basic code, but using qsort. Note that the cmpr() function needed one more dereference for each parameter.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int data;
char name[32];
}XMPL;
int cmpr(const void * pi, const void *pj)
{
if((*(XMPL **)pi)->data < (*(XMPL **)pj)->data)
return -1;
if((*(XMPL **)pi)->data > (*(XMPL **)pj)->data)
return 1;
return 0;
}
#define COUNT (1024)
int main(int argc, char**argv)
{
XMPL *ax; /* array of structures */
XMPL **pax; /* array of pointers to structures */
int i;
ax = malloc(COUNT * sizeof(XMPL));
pax = malloc(COUNT * sizeof(void **));
for(i = 0; i < COUNT; i++){ /* init structs, array of ptrs */
ax[i].data = rand();
pax[i] = ax+i;
}
qsort(pax, COUNT, sizeof(XMPL *), cmpr);
for(i = 1; i < COUNT; i++){
if(pax[i-1]->data > pax[i]->data){
break;
}
}
if(i == COUNT)
printf("passed\n");
else
printf("failed\n");
free(pax);
free(ax);
return(0);
}

Pointers to pointers segmentation fault

I created an insertion sort method which accepts an array, its size and a comparator. The comparator function is this:
int compare_int_ptr(void* ptr1, void* ptr2) {
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
if(i1<i2) {
return -1;
}
if(i1 == i2) {
return 0;
}
return 1;
}
The insertion is this:
void insertion_sort(void** array, int size, CompFunction compare){
int i,j;
void* key;
for(i = 1; i<size;i++){
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
swap(&array[j+1],&array[j]);
}
array[j+1] = key;
}
}
If I try to execute it, I get the segmentation fault error, so I think that I didn't used the pointer correctly. Is it correct that when I do the swap i pass it with the &?
EDIT: this is where I call the method:
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("Usage: sortingfirstusage <file_name>\n");
exit(EXIT_FAILURE);
}
double* array = load_array(argv[1]);
insertion_sort((void**)array, 3, compare_int_ptr);
free(array);
return 0;
The array is correctly loaded because I printed all the elements before calling the insertion sort and they were in.
You are trying to sort an array of doubles. double *array points to the first of n elements:
array ==> [ double ] \
[ double ] |
. > n elements
. |
[ double ] /
You are casting array to a void **:
(void **)array ==> [ void * ] \
[ void * ] |
. > n elements
. |
[ void * ] /
It should not be hard to determine that trouble lies ahead. A void * is not a double. It may or may not be the same size as a double. It almost certainly doesn't point to a valid memory location, so if you dereference it you will invoke undefined behavior, almost certainly resulting in your program being killed by a signal. Unfortunately, your insertion_sort function does dereference it when it calls the comparison function:
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
array[i] and array[j] are both invalid void * values (because the underlying memory contains doubles, not void *s). Your comparison function dereferences them here:
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
ptr1 and ptr2 contain meaningless pointer values. They do not point to doubles. Dereferencing them invokes undefined behavior.
Here is a working version of insertion_sort using the same function type and equivalent functionality to the qsort function from the C standard library (although the function is a lot less efficient than qsort):
insertion_sort.h:
#ifndef INSERTION_SORT_H_INCLUDED__
#define INSERTION_SORT_H_INCLUDED__
#include <stddef.h>
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#endif
insertion_sort.c:
#include <string.h>
#include "insertion_sort.h"
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
char (*b)[size] = base;
size_t i;
size_t j;
int cmp;
for (i = 1; i < nmemb; i++) {
j = i - 1;
/* search backwards for insertion point */
while ((cmp = compar(b + j, b + i)) > 0 && j > 0)
j--;
if (cmp <= 0)
j++; /* went back one too far */
if (j < i) {
/* rotate element i to position j, j to j+1, ..., i-1 to i */
char tmp[size];
memcpy(&tmp[0], &b[i][0], size);
memmove(&b[j + 1][0], &b[j][0], size * (i - j));
memcpy(&b[j][0], &tmp[0], size);
}
}
}
Here is an example of the usage of the above function:
main.c:
#include <stdio.h>
#include "insertion_sort.h"
int compar_double(const void *a, const void *b)
{
double d1 = *(const double *)a;
double d2 = *(const double *)b;
if (d1 < d2)
return -1;
if (d1 > d2)
return 1;
return 0;
}
void print_doubles(const double *d, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf("%g\n", d[i]);
}
int main(void)
{
double numberlist[] = { 3.0, 1.0, 5.0, -4.0, 2.0 };
size_t len = sizeof numberlist / sizeof numberlist[0];
printf("Unsorted:\n");
print_doubles(numberlist, len);
printf("\n");
insertion_sort(numberlist, len, sizeof numberlist[0], compar_double);
printf("Sorted:\n");
print_doubles(numberlist, len);
return 0;
}
Here is the output produced by the above program:
Unsorted:
3
1
5
-4
2
Sorted:
-4
1
2
3
5
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
Like qsort, your sorting function should take a void * as the first parameter, not void **. The double indirection is a mistake that you should have noticed when calling insertion_sort. Converting a double[] array to void ** requires a cast, whereas it can be converted automatically to void * without one.
Without knowing what load_array(argv[1]); does, the answer is impossible to predict as Peter suggested in the comments.
Assuming this function call is doing something legitimate and loading the array with pointers that can be de-referenced properly then your problem is the cast. You cannot make a pointer into a pointer to pointers. You have to pass the address of the pointer to accomplish what you want.
insertion_sort(&array, 3, compare_int_ptr);

How to reverse digits of each number in an array using pointer arithmetic

I tried to write a program in C that reverses all the numbers in an array, but it actually doesn't reverse anything, so I get unchanged numbers back. I guess I got something wrong with the pointers.
Here is my code:
#include <stdio.h>
void reverse(int *n) {
int number = *n, number2 = 0;
while (number!=0) {
number2 *= 10;
number2 += number % 10;
number /= 10;
}
*n = number2;
}
void ReverseDigits(int *p, int n) {
int i = 0;
while (i < n) {
reverse(&p);
p++;
i++;
}
}
int main() {
int array[3] = {123, 456, 789}, i = 0;
while (i < 3) {
ReverseDigits(array, 3);
i++;
}
return 0;
}
In ReverseDigits the variable p is an int pointer. When you do &p you'll get a pointer to int pointer. But your reverse function just expects an int pointer so your call of reverseis wrong. Simply do
reverse(p); // insteand of reverse(&p)
In main you shall not call ReverseDigits in a loop as the function already loops the array (i.e. the number of elements passed). So skip the while and simply do:
int main() {
int array[3] = {123, 456, 789};
ReverseDigits(array, 3);
return 0;
}
It seems to me that your reverse() function is "both baffling, and necessarily wrong." (Hey, don't take that personally...)
How could such a function possibly work, without being told, not only where the (array) is, but how long it is? You seem to be missing a parameter here.
Once you've settled that problem in your design, the task of "reversing" an array is simply a process of "swapping" the first-and-last elements in an algorithm that goes something like this: (pseudocode!)
function reverse( array[], array_size) {
int i = 0;
int j = array_size - 1; // since zero-based
while (i < j) { // no need to use "<=" here"
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
}

Resources