Passing an Array to a structure in C - c

In order to fill a structure with integers (to then be passed on further in the program) I thought the following would work:
main() {
struct songs {int pitch[5], length[5];} songs[4];
int i[5]={1,22,23,14,52};
int k=0;
songs[0].pitch=i;
for (k=0; k<5; k++) printf("%d\n",songs[0].pitch[k]);
}
however this comes up with an error "incompatible types in assignment"
if I dont however pass this array to the structure, using the following:
main() {
int i[5]={1,22,23,14,52};
int k=0;
for (k=0; k<5; k++) printf("%d\n",i[k]);
}
it compiles and will display the content of the array.
I realise there is probably a simple fix to this, but any help would be brilliant!
Thanks in advance

C89 does not allow you to assign an array to another array. Here's the relevant bit from C99, but the text is much the same in C89 with the exception of the mention of the C99 only type _Bool. (I only have paper copies of C89)
Arrays don't fit any of these conditions -- they aren't arithmetic types, they aren't of structure or union type, and they're not pointers1. Therefore you can't use the assignment operator on them.
You can, however, use memcpy. If you replace this line:
songs[0].pitch=i;
with this line:
memcpy(songs[0].pitch, i, sizeof(i));
you'll get the behavior you expect. (After including <string.h> first of course)
1 Technically speaking 6.3.2.1/3 says that the array is converted into an rvalue pointer before it is seen by operator=, but such an assignment is still prohibited because 6.5.16/2 requires that the left side of an assignment be an lvalue.

Due to the way C handles arrays you can't assign to one like that. You need to copy over the values, either individually or via memcpy (or similar functions). Example:
for (k=0; k<5; k++){
songs[0].i[k] = i[k];
}
or:
memcpy(songs[0].i, i, sizeof i);
Note that memcpy requires you to include <string.h>

You will need to copy the array elements individually. Also the main function really should return an int.
int main( void ) {
struct songs {int pitch[5], length[5];} songs[4];
int i[5]={1,22,23,14,52};
int qq, k=0;
for( qq=0; qq<5; qq++) {
songs[0].pitch[qq]=i[qq];
}
for (k=0; k<5; k++) printf("%d\n",songs[0].pitch[k]);
return 0;
}

C does not let you copy arrays into arrays. You have to do an element by element copy.
struct songs {int pitch[5], length[5];} songs[4];
int i[5]={1,22,23,14,52};
int k=0;
for (k=0; k<5; k++) songs[0].pitch[k] = i[k];
for (k=0; k<5; k++) printf("%d\n",songs[0].pitch[k]);

when you declare an array, you have 2 options:
int * i; // #1; you do this when you don`t know the size
int i[size]; // #2
you can not assign an array to another array.
what you need to do, as others suggested, is to copy all elements of the array one by one:
for (int j = 0; j < 5; j++) {
songs[0].pitch[j] = i[j];
}
remember that using the index operator, [], is the same as dereferencing the pointer.
even more, when you say pitch[j] you actually move the pointer j positions forward and dereference it; like you would be saying *(pitch+j)

the following, compiles, runs, works.
notice the correction to the declaration of main
notice the addition of #include string.h to support memcpy function
notice the proper return statement at the end
and most importantly,
notice the correct method of copying an array
as a side note:
making the struct tag name and the instance name the same
is very bad programming practice
#include <stdio.h>
#include <string.h>
int main()
{
struct songs
{
int pitch[5];
int length[5];
} songs[4];
int i[5]={1,22,23,14,52};
int k=0;
memcpy( songs[0].pitch, i, sizeof( i ) );
for (k=0; k<5; k++)
{
printf("%d\n",songs[0].pitch[k]);
} // end for
return(0);
}

Problem is here,
songs[0].pitch=i;
Use int* in the structure, You can't assign an array to another array and name of the structure and the structure object.
This would work.
struct Songs {int* pitch, length[5];} songs[4];

Related

C: Passing an arbitrary sized array to a function

I am attempting to write a C program which reads input from a text file and puts it into a 2D-array where Rows are lines and columns are characters.
However I am confused after reading the following article:
http://c-faq.com/aryptr/pass2dary.html
The function definition which I am thinking of is
int processArray(char **text) {
...
...
}
where I am attempting to pass in a pointer to a 2D array whose dimensions I don't know until runtime. I would like to be able to access the elements using two square brackets [] []
However in the link it says the following:
An intermediate pointer would have to be used when attempting to call
it with a two-dimensional array:
extern g(int **ipp);
int *ip = &array[0][0];
g(&ip); /* PROBABLY WRONG */
but this usage
is misleading and almost certainly incorrect, since the array has been
``flattened'' (its shape has been lost).
What is wrong with the above declaration?
How should you define an array to multiple dimensions?
Leaving aside VLAs you can use a simple pointer to point your matrix:
#include "stdio.h"
#define MAX_ROWS 2
#define MAX_COLS 2
void test (int *matrix, int col_max, int row_max)
{
for (int i=0; i<row_max; i++)
{
for (int j=0; j<col_max; j++)
{
printf("matrix[%d][%d]= %d\n", i, j, *(matrix+(i*col_max)+j) );
}
}
}
int main(void)
{
int matrix[MAX_ROWS][MAX_COLS] = { {1,2}, {3,4} };
test(&matrix[0][0], MAX_ROWS, MAX_COLS);
return 0;
}

