I want to make a random sized array everytime program executes at first but compiler yells me
"Error 2 error C2466: cannot allocate an array of constant size 0"
Is there any way that I can randomly choose the SIZE by SIZE = rand() % 100 at the beginning and then intialize the array with int myarray[SIZE]={0} ??? or should I everytime initialize it with an exact number at the beginning?
int main(void) {
int i;
int SIZE=rand()%100;
int array2[SIZE]={0};
for(i=0;i<SIZE;i++) //fill the array with random numbers
array2[i]=rand()%100;
...
}
You indicated you're using Microsoft's visual studio. MS visual studio is not c99 compilant (they cherry pick at best) and one of the missing features is VLAs.
The best you'll be able to do with MS VS is to do this dynamically using malloc():
int main(int argc, char *argv[])
{
int i;
int SIZE=rand()%100;
int *array2=malloc(SIZE * sizeof(int)); // allocate space for SIZE ints
for(i=0;i<SIZE;i++) //fill the array with random numbers
array2[i]=rand()%100;
free(array2); // free that memory when you're done.
return 0;
}
If you want to switch compilers, there are other options.
You can use malloc() or calloc() to do this in C. For example,
int SIZE=(rand()%100)+1; // size can be in the range [1 to 100]
int *array2 = (int*) malloc(sizeof(int)*SIZE);
But at the same time, the array size can not be anything other than a constant value.
The following two declarations are valid.
int a[10];
and
#define MAX 10
int b[MAX];
But you will get an error if you try to declare using the following methods.
int x=10;
int a[x];
and
const int y=10;
int b[y];
Note that rand()%100 can and will be 0. If you want a random value 1 <= n <= 100 then you need to use (rand()%100)+1
The best way to do this would be to make your array a pointer and use malloc:
int SIZE=(rand()%100) + 1; //range 1 - 100
int *array2 = malloc(sizeof(int) * SIZE);
Afterwards you can use array2 much as you would use an array.
Related
This question already has answers here:
Can you define the size of an array at runtime in C
(10 answers)
C dynamically growing array
(10 answers)
Closed 2 years ago.
I am trying to create an array of arrays but the the number of subarrays is unknown.
Jagged array is array of arrays such that member arrays can be of different sizes, i.e., we can create a 2-D array but with a variable number of columns in each row.
Static Jagged Array:
int kk0[4] = { 1, 2, 3, 4 };
int kk1[2] = { 5, 6 };
int* jagged[2] = { kk0, kk1 };
Dynamic Jagged Array:
int* jagged[2];
jagged[0] = malloc(sizeof(int) * 1);
jagged[1] = malloc(sizeof(int) * 3);
Reference : https://en.wikipedia.org/wiki/Jagged_array
If the number of sub arrays is not known then the array must be expandable when there are more sub arrays than you thought.
int **myArrays; // the array of arrays
int nSubArrays= 0; // its current size
int nUsed= 0; // how many have been used
#define INCREMENT 5 // increment for alocation
myArrays= malloc(sizeof(int *) * INCREMENT);
nSubArrays= INCREMENT;
nUsed= 0;
now fill the array(s):
myArrays[nUsed]= fillSubArray();
nUsed++;
and expand the array when it becomes full:
if (nUsed==nSubArrays) {
int **tmp= realloc(myArrays, sizeof(int *)*(nSubArrays+INCREMENT));
if (!tmp) return 0; // error
myArrays= tmp;
nSubArrays += INCREMENT;
"create an array of arrays but the the number of subarrays is unknown."
If using C99, or a compiler since then that supports variable length arrays (optional since C11), this would provide a way to do this at run-time. A short example:
#define ARRAY_BASE_SIZE 20 //known at compile time
int main()
{
int numSubArrays = 0;
printf("enter a value for number of sub-arrays:\n");
int count = scanf("%d", &numSubArrays);//not known until run-time
if(count == 1)
{
int array[ARRAY_BASE_SIZE][numSubArrays];
memset(array, 0, sizeof(array));
}
return 0;
}
How about this, its just an attempt to give a start point, not the complete answer, but we can build on this.
Also we need to keep track of size of each subarray to access valid locations, am sure that can be done easily by some kind of book keeping.
#include <stdio.h>
#include <stdlib.h>
#define BASE_SIZE 3
int main()
{
int** dyn_array = NULL;
int countSubArray = 0;
int count = 0;
int size = 0;
dyn_array = malloc(sizeof (int* ) * BASE_SIZE);
if ( dyn_array ) {
printf("enter number of subarrays:");
scanf("%d", &countSubArray);
while( count < countSubArray) {
printf("enter sizeof %d subarray", count+1);
scanf("%d", &size);
if ( dyn_array[count] = malloc(sizeof (int) * size) )
{
printf("Allocated sub array %d at %p\n",count+1, (void*) dyn_array[count]);
}
count++;
}
}
return 0;
}
In C it is very common practice to declare a pointer and reference it as an array. In C an array will decay to a pointer when the reference of the array is assigned to the pointer. To reference an array of arrays, it is common to declare a pointer-to-pointer, assign it to the reference of a 2-D array, and later index it like a 2-D array.
The following are all equivalent. argv is an array of array of char. Using [] makes your intention of using indexing a pointer as an array clear to other programmers who might be reading your code.
char **argv;
char *argv[];
char argv[][]; (this is wrong)
The size of the array is usually communicated separately. In fact, the parameters of the main function does just that. When you see
int main(int argc, char *argv[]);
The char *argv[] is an array of array of characters (aka array of strings) passed from the command line. The argument argc represents the number of arrays in argv. To index the first element in the array, use argv[0], whose type is will be char* (aka char[]).
The Question given to me specifically says that a functions takes an integer 2d array and size as parameters. That means,
1) im not allowed to define the size of the array at the declaration.
2) I have to pass the number of rows and cols into the function.
I did it for 1D array previously and it worked, however in the 2D array case it gives a syntax error. I made test codes to check the logic of the syntax. This is the 1D array logic that works.
Also this module requires me only to use stido.h library in C. The reason for passing the size of array size is to fill the array in a different function where the loop conditions will take the array size to go through indexes
#include<stdio.h>
void print(int table[],int r);
int main()
{ int r=7,table[r];
print(table,r);
}
void print(int table[],int r)
{ printf("table rows is%d\n",r);
}
However this same logic doesnt work for when I try with a 2D array.(gives a syntax error)
#include<stdio.h>
void print(int table[][],int c,int r);
int main()
{int c=7,r=7,table[c][r];
print(table,c,r);
}
void print(int table[][],int c,int r)
{printf("table rows is\ntable cols is\n",r,c)
}
Can someone kindly explain why this is happening, and suggest a solution for this problem. ?
Thanks in advance
You can't have a 2D array with unspecified dimensions. However, it seems that you have a C99+ compiler and therefore can use a variable-length array. However, you need to reorder the arguments too.
Notice that I use size_t here instead of int for the indices/dimensions - as one might have a table (though unlikely) that has more elements than is possible to represent with an int.
#include <stdio.h>
#include <stdlib.h>
void print(size_t, size_t, int [*][*]);
int main(void) {
size_t c = 7, r = 9;
int table[c][r];
print(c, r, table);
}
void print(size_t c, size_t r, int table[c][r]) {
printf("table rows is %zu\ntable cols is %zu\n", r, c);
}
It compiles in C99, (and those C11 compilers that support the optional VLA extension); and when run, it prints
table rows is 9
table cols is 7
First, you want to know why this isn't possible. It's not allowed by the language standard and the technical reason for this is the compiler cannot calculate offsets into the array when a second dimension isn't known.
A 2D array is just like a 1D array a set of values in memory one after the other. It is not, like in some other languages, an array of arrays. With a 2D array like int a[5][3], you have 5 times 3 ints in a row, all in all 15 ints. For accessing an element, the compiler will compute the offset for you, so if you write e.g. a[2][2], this is the 2*3 + 2th element (there are two rows of 3 columns to skip for the beginning of the third row).
If the compiler doesn't know the second dimension, this calculation of offets is impossible.
Antti Haapala's answer already shows how you can get around this using the C99 feature variable length arrays. That's a good approach, but unfortunately, with C11, this feature is optional, so there may be compilers not supporting it. If you're sure to only use compilers supporting VLAs (which is the great majority of all modern C compilers), go with the code from this answer.
When passing an array to a function, instead of the array, a pointer to its first element is passed (the array decays as a pointer). So the following declarations are the same:
void print(size_t n, int arr[]);
void print(size_t n, int *arr);
With that knowledge, you could be tempted to write it differently and do the offset calculations yourself:
void print(size_t r, size_t c, void *data)
{
int *arr = data;
// access arr[2][2]:
int v = arr[2*c + 2];
}
And indeed, this is very likely to work, but be aware this is undefined: int[] and int[][] are not compatible types. For details on this idea, see this question with two quite interesting answers. Bottom line: This kind of code will work with a very high probability. Still, to be sure, don't do it....
So, if you don't have variable length arrays, and if you don't want to rely on something not perfectly well-defined, the only other way would be to actually build an array of arrays by having an array of pointers:
int row1[3] = {0, 1, 2};
int row2[3] = {3, 4, 5};
int *rows[2] = { row1, row2 };
Then you can pass it like this:
void print(size_t r, size_t c, int **arr)
{
int a = arr[0][2]; // 2
}
Of course, this isn't a 2D array any more, it's a replacement construct that can be used in some similar fashion.
You can't pass a 2D array without a defined constant for the final dimension. (absent the C99 VLA additions). You can however change the order of your parameters in print so that r is defined before you declare table as a pointer to array of int [r], and pass table as follows, e.g.
#include<stdio.h>
void print (int c, int r, int (*table)[r]);
int main (void) {
int c = 7, r = 7, table[c][r];
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
table[i][j] = i * j + i + j;
print (c, r, table);
return 0;
}
void print (int c, int r, int (*table)[r])
{
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++)
printf (" %3d", table[i][j]);
putchar ('\n');
}
}
This method is proper for utilizing the VLA with the C99 VLA extensions.
Example Use/Output
$ ./bin/fpass2d
0 1 2 3 4 5 6
1 3 5 7 9 11 13
2 5 8 11 14 17 20
3 7 11 15 19 23 27
4 9 14 19 24 29 34
5 11 17 23 29 35 41
6 13 20 27 34 41 48
If VLA extensions are not available, you can work around that by allocating and then manually indexing 2D array as a 1D array. This works because a 2D array is an array-of-arrays sequentially stored in memory (e.g. a[2][3] is a00,a01,a02,a10,a11,a12 in memory.) To prevent any undefined behavior, you can allocate storage for table (e.g. int *p = malloc (sizeof table); copy table and then index each element calling print (p, c, r) as follows, e.g.
void print (int *table, int c, int r)
{
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++)
printf (" %3d", table[i * r + j]);
putchar ('\n');
}
}
Where table is indexed with table[i * r + j] to access each of the original elements of the 2D array. While this method is a workaround, without the VLA extensions, you would presumably have a defined constant to pass for the final array dimension making the workaround or a change in the order of parameters unnecessary.
Look things over and let me know if you have questions.
First of all, the type of your function argument decays to a pointer to the first element of the array. That is, the following declaration pairs are perfectly equivalent:
void f(int a[]);
void f(int *a);
void g(int a[][7]);
void g(int (*a)[7]);
void h(int a[][7][6]);
void h(int (*a)[7][6]);
Now, when you index into an array, that operation is in fact defined in terms of pointer arithmetic. So, the expression a[3] is in fact equivalent to *(a + 3).
In this expression, a yields a pointer to the first element of the array, and the addition adds the offset to skip three elements of the array. That is, the machine will perform this calculation: *(elementType*)((char*)a + 3*sizeof(elementType))
The crucial part in this is the sizeof(elementType): If the type of a is int[][], then the type of its elements is int[], and you cannot take the size of an array of unknown length for obvious reasons. Consequently, the types of all array dimensions except the outermost one must be known in order to be able to index into the multidimensional array.
So much for the explanation of what's going on. The consequence for you is, that you have to supply the size of the inner dimension. As the other answers have shown, this can be done by simply ordering the size arguments first, so they are available to the declaration of the array argument:
void print(int c, int r, int table[c][r]);
Or, equivalently, as the value of c is actually ignored in the declaration above:
void print(int rowCount, int columnCount, int (*table)[columnCount]) {
printf("table has %d columns and %d rows\n", columnCount, rowCount);
for(int curRow = 0; curRow < rowCount; curRow++) {
for(int curColumn = 0; curColumn < columnCount; curColumn++) {
printf("%d ", table[curRow][curColumn]);
}
printf("\n");
}
}
(I have taken the liberty to use proper formatting and variable names in this last example. Please, never use just a single character for variables names as vital as array dimension sizes.)
I want to know why this program, that i create just for practice, don't works properly. The program asks for 5 numbers that put in an array called "array". There are also 2 VOID functions, one for get the numbers, that uses a for cicle and scanf instruction , and another, that has to print the 5 numbers in the array. The problem is that the numbers printed are only the firsts 4. What's wrong?
P.S. Sorry for my ignorance but i'm a beginner. Here's the code
#include <stdio.h>
#include <stdlib.h>
void
array_print(int array[],size_t size){
int i;
for(i=0;i<size;i++){
printf("%i ",array[i]);
}
}
void
get_num(int array[],size_t size){
int i;
for(i=0;i<size;i++){
scanf("%i",&array[i]);
}
}
int
main(){
int array[5];
size_t size;
size=sizeof(int);
printf("Insert 5 numbers: ");
get_num(array,size);
array_print(array,size);
return 0;
}
In the environment where you run the program sizeof(int) is equal to 4.
The size of the array can be calculated like
size = sizeof( array ) / sizeof( int );
Take into account the type of the value returned by the operator sizeof is size_t. So it would be better to use this type for the size of the array.
Also you could introduce a manifest constant for number 5. As for example
#define N 5
and declare the array like
int array[N];
Or if the compiler supports variable length arrays you could write
int main( void )
^^^^^^^^^^^^^^^^
{
const size_t N = 5;
int array[N];
//...
The architecture of the compiler in which you're executing your code is 32bit so the size of int is 32bits = 4 bytes.
size = sizeof(int)
will return
size = 4
and you will be only able to enter four values.
Is it possible to write a function which accept 2-d array when the width is not known at compile time?
A detailed description will be greatly appreciated.
You can't pass a raw two-dimensional array because the routine won't know how to index a particular element. The 2D array is really one contiguous memory segment.
When you write x[a][b] (when x is a 2d array), the compiler knows to look at the address (x + a * width + b). It can't know how to address the particular element if you don't tell it the width.
As an example, check http://www.dfstermole.net/OAC/harray2.html#offset (which has a table showing how to find the linear index for each element in an int[5][4])
There are two ways to work around the limitation:
1) Make your program work with pointer-to-pointers (char *). This is not the same as char[][]. A char * is really one memory segment, with each value being a memory address to another memory segment.
2) Pass a 1d pointer, and do the referencing yourself. Your function would then have to take a "width" parameter, and you could use the aforementioned formula to reference a particular point
To give a code example:
#include <stdio.h>
int get2(int *x) { return x[2]; }
int main() {
int y[2][2] = {{11,12},{21,22}};
printf("%d\n", get2((int *)y));
}
This should print out 21, since y is laid out as { 11, 12, 21, 22 } in memory.
C supports variable-length arrays. You must specify the width from a value known at run-time, which may be an earlier parameter in the function declaration:
void foo(size_t width, int array[][width]);
One way is use the good old "pointer to array of pointers to arrays" trick coupled with a single continuous allocation:
/* Another allocation function
--------------------------- */
double ** AnotherAlloc2DTable(
size_t size1, /*[in] Nb of lines */
size_t size2 /*[in] Nb of values per line */
)
{
double ** ppValues;
size_t const size1x2 = size1*size2;
if(size1x2 / size2 != size1)
return NULL; /*size overflow*/
ppValues = malloc(sizeof(*ppValues)*size1);
if(ppValues != NULL)
{
double * pValues = malloc(sizeof(*pValues)*size1x2);
if(pValues != NULL)
{
size_t i;
/* Assign all pointers */
for(i=0 ; i<size1 ; ++i)
ppValues[i] = pValues + (i*size2);
}
else
{
/* Second allocation failed, free the first one */
free(ppValues), ppValues=NULL;
}
}/*if*/
return ppValues;
}
/* Another destruction function
---------------------------- */
void AnotherFree2DTable(double **ppValues)
{
if(ppValues != NULL)
{
free(ppValues[0]);
free(ppValues);
}
}
Then all you have to do is pass a char ** to your function. The matrix is continuous, and usable as mat[x][y].
Possible accessor functions:
int get_multi(int rows, int cols, int matrix[][cols], int i, int j)
{
return matrix[i][j];
}
int get_flat(int rows, int cols, int matrix[], int i, int j)
{
return matrix[i * cols + j];
}
int get_ptr(int rows, int cols, int *matrix[], int i, int j)
{
return matrix[i][j];
}
An actual multi-dimensional array and a fake one:
int m_multi[5][7];
int m_flat[5 * 7];
Well-defined ways to use the accessor functions:
get_multi(5, 7, m_multi, 4, 2);
get_flat(5, 7, m_flat, 4, 2);
{
int *m_ptr[5];
for(int i = 0; i < 5; ++i)
m_ptr[i] = m_multi[i];
get_ptr(5, 7, m_ptr, 4, 2);
}
{
int *m_ptr[5];
for(int i = 0; i < 5; ++i)
m_ptr[i] = &m_flat[i * 7];
get_ptr(5, 7, m_ptr, 4, 2);
}
Technically undefined usage that works in practice:
get(5, 7, (int *)m_multi, 4, 2);
[Warning - this answer addresses the case where the number of columns - the WIDTH - is known]
When working with 2D arrays, the compiler needs to know the number of columns in your array in order to compute indexing. For instance, if you want a pointer p that points to a range of memory to be treated as a two-dimensional set of values, the compiler cannot do the necessary indexing arithmetic unless it knows how much space is occupied by each row of the array.
Things become clearer with a concrete example, such as the one below. Here, the pointer p is passed in as a pointer to a one-dimensional range of memory. You - the programmer - know that it makes sense to treat this as a 2D array and you also know (must know) how many columns are there in this array. Armed with this knowledge, you can write code to create q, that is treated by the compiler as a 2D array with an unknown number of rows, where each row has exactly NB columns.
I usually employ this when I want the compiler to do all the indexing arithmetic (why do it by hand when the compiler can do it?). In the past, I've found this construct to be useful to carry out 2D transposes from one shape to another - note though that generalized 2D transposes that transpose an MxN array into an NxM array are rather beastly.
void
WorkAs2D (double *p)
{
double (*q)[NB] = (double (*)[NB]) p;
for (uint32_t i = 0; i < NB; i++)
{
for (uint32_t j = 0; j < ZZZ; j++) /* For as many rows as you have in your 2D array */
q[j][i] = ...
}
}
I believe a nice solution would be the use of structures.
So I have an example for 1d-Arrays:
Definition of the struct:
struct ArrayNumber {
unsigned char *array;
int size;
};
Definition of a function:
struct ArrayNumber calcMultiply(struct ArrayNumber nra, struct ArrayNumber nrb);
Init the struct:
struct ArrayNumber rs;
rs.array = malloc(1);
rs.array[0] = 0;
rs.size = 1;
//and adding some size:
rs.size++;
rs.array = realloc(rs.array, rs.size);
hope this could be a solution for you. Just got to change to a 2d Array.
I am trying to get the number of rows and columns of a 2D Array from a double pointer pointed to the array.
#include <stdio.h>
#include <stdlib.h>
void get_details(int **a)
{
int row = ??? // how get no. of rows
int column = ??? // how get no. of columns
printf("\n\n%d - %d", row,column);
}
Above function needs to print the details of the size, where am going wrong.
int main(int argc, char *argv[])
{
int n = atoi(argv[1]),i,j;
int **a =(int **)malloc(n*sizeof(int *)); // using a double pointer
for(i=0;i<n;i++)
a[i] = (int *)malloc(n*sizeof(int));
printf("\nEnter %d Elements",n*n);
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf("\nEnter Element %dx%d : ",i,j);
scanf("%d",&a[i][j]);
}
get_details(a);
return 0;
}
I am using malloc to create the array.
What if I use something like this
column = sizeof(a)/sizeof(int) ?
C doesn't do reflection.
Pointers don't store any metadata to indicate the size of the area they point to; if all you have is the pointer, then there's no (portable) way to retrieve the number of rows or columns in the array.
You will either need to pass that information along with the pointer, or you will need to use a sentinel value in the array itself (similar to how C strings use a 0 terminator, although that only gives you the logical size of the string, which may be smaller than the physical size of the array it occupies).
In The Development of the C Programming Language, Dennis Ritchie explains that he wanted aggregate types like arrays and structs to not just represent abstract types, but to represent the collection of bits that would occupy memory or disk space; hence, no metadata within the type. That's information you're expected to track yourself.
void get_details(int **a)
{
int row = ??? // how get no. of rows
int column = ??? // how get no. of columns
printf("\n\n%d - %d", row,column);
}
I'm afraid you can't, as all you will get is the size of the pointer.
You need to pass the size of the array.
Change your signature to:
void get_details(int **a, int ROW, int COL)