I was trying to initialize and print array of pointers to integers.
Is this method of initialization is correct or any other method is available to initialize when we declare it as array of pointers. We can also use traditional array of arrays ar1[][] anyway.
#include <stdio.h>
#include <stdlib.h>
#define NUM_COLS 4
#define NUM_ROWS 3
int main(void)
{
int rowCnt;
int colCnt;
int *ar2[NUM_ROWS]={
(int[]){11,12,13,14},
(int[]){21,22,23,24},
(int[]){31,32,33,34},
};
for(rowCnt=0;rowCnt<NUM_ROWS;rowCnt++)
{
for(colCnt=0;colCnt<NUM_COLS;colCnt++)
{
printf("%d\t",*(*(ar2+rowCnt)+colCnt));
}
printf("\n");
}
return(0);
}
This initialization is correct; compound literals have lifetime to match the block they are declared in. The literals have the same lifetime as ar2 in this case.
However I would recommend using a simple array as in dbush's answer unless you have some extra requirement (such as wanting rows of differing lengths).
Since you know the number of rows and colums, you can define a 2D array (formally an array of arrays) instead of an array of pointers:
int ar2[NUM_ROWS][NUM_COLS]={
{11,12,13,14},
{21,22,23,24},
{31,32,33,34},
};
This declaration below is incorrect.
int *ar2[NUM_COLS]={
(int[]){11,12,13,14},
(int[]){21,22,23,24},
(int[]){31,32,33,34},
};
This is an array of NUM_COLS of pointers to ints. The memory of these pointers to ints do not get properly allocated this way, and will result in undefined behavior.
If you wanted to allocate the entire array on the stack, you could do something like this:
int ar2[NUM_ROWS][NUM_COLS]= {
{11,12,13,14},
{21,22,23,24},
{31,32,33,34},
{0,0,0,0}
};
If you want the pointers to ints to be properly on the heap, you should use malloc/free respectively
int *ar2[NUM_ROWS];
for (int i = 0; i < NUM_ROWS; ++i)
{
ar2[i] = (int*)malloc(sizeof(int) * NUM_COLS);
}
///now you can set up your arrays
memcpy(ar2[0], (int []){11,12,13,14}, 4 * sizeof(int));
memcpy(ar2[1], (int []){21,22,23,24}, 4 * sizeof(int));
memcpy(ar2[2], (int []){31,32,33,34}, 4 * sizeof(int));
///Do what you want with the array
...
///Free array once you are done
for (int i = 0; i < NUM_ROWS; ++i)
{
free(ar2[i]);
}
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[]).
Im trying to initialize 2d array of chars with this ode
int x=4;
int y=4;
char plg[x][y]={{"o","o","o","o"},{"o","o","o","o"},{"o","o","o","o"},{"o","o","o","o"}};
but this piece of code throws error error: excess elements in char array initializer| i was searching for a while and everything says this is the rigth method how to do 2d char array. Why does it throw error?
In C you cannot use dynamic expressions as array sizes for global variables. It is possible for local variables since the C99 Standard, but these arrays known as VLA cannot be initialized.
For your purpose, you must specify the size directly with literal constants or constant expressions. You can use macros to increase readability, but it is a bad idea to #define x 4 as short identifiers like x may be used elsewhere in your program and will be substituted as well, leading to obscure bugs.
You cannot initialize the 2D array of char with a string for each individual char, you can either use character literals this way:
char plg[4][4] = {
{'o','o','o','o'},
{'o','o','o','o'},
{'o','o','o','o'},
{'o','o','o','o'}
};
Or you can use string literals to initialize the last level of the array:
char plg[4][4] = {"oooo", "oooo", "oooo", "oooo" };
Note that although you can elide the inner braces with char literal initializers this way:
char plg[4][4] = {'o','o','o','o','o','o','o','o','o','o','o','o','o','o','o','o' };
It is not possible to coalesce string initializers this way:
char plg[4][4] = { "oooooooooooooooo" }; // warning: initializer-string for char array is too long
The syntax above only initializes the first subarray with 'o's, leaving the remaining 3 initialized with '\0's
If you really need for the sizes to be dynamic, you will need to initialize the array some other way:
void myfunc(int x, int y) {
char plg[x][y];
int scores[x][y];
// you can initialize char arrays this way
memset(plg, 'o', sizeof(plg));
// you need a loop for other types
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
scores[i][j] = 1;
}
}
...
}
You still need to be careful with this feature: you must check user input a avoid allocating too much data in automatic storage (aka on the stack). Sufficiently large or possibly negative values of x or y will invoke undefined behavior. Only small values should be allowed, typically less than 256. For a more general solution, you will need to allocate plg from the heap.
"this is a string"
and
'o' /* this is a character */
#define N_ROWS 4
#define N_COLS 4
you have to replace " with ' (single) cause it's not string but chars:
char plg[N_ROWS][N_COLS]={{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'}};
moreover the initializers have to be definied during compile time not during runtime otherwise it would be a dynamic array for which you need to allocate memory manually.
Usually you need to define rows and cols when declaring a matrix, such as:
#define N_ROWS 4
#define N_COLS 4
char plg[N_ROWS][N_COLS]={{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'},{'o','o','o','o'}};
Now if you need rows and cols as input variables, you need to dynamically allow the array. For example,
#include <stdlib.h>
#include <string.h>
int x = 4;
int y = 4;
char **plg = malloc(sizeof(char *) * x);
int i = 0;
for( i = 0; i < x; i++ )
{
plg[i] = malloc(sizeof(char) * (y + 1)); // +1 for NULL terminator
}
for( i = 0; i < x; i++ )
{
strcpy( plg[i], "oooo" );
printf( "%s \n", plg[i] );
}
An example to illustrate:
#include <stdlib.h>
#include<stdio.h>
void simple_function(int s , int array[][s]);
int main(void){
int x;
/*Static 2D Array*/
int array[2][2];
/*Many Methods to Dynamically Allocate 2D Array....for example*/
/* Using Array of pointers*/
int *array1[2];
for(x=0;x<2;x++){array1[x] = calloc (2, sizeof(int));}
/*Using pointer to a pointer */
int **array2 = calloc (2, sizeof(int*));
for(x=0;x<2;x++){array2[x] = calloc (2, sizeof(int));}
/*Using a single pointer*/
int *array3 = calloc (4 , sizeof(int));
/* Codes To Fill The Arrays*/
/*Passing the Arrays to the function, some of them won't work*/
simple_function(2, array); /*Case 1*/
simple_function(2, array1); /*Case 2*/
simple_function(2, array2); /*Case 3*/
simple_function(2, array3); /*Case 4*/
return 0;
}
void simple_function (int s, int array[][s]){
int x,y;
for(x=0;x<s;x++){
for(y=0;y<s; y++){
printf ("Content is %d\n", array[x][y]);
}
}
}
My Question:
Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose? If not, what is the most preferable for the function if I want to make a library?
You've actually declared two different types of objects, as shown below
Your array and array3 are both stored in memory as 4 contiguous ints. There's no additional information, you've simply reserved space for 4 ints, and the C specification requires that they are contiguous.
However, array1 and array2 are actually pointer arrays. Your code reserves memory for an array of two pointers, and each pointer points to an array of two ints. The ints will be arranged in groups of two, but the groups can be scattered anywhere in memory.
From this, it should be clear that the compiler cannot use the same code to access both types of array. For example, let's say that you're trying to access the item at array[x][y]. With a contiguous array, the compiler computes the address of that item like this
address = array + (x * s + y) * sizeof(int)
With a scattered array, the compiler computes the address like this
pointer = the value at {array + x * sizeof(int *)}
address = pointer + y * sizeof(int)
So you need two functions to handle those two cases. For the contiguous array, the function looks like this
void showContiguousArray( int s, int array[][s] )
{
for ( int x=0; x<s; x++ )
for ( int y=0; y<s; y++ )
printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}
For the scattered array, the function is
void showScatteredArray( int s, int **array )
{
for ( int x=0; x<s; x++ )
for ( int y=0; y<s; y++ )
printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}
Notice that those functions are identical, except for one thing, the type of the array argument. The compiler needs to know the type in order to generate the correct code.
If the array is declared in the same scope where it's used, then all of these details are hidden, and it seems that you're using the exact same code to access different types of arrays. But that only works because the compiler knows the type of the array from the earlier declaration. But if you want to pass the array to a function, then the type information must be explicitly specified in the function declaration.
Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose?
"All the cases" apparently describes the different declarations array, array1, array2, and array3, the latter three of which are described in code comments as "Methods to Dynamically Allocate 2D Array." But none of the four types are the same as any of the others, and none of the latter three in fact declare 2D arrays nor pointers to such. None of them are even compatible with each other. Of the dynamic ones, only array3 can even usefully be converted to something comparable to array.
A dynamically-allocated 2D array would be referenced via a pointer of this type:
int (*array4)[2];
array4 = calloc(2 * sizeof(*array4));
So, no.
If not, what is the most preferable for the function if I want to make a library?
It depends on your objectives. If your function must be compatible with static 2D arrays, then something of the general form you presented, plus or minus the variable dimension, is the only alternative. If you want to support the pointer-to-pointer form, then that's fine, and usable with declarations like array1's and array2's, but not with array, array3, or array4.
Assuming that you want this for 2D arrays, perhaps this can get you started ...
void simple_function(int s, int t , int* array) {
int i, j;
for (i=0; i<s; i++) {
for (j=0; j<t; j++) {
// accessing your array elements
printf(" %d", *(array + i*t + j));
}
printf("\n");
}
}
int main(void)
{
int array[2][3];
array[0][0] = 1;
array[0][1] = 2;
array[0][2] = 3;
array[1][0] = 11;
array[1][1] = 12;
array[1][2] = 13;
array[2][0] = 21;
array[2][1] = 22;
array[2][2] = 23;
simple_function(3, 3 , array);
return 0;
}
The expression int **array2 is not a 2D array by the way, it is a variable that holds the address of a pointer variable.
I recently started programming C just for fun. I'm a very skilled programmer in C# .NET and Java within the desktop realm, but this is turning out to be a bit too much of a challenge for me.
I am trying to do something as "simple" as returning a two-dimensional array from a function. I've tried researching on the web for this, but it was hard for me to find something that worked.
Here's what I have so far. It doesn't quite return the array, it just populates one. But even that won't compile (I am sure the reasons must be obvious to you, if you're a skilled C programmer).
void new_array (int x[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
return x;
}
And usage:
int x[n][n];
new_array(x);
What am I doing wrong? It should be mentioned that n is a constant that has the value 3.
Edit: Here's a compiler error when trying to define the constant: http://i.imgur.com/sa4JkXs.png
C does not treat arrays like most languages; you'll need to understand the following concepts if you want to work with arrays in C.
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. This result is not an lvalue; it cannot be the target of an assignment, nor can it be an operand to the ++ or -- operators.
This is why you can't define a function to return an array type; the array expression will be converted to a pointer type as part of the return statement, and besides, there's no way to assign the result to another array expression anyway.
Believe it or not, there's a solid technical reason for this; when he was initially developing C, Dennis Ritchie borrowed a lot of concepts from the B programming language. B was a "typeless" language; everything was stored as an unsigned word, or "cell". Memory was seen as a linear array of "cells". When you declared an array as
auto arr[N];
B would set aside N "cells" for the array contents, along with an additional cell bound to arr to store the offset to the first element (basically a pointer, but without any type semantics). Array accesses were defined as *(arr+i); you offset i cells from the address stored in a and dereferenced the result. This worked great for C, until Ritchie started adding struct types to the language. He wanted the contents of the struct to not only describe the data in abstract terms, but to physically represent the bits. The example he used was something like
struct {
int node;
char name[14];
};
He wanted to set aside 2 bytes for the node, immediately followed by 14 bytes for the name element. And he wanted an array of such structures to be laid out such that you had 2 bytes followed by 14 bytes followed by 2 bytes followed by 14 bytes, etc. He couldn't figure out a good way to deal with the array pointer, so he got rid of it entirely. Rather than setting aside storage for the pointer, C simply calculates it from the array expression itself. This is why you can't assign anything to an array expression; there's nothing to assign the value to.
So, how do you return a 2D array from a function?
You don't. You can return a pointer to a 2D array, such as:
T (*func1(int rows))[N]
{
T (*ap)[N] = malloc( sizeof *ap * rows );
return ap;
}
The downside to this approach is that N must be known at compile time.
If you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you could do something like the following:
void func2( size_t rows, size_t cols, int (**app)[cols] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...; // the parens are necessary
...
}
If you don't have variable-length arrays available, then at least the column dimension must be a compile-time constant:
#define COLS ...
...
void func3( size_t rows, int (**app)[COLS] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...;
}
You can allocate memory piecemeal into something that acts like a 2D array, but the rows won't necessarily be contiguous:
int **func4( size_t rows, size_t cols )
{
int **p = malloc( sizeof *p * rows );
if ( p )
{
for ( size_t i = 0; i < rows; i++ )
{
p[i] = malloc( sizeof *p[i] * cols );
}
}
return p;
}
p is not an array; it points to a series of pointers to int. For all practical purposes, you can use this as though it were a 2D array:
int **arr = foo( rows, cols );
...
arr[i][j] = ...;
printf( "value = %d\n", arr[k][l] );
Note that C doesn't have any garbage collection; you're responsible for cleaning up your own messes. In the first three cases, it's simple:
int (*arr1)[N] = func(rows);
// use arr[i][j];
...
free( arr1 );
int (*arr2)[cols];
func2( rows, cols, &arr2 );
...
free( arr2 );
int (*arr3)[N];
func3( rows, &arr3 );
...
free( arr3 );
In the last case, since you did a two-step allocation, you need to do a two-step deallocation:
int **arr4 = func4( rows, cols );
...
for (i = 0; i < rows; i++ )
free( arr4[i] )
free( arr4)
Your function return void, so the return x; line is superfluous. Aside from that, your code looks fine. That is, assuming you have #define n 3 someplace and not something like const int n = 3;.
You can't return an array in C, multidimensional or otherwise.
The main reason for this is that the language says you can't. Another reason would be that generally local arrays are allocated on the stack, and consequently deallocated when the function returns, so it wouldn't make sense to return them.
Passing a pointer to the array in and modifying it is generally the way to go.
To return (a pointer to) a newly-created array of dimensions known at compile time, you can do this:
#define n 10 // Or other size.
int (*new_array(void))[n]
{
int (*x)[n] = malloc(n * sizeof *x);
if (!result)
HandleErrorHere;
for (int i = 0; i < n; ++i)
for (int o = 0; i < n; ++o)
x[i][o] = InitialValues;
return x;
}
…
// In the calling function:
int (*x)[n] = new_array();
…
// When done with the array:
free(x);
If the size is not known at compile time, you cannot even return a pointer to an array. C does support variable-length arrays but not in the return types of functions. You could instead return a pointer to a variable-length array through a parameter. That requires using a parameter that is a pointer to a pointer to an array of variable length, so it gets somewhat messy.
Also, the preferred choices between allocating an array in the caller dynamically, allocating an array in the caller automatically, allocating an array in the called function dynamically and using variable-lengths arrays or fixed-length arrays or even one-dimensional arrays with manual indexing depend on context, including what how large the array might be, how long it will live, and what operations you intend to use it for. So you would need to provide additional guidance before a specific recommendation could be made.
In C there's only pass/return by value (no pass by reference). Thus the only way of passing the array (by value) is to pass its address to the function, so that it can manipulate it through a pointer.
However, returning by value an array's address isn't possible, since by the time control reaches the caller, the function goes out of scope and its automatic variables go down with it too. Hence if you really have to, you can dynamically allocate the array, populate and return it, but the preferred method is passing the array and leaving the onus of maintaining the array to the caller.
As for the error, the only warning I get in GCC for this is warning: 'return' with a value, in function returning void which is simply meaning that you shouldn't return anything from a void function.
void new_array (int x[n][n]); what you're really doing here is taking a pointer to an array of n integers; the decayed type is int (*x)[n]. This happens because arrays decay into pointers generally. If you know n at compile time, perhaps the best way to pass is:
#define n 3
void new_array (int (*x)[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
}
And call it as
int arr[n][n];
new_array(&arr);
You can pass around arbitrarily dimensions arrays like any another variable if you wrap them up in a struct:
#include <stdio.h>
#define n 3
struct S {
int a[n][n];
};
static struct S make_s(void)
{
struct S s;
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
s.a[i][j] = i + j;
}
return s;
}
static void print_s(struct S s)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf(" %d", s.a[i][j]);
printf("\n");
}
}
int main(void) {
struct S s;
s = make_s();
print_s(s);
return 0;
}
You are probably declaring n as a constant integer:
const int n = 3;
Instead, you should define n as a preprocessor definition:
#define n 3
I want to scan a 2D array with the help of pointers and have written this code, could you tell me why the compiler gives errors?
#include<stdio.h>
#include<stdlib.h>
int main(void) {
int i,j,n,a,b;
int (*(*p)[])[];
printf("\n\tEnter the size of the matrix in the form aXb\t\n");
scanf("%dX%d",&a,&b);
p=(int (*(*p)[b])[a])malloc(b*sizeof(int (*p)[a]));
for(i=0;i<b;i++) {
p[i]=(int (*p)[a])malloc(a*sizeof(int));
printf("\t\bEnter Column %d\t\n");
for(j=0;j<a;j++)
scanf("%d",&p[i][j]);
}
return 0;
}
This statement has several problems:
p=(int (*(*p)[b])[a])malloc(b*sizeof(int (*p)[a]));
First, malloc returns a void*. You are casting that pointer using (int (*(*p)[b])[a]) which yields a value, not a data type. That isn't a valid cast, so that's one reason that the compiler is yelling at you. At this point, p hasn't been initialized so the de-referencing taking place here can crash your program if this statement was executed.
Inside your malloc call, you are using sizeof(int (*p)[a]). The statement int (*p)[a] isn't a valid C statement.
It seems that you are making this a bit more complex that it needs to be. There are two ways of building a 2D array. You can build an array using malloc(a * b * sizeof(int)) as Reinderien explains. You can also build a 1D array of pointers, each pointing to an array of type int. From your code, it seems you are trying to do the latter.
The easier way to do this would be something like this:
int **p;
... get input from user ...
// Declare an array of int pointers of length b
p = malloc(b * sizeof(int*));
// For each int* in 'p' ...
for (i = 0; i < b; ++i) {
// ... allocate an int array of length 'a' and store a pointer in 'p[i]' ..
p[i] = malloc(a * sizeof(int));
// ... and fill in that array using data from the user
printf("\t\bEnter Column %d\t\n");
for(j = 0; j < a; j++)
scanf("%d", &p[i][j]);
}
Using this method of building a 2D array allows you to use the syntax p[x][y]. Since p is a pointer-to-pointer, p[x] is a pointer to an array and p[x][y] is an item in the pointed-to array.
That's some pretty contorted syntax. Usually when you make a 2D array:
The declaration is simply int *p;
The allocation is simply p = malloc(a*b*sizeof(int));
You cannot write p[i][j]. You must do one of several things - either make a secondary array int **q that contains row pointers to be able to write q[i][j] (better performance and legibility), or write p[b*i + j] (fewer steps).
Additionally, note that:
Your printf will spew garbage due to the missing %d parameter.
Since C is not typesafe, using scanf will hide any errors in indirection that you may make.
About the closest thing I could think of that remotely resembles what you were trying to do:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j;
const int a = 3, b = 4;
int m[4][3];
int (*p[4])[3];
for (i = 0; i < b; i++)
{
p[i] = &m[i];
printf("\t\bEnter Column %d\t\n", i);
for (j = 0; j < a; j++)
{
int x;
scanf("%d", &x);
(*p[i])[j] = x;
}
}
return 0;
}
It compiles and functions as expected, but it's pointlessly complicated. p is an array of pointers to arrays.