Ways to pass 2D Array to function in C

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 :)

Pass a 2D char array to a function in C

I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.
I identify the array and the function in the main function as, and after initializing it, attempt to call it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int const ROWS = 8;
int const COLS = 8;
int main(int argc, char** argv) {
char board[ROWS][COLS];
bool canReach(char board[][], int i, int j);
//initialize array
//values of i and j given in a for loop
canReach(board, i, j);
return (EXIT_SUCCESS);
}
While writing the function outside the main function, I defined it exactly the same as I did in the main function.
bool canReach(char board[][], int i, int j){
//Functions purpose
}
When I attempt to build the program, I'm given this error twice and the program does not build:
error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
^
Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!
You can just pass arrays as function arguments with definition of their size.
bool canReach(char board[ROWS][COLS], int i, int j);
When the size is unknown, pointers are the way.
bool canReach(char* board, int i, int j);
You should know, that arrays != pointers but pointers can storage the address of an array.
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool canReach( int n, int m, char board[][m] )
{
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
{
board[i][j] = 0;
}
}
return printf( "Hello SaarthakSaxena" );
}
int main( void )
{
const int ROWS = 8;
const int COLS = 8;
char board[ROWS][COLS];
canReach( ROWS, COLS, board );
return EXIT_SUCCESS;
}
Its output is
Hello SaarthakSaxena
Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.
You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.
It also is not a good idea to use const variables for array dimensions in C. Instead
#define ROWS 8
#define COLS 8
Assuming i and j are the indexes of an element in the array, you can use the signature:
bool canReach(size_t rows, size_t cols, char board[rows][cols],
size_t i, size_t j);
This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:
bool canReach(char board[ROWS][COLS], size_t i, size_t j);
But only if using the macros above. It does not work with the const variables.
Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.
Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.
Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.

How can I define typedef matrix in ansi c

I have 2 .c files, adj.c and main.c.
What i try to do is to define at adj.c
#define N 12
typedef int adj_mat[N]
and use this typedef at main.c as two dimensional array
I tried to define like this,
adj_mat mat[N];
I have a fucntion in my program that fills this matrix with zero, with definition:
void fill_mat_zero(adj_mat);
My problem that if i run this program with Visual studio there are no problems,
but if i try to compile it in Ubuntu it shows me an error that looks like:
note: expected ‘int ’ but argument is of type ‘int ()[12]’
What is the problem here? The definiton of typedef is not correct?
Is there a way to define an adn_mat[N] array as typedef and later use it as multidimensional array?
thank you.
It is unclear from the question whether you want a 1-D array which you will index as if it is a 2-D, for example
adj_mat[3*row + col]
In this case, your declararations are only partially made. This compiles cleanly, I removed the [N] from your declaration and added an identifier to the function argument.
#define N 12
typedef int adj_mat[N];
void fill_mat_zero(adj_mat m) {
int i;
for (i=0; i<N; i++)
m[i] = 0;
}
int main(void){
adj_mat mat;
fill_mat_zero(mat);
return 0;
}
Or perhaps you want to make it 2-D by having an array of adj_mat[].
#define N 12
typedef int adj_mat[N];
void fill_mat_zero(adj_mat *m, int size) {
int i, j;
for (i=0; i<N; i++)
for (j=0; j<size; j++)
m[i][j] = 0;
}
int main(void){
adj_mat mat[N];
fill_mat_zero(mat, N);
return 0;
}
But if you want to fill an array with 0 it is more efficient to use memset().
This
#define N 12
typedef int adj_mat[N]
defines adj_mat as 12-element array of type int.
This
adj_mat mat[N];
defines mat as a 12-element array of type adj_mat, which means mat is actually an int[12][12]. So you get the error.
And
void fill_mat_zero(adj_mat);
is a declaration, not a definition. A definition has a body of code. Think of a declaration as just like a customs declaration when you're entering a country - you declare that you have something, but the declaration isn't actually that thing.

what is "error: variable-sized object may not be initialized"?

I'm trying to fill an array with numbers from 1-100 with this code:
#include <stdio.h>
int main()
{
int num[100];
int i = 0;
for (i = 0; i < 100; i++)
{
int num[i] = i+1;
}
}
but I'm getting this error:
c:18:13: error: variable-sized object may not be initialized
I'm still relatively new to programming so I'm not sure what this means. Can you tell me?
Replace this
int num[i] = i+1;
For this:
num[i] = i+1;
You already declare the array on the top int num[100];
First you declare the array, and then you iterate over it inside the loop.
Since you are new, it is preferable you start by reading a good book about the subject my recommendation.
The problem is the int in int num[i] = i+1. The compiler thinks you're trying to declare a new array (also called num) with i elements in it (that's the variable-sized object part). Just remove the int from that line.
You are declaring the array again in the loop:
int num[i] = i+1;
Anyway, this is the error in your code but the problem for the compiler is not there: it gives you that error because that's not a valid declaration with initialization for an array. If you just write int num[i]; the code it's valid code and it will compile without error (well, only from C99, old C89 doesn't support variable-length arrays). This is what the compiler recognizes and tries to report.

Resources