I have this function :
void foo( char tab[8][8] )
I want this function to edit the values of the tab array, so i tried theses syntax :
void foo( char *(*tab)[8][8] )
void foo( char *(tab)[8][8] )
void foo( char **tab )
And a LOT of others. I always get a fail while compiling, like this one :
error: cannot convert 'char ()[8][8]' to 'char (*)[8][8]' for argument '1' (...)
So, my quesiton is : how to create and pass to a function a pointer to a 2D array ?
Thanks.
This time try to declare your function as
void foo( char (*tab)[8] );
and call it as
foo(point);
Note that in this case you need to pass only array name as it decays to pointer when passed to a function (some exceptions are there). After decay it is of type char (*)[8].
You can do it also by declaring
void foo( char (*tab)[8][8] );
and call it as
foo(&point);
In this case notice that I passed &poinnt, i.e, address of the entire array which is of type char (*)[8][8].
Sample:
void foo(char (*tab)[8][8])
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 68j++)
{
scanf("%d", &(*tab)[i][j]);
}
}
}
With an array, you can always modify the data in the function because what is passed is a pointer (in the absence of const qualifiers, of course). That is, you could write:
void foo(char tab[8][8])
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
tab[i][j] = (x + y) % 2 : 'X' : 'O';
}
}
And call it:
void calling_func(void)
{
char board[8][8];
foo(board);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
putchar(tab[i][j]);
putchar('\n');
}
}
You can get the error messages you were seeing if you write:
foo(&board);
That passes a pointer to an array to the function. For that to work, you have to rewrite the function as:
void foo(char (*tab)[8][8])
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
(*tab)[i][j] = (x + y) % 2 : 'X' : 'O';
}
}
However, this is seldom the correct way to write the code. Use the first alternative until this is forced upon you (which probably won't be this year — I don't recall having to use a pointer to an array except to answer questions on SO, but maybe it was such a ghastly experience that I have forgotten all about it).
Related
This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 13 days ago.
I wrote this program that is supposed to sort NxN array. It gets compiled but doesn't work because the pointer type is incompatible.
I just need help with the pointers as argument. I get incompatible pointer type warning for both functions swap and dblArraySort. Any idea why is that ?
thanks in advance !
#include <stdio.h>
#include <stdlib.h>
void
swap(int **a, int **b)
{
int temp;
temp = **a;
**a = **b;
**b = temp;
}
void
dblArraySort(int **dblArray, int arrLen)
{
int chkIndex;
int i, j, k;
for (i = 0; i < arrLen; i++) {
if ((i + 1) % 2 == 0) {
for (j = 0; j < arrLen; j++) {
chkIndex = dblArray[i][j];
for (k = 1; k + j < arrLen; k++)
if (chkIndex < dblArray[i][k + j])
swap(&dblArray[i][j], &dblArray[i][k + j]);
else
continue;
}
} else {
for (j = 0; j < arrLen; j++) {
chkIndex = dblArray[i][j];
for (k = 1; k + j < arrLen; k++)
if (chkIndex >= dblArray[i][k + j])
swap(&dblArray[i][j], &dblArray[i][k + j]);
else
continue;
}
}
}
}
int
main()
{
unsigned int arrayLength;
printf("Provide array size: \n");
scanf("%d", &arrayLength);
int doubleArray[arrayLength][arrayLength];
for (int i = 0; i < arrayLength; i++) {
for (int j = 0; j < arrayLength; j++) {
scanf("%d", &doubleArray[i][j]);
}
}
dblArraySort(doubleArray, arrayLength);
for (int i = 0; i < arrayLength; i++) {
for (int j = 0; j < arrayLength; j++) {
printf("%d ", doubleArray[i][j]);
}
printf("\n");
}
return 0;
}
I tried the code mentioned above
Arrays in C can be confusing. The thing you need to worry about is element type.
The element type of int ** dblArray is int *. In other words, dblArray is an array of int *s.
However, the element type of int doubleArray[arrayLength][arrayLength] is int row_type[arrayLength]. That is not an int *, that is an array, which is a totally different thing.
Moreover, when you use an array⟶pointer conversion, as happens when you say:
dblArraySort(doubleArray, arrayLength); // doubleArray is converted to a pointer
You get a pointer to the array, which in this case is a pointer to the innermost element type, an int — which is also not an int *.
tl;dr: You are trying to pass an array of array of int to a function taking an array of pointer to int. That won’t work.
I would like to comment on your variable naming as well. When you say “double” or “dbl”, as in doubleArray and dblArray the very first thing people will think is that you are handling a linear array of type double, which is also not what the array is.
You have there a two-dimensional array. Not a “double” array. Common naming for such thing would be array2D or matrix.
To make it work you need either C11, which allows you to pass a VLA as:
void sort_array2D( size_t rows, size_t columns, int array[rows][columns] )
{
...
int value = array[i][j];
...
}
int main(void)
{
int array2D[Array_Length][Array_Length];
...
sort_array2D( Array_Length, Array_Length, array2D );
Or you need to simply assume you must compute the index manually. A little function will help:
size_t index2D( size_t rows, size_t columns, size_t r, size_t c )
{
(void)rows; // (quiet the compiler about not using this argument)
return r * columns + c;
}
Then you can write your function as:
void sort_array2D( int * array, size_t rows, size_t columns )
{
...
int value = array[index2D( rows, columns, i, j )];
...
}
int main(void)
{
int array2D[Array_Length][Array_Length];
...
sort_array2D( (int *)array2D, Array_Length, Array_Length );
I haven’t bothered to analyze your sort function. It doesn’t look right to me, but honestly, I’ve barely glanced at it. Calling a value from the array chkIndex looks fishy, since the values of the array are not indices per se, at least not in the context of sorting them.
Remember, when messing with arrays in C you need to keep strict care to not mix up the type of the elements. (Or the types of things in general, whether syntactic or conceptual.)
I am writing a program that passes a 2D char array into a function for printing. However, when I try to access elements in the 2D array for printing, I can't. This problem does not occur when I place the printing loops and statements in the main() function, only if the array is passed.
Can someone help explain?
void disp_array(char* array)
{
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
printf("%c", array[i][j]);
}
printf("\n");
}
}
Attached is my code: the j in the printf statement is highlighted with an error:
E0142: "expression must have pointer-to-object type but it has type
int"
The function declaration is wrong.
As the parameter has the type char * then the expressions array[i] yields a scalar object of the type char that is promoted to the type int due to the integer promotions to which you may not apply the subscript operator as you are trying to do array[i][j]. So the compiler issues the error message
E0142: "expression must have pointer-to-object type but it has type
int"
The function should be declared like
void disp_array(char array[][SIZE], int n )
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < SIZE; j++)
{
printf("%c", array[i][j]);
}
printf("\n");
}
}
or like
void disp_array(char (*array)[SIZE], int n )
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < SIZE; j++)
{
printf("%c", array[i][j]);
}
printf("\n");
}
}
The parameter having the array type char[SIZE][SIZE] is implicitly adjusted by the compiler to the type char ( * )[SIZE]. That is the function does not know how many elements of the type char ( * )[SIZE] exist. So you need to specify the number of elements explicitly. Try always to define a more general function.
And along with the array you need to pass the number of rows in the array. For example
disp_array( array, SIZE );
If the array contains strings then the function definition will look like
void disp_array(char (*array)[SIZE], int n )
{
for (int i = 0; i < n; i++)
{
puts( array[i] );
}
}
I am trying to create a function that changes my 2d array and saves changes to it
The code is working but warnings about pointers appear, and I don't know how to bypass it with my yet basic knowledge of C language
#include <stdio.h>
int size = 0;
void functionName(char (*tab)[size][size]) {
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
(*tab)[i][j] = (*tab)[i][j]-'0';
}
}
}
int main() {
scanf("%d", &size);
char tab[size][size];
for(int i = 0; i < size; i++) {
for(int j = 0; j < size; j++) {
scanf("%c", &tab[i][j]);
}
}
functionName(tab);
return 0;
}
The error occurs because char tab[][] decays to a char (*)[] when passed as an argument, which doesn't match the type functionName expects. To resolve the inconsistency, either:
pass tab as a char (*)[][] by calling functionName(&tab) instead;
or, change the argument type of functionName to void functionName(char tab[size][size]), and fix the code inside the function to use tab[i][j] instead of (*tab)[i][j].
Problem is as answered by dxiv
C99 with variable length arrays or select later version of C, use:
void functionName(int size, char tab[size][size]) {
...
}
and call with
functionName(size, tab);
Also suspect OP's scanf("%c", &tab[i][j]); should change to scanf(" %c", &tab[i][j]); (Add space)
I want foo() not to modify the array. So I declared array in foo() as const
If I compile this code, compiler is complaining:
#include <stdio.h>
void foo(const int arr[5][5])
{
int i,j;
for( i = 0; i < 5; i++)
{
for( j = 0; j < 5; j++)
{
printf("%d\n", arr[i][j]);
}
}
}
int main()
{
int val = 0;
int i,j;
int arr[5][5];
for( i = 0; i < 5; i++)
{
for( j = 0; j < 5; j++)
{
arr[i][j] = val++;
}
}
foo(arr);
}
The warning is:
allocate.c: In function 'main':
allocate.c:26:9: warning: passing argument 1 of 'foo' from incompatible pointer type
foo(arr);
^
allocate.c:3:6: note: expected 'const int (*)[5]' but argument is of type 'int (*)[5]'
void foo(const int arr[5][5])
^
How else can I declare formal parameter as constant?
I assume that you do not want foo() to be able to modify the array in the interest of encapsulation.
As you are likely aware, in C arrays are passed into functions by reference.
Because of this, any changes that foo() makes to the values array will be propagated back to the variable in main(). This is not in the interest of encapsulation.
const will not prevent foo() from modifying the array
The C keyword const means that something is not modifiable. A const pointer cannot modify the address that it points to. The value(s) at that address can still be modified.
In c, By default, you cannot assign a new pointer value to an array name. There is no need for const. Similar to a const pointer, the values in this array can still be modified. Encapsulation problem is not solved.
To encapsulate foo() from your main() function, put your array in a struct. Structs are passed by value and so foo() will receive a copy of the data. As it has a copy, foo() will not be able to alter the original data. Your functions are encapsulated.
Solution (that works!):
#include <stdio.h>
typedef struct
{
int arr[5][5];
} stct;
void foo(const stct bar)
{
int i,j;
for( i = 0; i < 5; i++)
{
for( j = 0; j < 5; j++)
{
printf("%d\n", bar.arr[i][j]);
}
}
}
int main()
{
int val = 0;
int i,j;
stct bar;
for( i = 0; i < 5; i++)
{
for( j = 0; j < 5; j++)
{
bar.arr[i][j] = val++;
}
}
foo(bar);
}
I put const in the foo() definition because you asked how you could declare the formal parameter as a constant. It works but is not needed.
void foo(stct bar)
Removing the const will not break the function.
I am a complete beginner with C and we have an assignment in class to take a given list of strings, put them in an array of strings, and pass that to a user-defined sort function that prints them in alphabetical order. Whenever I run my code, it does not give any compiler errors, but it also crashes immediately at runtime. Debugging gives me a segmentation fault, but it does not give me a specific line that caused it. I am running my code through the gcc compiler included in Dev C++.
Here is my code. Any help would be appreciated. I think my problem is trying to pass an array of strings to the function, but I haven't been able to find any answers on the subject that I could understand.
#include <stdio.h>
#include <string.h>
void sort(char *[]);
int main()
{
char *states[4] = {0};
states[0] = "Florida";
states[1] = "Oregon";
states[2] = "California";
states[3] = "Georgia";
sort(states);
return 0;
}
void sort(char *ptr[])
{
int i, j;
char temp[20];
for ( i = 1; i <= 4; i++ )
{
for ( j = 1; j <= 4; j++ )
{
if (strcmp(ptr[j-1], ptr[j]) > 0)
{
strcpy(temp, ptr[j-1]);
strcpy(ptr[j-1], ptr[j]);
strcpy(ptr[j], temp);
}
}
}
int x;
for ( x = 0; x < 4; x++ )
{
printf("%s", ptr[x]);
printf("\n");
}
}
Issues I see:
You are using the wrong indices in the for loops.
Instead of:
for ( i = 1; i <= 4; i++ )
{
for ( j = 1; j <= 4; j++ )
use:
for ( i = 0; i < 4; i++ ) // Keep the values in the range 0 - 3.
{
for ( j = 0; j < 4; j++ )
You are modifying read-only memory.
When you use:
states[0] = "Florida";
states[0] has the value of a read-only address that contains the string "Florida". If you modify the values at that address, which you are doing in sort, you are entering undefined behavior territory.
You can fix the problem by switching pointers instead of copying the values.
// Use char* for temp instead of an array
char* temp;
if (strcmp(ptr[j-1], ptr[j]) > 0)
{
temp = ptr[j-1];
ptr[j-1] = ptr[j];
ptr[j] = temp;
}
Addendum, in response to comment by OP
The following version of sort works for me:
void sort(char *ptr[])
{
int i, j;
char* temp;
for ( i = 0; i < 4; i++ )
{
// NOTE:
// This is different from your version.
// This might fix your problem.
for ( j = i+1; j < 4; j++ )
{
if (strcmp(ptr[j-1], ptr[j]) > 0)
{
temp = ptr[j-1];
ptr[j-1] = ptr[j];
ptr[j] = temp;
}
}
}
for ( i = 0; i < 4; i++ )
{
printf("%s", ptr[i]);
printf("\n");
}
}
The cause of crash is j <= 4. The other problem is that you want to swap pointers to string and not the chars.
void sort(char *ptr[])
{
int i, j;
char *temp;
for (i = 0; i < 4; i++) // sticking to array boundary convention
{
for ( j = 1; j < 4; j++ )
{
if (strcmp(ptr[j-1], ptr[j]) > 0)
{
// swap pointers
tmp = ptr[j];
ptr[j] = ptr[j-1];
ptr[j-1] = ptr[j];
}
}
}
for (i = 0; i < 4; i++)
printf("%s\n", ptr[i]);
}
C's Standard Library already comes with a function to sort arbitrary arrays of data. It is called qsort.
qsort can sort arrays based on any criterion you supply using its fourth argument, the comparison function. In this case, we have a natural comparison function which we would like to shoehorn into using with what qsort expects.
So, mycmpstr below casts the incoming pointers appropriately, and returns the result of comparing strings using strcmp. We know that qsort will be calling our comparison function with constant pointers to constant char pointers, and we 'cast' appropriately.
Keep in mind that you are sorting pointers to character arrays. That means, you do not need to move the strings themselves, just the pointers. You use strcmp to decide which pointer should come before which based on the ordering of the strings to which they point.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int mycmpstr(const void *p, const void *q) {
const char *const *x = p;
const char *const *y = q;
return strcmp(*x, *y);
}
int main(void)
{
int i;
const char *states[] = {
"Florida", "Oregon", "California", "Georgia"
};
qsort(
states,
4,
sizeof(char *),
mycmpstr
);
for (i = 0; i < 4; i += 1) {
puts(states[i]);
}
return 0;
}
Output:
$ clang -Wall -O1 sortex.c -o sortex
$ ./sortex
California
Florida
Georgia
Oregon