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'.
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");
Context
I created this simple code where I store various arrays in my_arrays() function and different functions (in my example the main()) can get the hard-coded arrays via the function my_arrays().
See the code here:
#include <stdio.h>
int my_arrays(int *size, int **arrays) {
size[0] = 3;
int array_1[3] = {1, 2, 3};
arrays[0] = array_1;
size[1] = 5;
int array_2[5] = {2, 3, -5, 7, 11};
arrays[1] = array_2;
}
int main() {
int num_of_arrays = 2;
int sizes[2];
int *arrays[2];
my_arrays(sizes, arrays);
for (int i=0; i < num_of_arrays; i++) {
int *array = arrays[i]; // point to sub-array
int size = sizes[i];
printf("array[%d]: {", i);
for (int x=0; x < size; x++) {
printf(" %d", array[x]);
}
printf(" }\n", i);
}
return 0;
}
In the main() I then loop through the sub-arrays and loop through each individual number and print it out.
What I expect the code above to print out is:
array[0]: { 1 2 3 }
array[1]: { 2 3 -5 7 11 }
But when compiling and running I get this:
array[0]: { 1993067712 1617605192 -2 }
array[1]: { 3936256 8 6422188 7 6422476 }
Why?
In my_arrays, array_1 and array_2 are local arrays on the stack. They will be invalid as soon as you return from my_array. Now arrays[0] and arrays[1] hold pointers to invalid or "stale" memory. Accessing that is undefined behaviour.
(The garbage values you see shows you that your arrays have been overwritten by other uses of the stack space, probably by calls to printf.)
If you want to create arrays, you can allocate memory on the heap:
int my_arrays(int *size, int **arrays)
{
size[0] = 3;
arrays[0] = malloc(3 * sizeof(int));
arrays[0][0] = 1;
arrays[0][1] = 2;
arrays[0][2] = 3;
// ... initialize other arrays ...
return 0;
}
You should explicitly free it after you're done using it:
// at the end of main
for (int i=0; i < num_of_arrays; i++) {
free(arrays[i]);
}
I am trying to write a C program that squares each element of an array:
Input:
v = {1,2,3}
Output:
v = {1,4,9}
Here is my C code:
#include <stdio.h>
#include <math.h>
void squaredVector(int *rowVector[] , int arrayLength);
int main(void)
{
int result;
int a[] = {1 , 2 , 3};
result = squaredVector(&a , 3); /* use the address of array a */
printf("%d" , result);
return 0;
}
The function that squares my vector:
void squaredVector(int *rowVector[] , int arrayLength)
{
int i;
for(i = 0; i < arrayLength; i++)
{
*rowVector[i] = (*rowVector[i]) * (*rowVector[i]);
}
}
I am not really sure what the function is doing, but I assume the values of the array are being passed to the square vector function. I assume that:
*rowVector[i] = (*rowVector[i]) * (*rowVector[i]);
is taking element a[i] and squaring it using unmasked pointers
You are using a 1D array, so you should not use
void squaredVector(int *rowVector[] , int arrayLength); // This is an array of pointers
Instead the proper function declaration is
void squaredVector(int rowVector[] , int arrayLength); //1D array
OR
void squaredVector(int *rowVector , int arrayLength); //1D array
Inside the function, the for loop should change to
for(i = 0; i < arrayLength; i++)
{
rowVector[i] = (rowVector[i]) * (rowVector[i]);
}
Call the function in main by
result = squaredVector(a , 3);
/*Jeremy Johnson 11-18-48
*
*The purpose of this program to to swap halves of an array. So {1 2 3 4 5 6}
*becomes {4 5 6 1 2 3} using pointer notation.
*/
#include <stdio.h>
#include <string.h>
int array[] = {1, 2, 3, 4, 5, 6}; //initialize array
void mirror(int* array, int from_index, int to_index); //prototype statment
int main() {
//define and assign pointer to array address
int *arrptr, i;
arrptr = &array[0];
//print original array
printf("Original Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
//call function to swap values and mirror the array
mirror(arrptr, 0, 2);
mirror(arrptr, 3, 5);
mirror(arrptr, 0, 5);
mirror(arrptr, 1, 4);
mirror(arrptr, 2, 3);
//print final array
printf("Mirror Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
return 0;
}
void mirror(int* array, int from_index, int to_index) {
//create pointer for temporary memory storage
int *temp, c[1];
temp = &c[0];
//Place to_index in temporary memory
*(temp) = *(array + to_index-1);
//Copy from_index to to_index
*(array + to_index-1) = *(array + from_index-1);
//Copy temporary value back into from_index
*(array + from_index-1) = *(temp);
return;
}
/* This code works for the function however I am not allowed to use array
notation.
c[1]=array[to_index];
array[to_index]=array[from_index];
array[from_index]=c[1]; */
I am trying to swap each half of the array; I have done so by switching the indices of the arrays by calling the mirror function 5 times and swapping the appropriate values. I was able to do so using the commented code at the bottom in place of the current function code, but now I receive and exit value 5, and I'm not sure why. (I receive no other errors within the code)
// perhaps swap the array by:
void mirror( int*, int* );
int main()
{
...
int *pSecondHalf = array[(sizeof(array)/sizeof(int))>>1];
// note: above line will not work for odd size array so:
if( array[(sizeof(array)/sizeof(int)] & 0x01 )
{
pSecondHalf++; // middle term in odd size array will not move
}
int *pFirstHalf = array;
const int *pLastHalf = array+((sizeof(array)/sizeof(int))>>1);
// note: following 'for' loop will execute one extra time
// for odd size array, but nothing will be changed
for( ; pFirstHalf < pLastHalf; pFirstHalf++, pSecondHalf++ )
{
mirror( pFirstHalf, pSecondHalf );
}
...
return(0);
}
// and in mirror()
void mirror( int *pVal1, int* pVal2)
{
int temp = *pVal1;
*pVal1 = *pVal2;
*pVal2 = temp;
}
The problem was in the mirror function. I did not move each element of the array to the temporary array using a for loop (aka counting loop). I added two loops to the function and it runs fine now.
/*Jeremy Johnson 11-18-48
*
*The purpose of this program to to swap halves of an array. So {1 2 3 4 5 6}
*becomes {4 5 6 1 2 3} using pointer notation.
*/
#include <stdio.h>
#include <string.h>
int array[] = {1, 2, 3, 4, 5, 6}; //initialize array
void mirror(int* array, int from_index, int to_index); //prototype statement
int main() {
//define and assign pointer to array address
int *arrptr, i;
arrptr = &array[0];
//print original array
printf("Original Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
//call function to swap values and mirror the array
mirror(arrptr, 0, 2);
mirror(arrptr, 3, 5);
mirror(arrptr, 0, 5);
//print final array
printf("Mirror Array: \n");
for (i = 0; i <= 5; i++) {
printf("%d", array[i]);
}
printf("\n");
return 0;
}
void mirror(int* array, int from_index, int to_index) {
//create pointer for temporary memory storage
int *temp, c[6], j;
temp = &c[0];
//Place array elements in temporary memory
for (j = 0; j < 6; j++) {
*(temp + j) = *(array + j);
}
//Place mirrored halves in array respectively
for (j = 0; j <= (to_index - from_index); j++) {
*(array + from_index + j) = *(temp + to_index - j);
}
return;
}
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");
}