I have a 1D array A[3] & a 2D array B[4][3]. I want to assign the array A[3] to one of the rows of array B[4][3]. How to do it correctly?
#include<stdio.h>
void main()
{
int A[3]={1,2,3};
int B[4][3]={0};
int row_select=2;
B[row_select][] = A;
}
But this assignment doesn't work. I don't want to assign element by element using a for loop. I want to do it in one statement.
memcpy could be a good option, although it's very likely it uses a loop internally.
memcpy(B[row_select], A, sizeof(A));
Don't Do This: Use memcpy
There is a way to do the assignment with a single statement, as long as you are willing to do some preliminary setup to render your code illegible. Your can use the fact that structures can (1) be assigned to each other in one step, and (2) contain fixed-size arrays. The compiler will probably run memcpy under the hood anyway, but it's a fun exercise in ridiculousness:
#include<stdio.h>
#define SZ 3 // this is just for convenience
// a pointer to an anonymous structure containing our array
typedef struct {
int x[SZ];
} *pthrowaway;
int main(void)
{
int A[SZ]={1,2,3};
int B[4][SZ]={0};
int row_select=2;
pthrowaway a = (pthrowaway)&A;
pthrowaway b = (pthrowaway)&B[row_select];
*b = *a; // magic
return 0;
}
The variables a and b are unnecessary. You can actually assign the arrays in a single statement:
*(pthrowaway)&B[row_select] = *(pthrowaway)&A;
Here is an IDEOne link showing the C99 version: https://ideone.com/IQ6ttg
And here is a regular C one: https://ideone.com/pH1hS2
Related
This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 4 years ago.
In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
I wanted to know how I should define the function so the length of the array is read correctly in the function.
There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []).
But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1
Don't use a function, use a macro for this:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.
Alternative if you want to pass one data type around is to define a type that has both an array and capacity:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
This takes longer to set up, but is useful if you find your self passing it around many many functions.
As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
When you write size(ar) then you're passing a pointer and not an array.
The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as #H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).
Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.If you want to pass the size of the array, you should pass it as a separated argument.
I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.
You need to wrap the array up into a struct:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.
I'm new to programming and I don't really understand this question. Can some of you give me examples of what it means. How do I write a function where a is int values and n is the length?
I'm confused...
I'm not sure what your question is, as you haven't provided much information. However, a function in C is defined like this:
return_type function_name( parameter list ) {
body of the function
}
So, for this situation, we could say:
void arrayFunction( int a[], int n){
//do whatever you need to do with the function here
}
This may help you some.
Suppose you have an array of ints, as follows:
int arr[] = {2,3,4,5,6};
You can see that there are 5 elements inside above array arr. You can count them.
But it happens that when you pass the above arr to function, that function has no idea about how many elements arr contains. See below (incorrect) code snippet:
#include <stdio.h>
void display(int arr[]){
}
int main(void) {
int arr[] = {2,3,4,5,6};
display(arr);
return 0;
}
The function named 'display()' has no idea about how many elements arr has
Therefore you you need to pass the extra argument (the extra argument called 'n') to tell that called function about the number of elements inside arr. You need to tell this separately - the length of arr.
Now this becomes - as you said in your question - arr is int values and n is the length
Below is the correct code:
#include <stdio.h>
void display(int a[], int n){
//Now display knows about lenth of elemnts in array 'a'
// Length is 5 in this case
}
int main(void) {
int arr[] = {2,3,4,5,6};
display(arr, 5);
return 0;
}
Now, the function named 'display()' knows the length of array of int. This is the way you write code where you specify your array and its length.
More formally, this is because while passing array, it decays to a pointer and so the need arises to pass its length also alongwith it.
I am not very good at C and I am really confused about double array. Below is an outline of a code I have a question about. Main function calls CreateRandConn function and passes it a 2D array filled with 0 as an argument. CreateRandConn function takes a 2D array as a parameter, changes some of the value in 2DArray from 0 to 1 and returns the changed 2DArray back to main. I want to indicate in the function prototype the return type of CreateRandConn function is a 2D array. How do I indicate that? I don't really understand the syntax. Is what I wrote wrong? Is the way I am passing the 2DArray as a parameter in the function header incorrect? If so, how I do write it? I still get confused about the relationship between pointers and double arrays. Can someone explain it with the below code outline? Hopefully someone knows what my question is...
//Function prototype
int ** CreateRandConn(char * RandRoom[7], int my2DArray[7][7], char * room_dir);
//Function
int ** CreateRandConn(char * RandRoom[7], int my2DArray[7][7], char * room_dir)
{
...
return my2DArray;
}
int main()
{
int 2DArray[7][7] = {0};
2DArray = CreateRandConn(RandRoomArray, my2DArray[7][7], room_dir);
return 0;
}
I don't really understand the syntax.
Ok, so let's recap the basics:
One cannot assign to an array variable.
If an array gets passed to a function it "decays" to a pointer to its 1st element.
A multidimensional array is just an array of arrays. So a 2D-array is a 1D-array of 1D-arrays, a 3D-array is a 1D-array of 2D-arrays, a 4D-array is a 1D-array of 3D-arrays, and so on ...
A pointer p to an array of N elements of type T is to be defined as: T (*p)[N]
Now for you example:
You have
int 2DArray[7][7] = ...;
for the sake of clarity of the following explanations I change this to be
int a[5][7] = ...;
So this then is passed to a function. Where the following happens/applies:
Following 1. above, it is not possible to pass an array, as if it were possible one would assign it to the variable inside the function, as arrays cannot be assigned, one cannot pass an array.
Following 2. above, the function would need to define the related variable as "a pointer to the arrays 1st element".
Following 3. above, the a's 1st element is an int [7]
Following 4. above, a pointer to an int[7] will be defined as: int(*)[7].
So the function's relevant variable would look like:
... func(int (*pa)[7])
pa points to the 1st element of a. As a side note: From this pointer a the function cannot derive how many elements a actually "provides", will say: how many valid element after the one a points to will follow, so this needs to be passed to the function as well:
... func(int (*pa)[7], size_t rows)
From the steps so far we learned, that an array is not passed, but just a pointer to it's 1st element *1 is passed, is copied into the function's local variable (pa here).
From this directly follows that an array cannot be passed back as the function's return value, but just a pointer to an array's element (typically the 1st)
Looking at how a pointer to an array is defined: T (*p)[N] we know need to derive how a function returning a pointer to an array would look. The function's defalcation somewhat needs to become the p above. So taking T as int and N as 7 we then get:
int (*func(int (*pa)[7], size_t rows))[7];
The trivial implementation and usage then would be:
#include <stdlib.h> /* for size_t */
#define ROWS (5)
#define COLS (7)
int (*func(int (*pa)[COLS], size_t rows))[COLS];
int (*func(int (*pa)[COLS], size_t rows))[COLS]
{
for (size_t i = 0; i < rows; ++i)
{
for (size_t j = 0; j < COLS; ++j)
{
pa[i][j] = 0;
}
}
return pa;
}
int main(void)
{
int a[ROWS][COLS];
int (*pa)[COLS] = func(a, ROWS);
return EXIT_SUCCESS;
}
*1
(which sloppy, but wrongly spoken often is referred to as "a pointer to an array is passed", which in general it is not, but just here, as it's a 2D-array, will say the array's elements are arrays themselves).
If you understood the above, then just for completeness following a less strange looking (but also probably less educational ;-)) version of the above function declaration. It may be declared by using a typedef construct hiding away the somehow complicated declaration of the array-pointers as parameter and return type.
This
typedef int (*PA)[COLS];
defines a type pointing a an array of COLS of ints.
So using PA we can instead of
int (*func(int (*pa)[COLS], size_t rows))[COLS];
write
PA func(PA pa, size_t rows))[COLS];
This version is identical to the above.
And yes it looks simpler, but brings along the fact, that pointers pa and the function's return value) are not identifiable as being pointers by just looking at their definition. Such constructs are considered "bad practice" by many fellow programmers.
This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 4 years ago.
In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
I wanted to know how I should define the function so the length of the array is read correctly in the function.
There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []).
But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1
Don't use a function, use a macro for this:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.
Alternative if you want to pass one data type around is to define a type that has both an array and capacity:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
This takes longer to set up, but is useful if you find your self passing it around many many functions.
As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
When you write size(ar) then you're passing a pointer and not an array.
The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as #H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).
Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.If you want to pass the size of the array, you should pass it as a separated argument.
I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.
You need to wrap the array up into a struct:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.
Let's say that any C function has a pointer already declared, but not assigned any value yet. We will int for our examples.
int *ptr;
The goal of the function is not to assign ptr any dynamic memory on the heap, so no malloc call. Instead, we want to have it point to an array of fixed size n. I know I could accomplish this like so:
int arr[n];
ptr = arr;
However, the code could get very messy and hard to read if we need to do this many times in a function, ie, a struct of many pointer fields all need to point to an array of fixed length. Is there a better way to accomplish this in one line? I was thinking of something similar to below, but it looks too ambiguous and uncompilable:
int *ptr;
// Many other things happen in between...
ptr[n];
***EDIT***
Here, the below additional information may help guide some more answers (not saying that the current answers are not fine). In my use case, the pointers are declared in a struct and, in a function, I am assigning the pointers to an array. I want to know if there is a simpler way to accomplish this than in the below code (all pointers to point to fixed-length array):
struct foo {
int* a;
short* b;
char* c;
...
};
void func(void) {
struct foo f;
int n = ...;
int tempArr1[n];
f.a = tempArr1;
short tempArr2[n];
f.b = tempArr2;
char tempArr3[n];
f.c = tempArr3;
...
}
You cannot declare an array and assign it to an existing pointer in a single declaration. However, you can assign an array pointer to a newly declared pointer, like this:
int arr[n], *ptr = arr;
If you insist on staying within a single line, you could use an ugly macro, like this:
#define DECL_ASSIGN_INT_ARRAY(name,size,pointer) int name[(size)]; pointer = name;
The clarity of this one-liner is far lower than that of a two-line version from your post, so I would keep your initial version.
EDIT (in response to the edit of the question)
Another option is to create an unused pointer variable in a declaration, and assign your pointer in an initializer, like this:
void func(void) {
struct foo f;
int n = ...;
int tempArr1[n], *tempPtr1 = f.a = tempArr1;
short tempArr2[n], *tempPtr2 = f.b = tempArr2;
char tempArr3[n], *tempPtr3 = f.c = tempArr3;
...
}
This seems like a clear case where you're in need of some refactoring. Take the similar statements, extract them into a new function (by passing a reference to the struct and the data you want the struct fields to point to) and give this new function a meaningful name.
This is probably more maintainable and readable than some fancy pointer arithmetic shortcut that you'll forget about in a few weeks or months.
The difference between ptr and arr in you example is you can change ptr's value. So I guess you want to move ptr through the array.
So how about this:
int arr[n], id=0;
And you change the value of id and use arr+id as ptr.
I guess the way to do this is to use a macro. Something like (untested)
#define autoptr(name,size) int Arrayname[size]; name = Arrayname;
I'm not clear why this is helping I think it might "look ugly" but will be easier to maintain without the macro. In general, hiding what you are actually doing is a bad thing.