I was writing a program to concatenate two arrays in C. I am allocating memory for a third array and using memcpy to copy the bytes from the two arrays to the third. The test output is:
1 2 3 4 5 0 0 0 0 0
Is there anything wrong with this approach?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int *array_concat(const void *a, int an,
const void *b, int bn)
{
int *p = malloc(sizeof(int) * (an + bn));
memcpy(p, a, an*sizeof(int));
memcpy(p + an*sizeof(int), b, bn*sizeof(int));
return p;
}
// testing
const int a[] = { 1, 2, 3, 4, 5 };
const int b[] = { 6, 7, 8, 9, 0 };
int main(void)
{
unsigned int i;
int *c = array_concat(a, 5, b, 5);
for(i = 0; i < 10; i++)
printf("%d\n", c[i]);
free(c);
return 0;
}
memcpy(p + an*sizeof(int),...
this second memcpy, you are trying to add 5 * sizeof(int) to an int pointer, p. However, when you add to a pointer, it already knows that it has to deal with sizeof(type), so you don't have to tell it.
memcpy(p + an,...
Remove the multiplication *sizeof(int) from the 1st argument of memcpy. Keep it in the argument of malloc and the 3rd argument of memcpy.
This is because p + an points to an int which is an ints to the right from p -- that is, the int which is an*sizeof(int) bytes to the right from p.
p is a pointer to int. When you add an integer to a pointer to an int, the compiler multiplies the integer by the size of an integer. The net result is to multiply by the size of an integer twice: what you're getting is "p + an*sizeof(int)" is p + (number of elements in a) * (number of bytes in an int) * (number of bytes in an int).
memcpy(p + an*sizeof(int), b, bn*sizeof(int));
should be:
memcpy(p + an, b, bn*sizeof(int));
You should remove sizeof(int) from second memcpy where you use pointer arithmetic (+).
Compiler doing this by itself depending on type of pointer.
you should see the definition of the memcpy, which copy's n "bytes" from the src to the dst area. so,you just need to times sizeof(int) only for the 3rd argument. and for "c", it's a pointer of int type, so, it does know that "+an" means move p forward to the an+1 int position.
Merging can be done by sorting the elements of the elements which are going to be merged code for merging two arrays
#include<stdio.h>
void sort(int arr[],int size){ // sorting function
int i,j,temp;
for(i=0;i<size;i++){
for(j=i;j<size;j++){
if(arr[i]>arr[j]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
int main(){
int a[10],b[10],c[10];
int n,i,k=0,j=0;
printf("Enter the size of the array:");
scanf("%d",&n);
for(i=0;i<n;i++){
printf("Enter the element of array A at index %d:",i); //input array A
scanf("%d",&a[i]);
}
sort(a,n);
for(i=0;i<n;i++){
printf("Enter the element of array B at index %d:",i); //Input array B
scanf("%d",&b[i]);
}
sort(b,n);
for(i=0;i<(n+n);i++){ // merging the two arrays
if(a[k]<b[j]){
c[i] = a[k];
k++;
}
else{
c[i] = b[j];
j++;
}
}
printf("Merged Array :\n");
for(i=0;i<(n+n);i++){
printf("c -> %d ",c[i]);
}
return 0;
}
Reference C program to Merge Two Arrays after Sorting
Related
I was trying to write the code for storing multiplication table in array.
First I wrote the following code.
#include<stdio.h>
void Multiplication(int arr[][10], int num,int size);
int main(){
int arr[3][10];
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
for(int i=0;i<3;i++){
printf("\n\nMultiplication Table of %d\n\n",arr[i][0]);
for(int j=0;j<10;j++){
printf("%d * %d = %d\n",arr[i][0],j,arr[i][j]);
}
}
return 0;
}
void Multiplication(int arr[][10], int num, int size){
for(int j=0;j<size;j++){
for(int i=0;i<10;i++){
arr[j][i] = num * (i+1);
}
}
}
When I was checking whether there is any reduntant part, I removed a little bit of pieces.
#include<stdio.h>
void Multiplication(int *arr, int num,int size);
int main(){
int arr[3][10];
Multiplication(arr[0],2,3);
Multiplication(arr[1],7,3);
Multiplication(arr[2],9,3);
for(int i=0;i<3;i++){
printf("\n\nMultiplication Table of %d\n\n",arr[i][0]);
for(int j=0;j<10;j++){
printf("%d * %d = %d\n",arr[i][0],j,arr[i][j]);
}
}
return 0;
}
void Multiplication(int *arr, int num,int size){
for(int i=0;i<10;i++){
arr[i] = num * (i+1);
}
}
Now, I noticed that &arr[0] and arr[0] are behaving same? I wanna know why is it so?
The following is the question asked:
I noticed that &arr[0] and arr[0] are behaving same? I wanna know why is it so?
We have
int arr[3][10];
arr[0] is a int[10], which is to say an array of 10 int values.
But it's being treated as a pointer. When an array is treated as a pointer, it produces a pointer to the first element of the array. So this means arr[0] is automatically converted to a int* pointing to the first element of the first row of arr when necessary.
&arr[0] means &(arr[0]). It produces a int(*)[10] (a pointer to an array of 10 int values) pointing to the first row of arr.
To recap,
arr[0] is a int[10] which degrades to a int*.
It points to the first element of the first row of arr.
&arr[0] is a int(*)[10].
It points to the first row of arr.
So, arr[0] is NOT equivalent to &arr[0], contrary to your assertion.
And this lack of equivalence is why you had to change from &arr[0] when you when you had int arr[][10] (which means int (*arr)[10] a parameter), to arr[10] when you had int *arr as the parameter.
The both programs are incorrect.
You declared a two dimensional array
int arr[3][10];
So expressions like this arr[0], arr[1], arr[2] have the array type int[10]. That is they produce the first "row", the second "row" and the third "row" of the two-dimensional array.
In the first program you are calling the function Multiplication like
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
and within the function there are two nested loops
void Multiplication(int arr[][10], int num, int size){
for(int j=0;j<size;j++){
for(int i=0;i<10;i++){
arr[j][i] = num * (i+1);
}
}
}
according to the argument specified for the parameter size the function deals with a two dimensional array with three elements (rows) of the array type int[10] using a pointer to the first element of the array. As a result for the argument expressions &arr[1] and &arr[2] there is an access to the memory beyond the original two dimensional array.
You may consider these calls
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
like
Multiplication( arr, 2, 3 );
Multiplication( arr + 1, 7, 3 );
Multiplication( arr + 2, 9, 3 );
The array designator arr is implicitly converted to a pointer to its first element (row) of the type int ( * )[10].
As you are setting only one "row" within the array then the function can be declared and defined the following way
void Multiplication(int arr[][10], int num ){
for(int j=0;j < 10;j++){
( *arr )[j]= num * (j+1);
}
}
and called like
Multiplication( arr, 2 );
Multiplication( arr + 1, 7 );
Multiplication( arr +2, 9 );
Of you want to set elements of a sub-array then the function can be defined the way it is defined initially but called like
Multiplication( arr, 2, 3 );
Multiplication( arr + 1, 7, 2 );
Multiplication( arr +2, 9, 1 );
In the second program the function is declared like
void Multiplication(int *arr, int num,int size){
for(int i=0;i<10;i++){
arr[i] = num * (i+1);
}
}
and you are calling it like
Multiplication(arr[0],2,3);
Multiplication(arr[1],7,3);
Multiplication(arr[2],9,3);
But within the function the parameter size is not used. There is used the magic number 10. And the passed argument 3 does not make a sense.
You should declare the function like
void Multiplication(int *arr, int num,int size){
for(int i=0;i<size;i++){
arr[i] = num * (i+1);
}
}
and call it like
Multiplication(arr[0],2,10);
Multiplication(arr[1],7,10);
Multiplication(arr[2],9,10);
I am trying to print a 2-D array in C by using pointers but I am not getting the expected output.
Program:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr+6; p++)
{
printf("%d ", *p);
}
return 0;
}
Output:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
Could you tell me where I am wrong as the output should only be:
1 2 3 4 5 6
Could you tell me where I am wrong
The elements of arr are not integers, but arrays of 3 integers. So arr+6 is surely a different address than what you expect, since pointer arithmetic works in multiples of the size of the type in the array.
You'll always be better off using nested loops to iterate over a multidimensional array; treating it as one single-dimensional array of int leads to exactly the kinds of confusion you see here. The code is harder to understand and verify, it won't be any slower.
First, when looping through arrays of size n wth an index i, the condition for continuation should be i < n rather than i <= n, because array indexes in C run from 0 through n-1.
However, your code has a more serious error: 1-dimensional arrays can be 'decayed' into pointers to the elements' type; however, 2-dimensional arrays decay into pointers to 1-dimensional arrays. So, in your case, the type of the pointer used in the arr + 6 expression is a pointer to an array of three integers; further, when the 6 is added, that operation is performed in terms of the size of the pointed-to object, which is sizeof(int) * 3 – so, even when changing the <= to <, you will be running far beyond the actual bounds of the array.
To make the pointer arithmetic work in the correct 'units' (i.e. sizeof(int)), cast the arr to an int* before the addition (and also change the <= to <):
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr + 6; p++) {
printf("%d ", *p);
}
return 0;
}
You are trying to access the value in the wrong way, The two-dimensional array is saved as a continuous block in the memory. So, if we increment the value of ptr by 1 we will move to the next block in the allocated memory.
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i++) {
printf("%d ", *(ptr + i));
}
return 0;
Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.
The type of the array elements of this array
int arr[2][3];
is int [3]. So a pointer to the first element of the array has the type int ( * )[3].
This assignment
p = arr;
where p has the type int * is incorrect because the operands of the assignment have incompatible pointer types.
At least you need to cast the right expression to the type int * like
p = ( int * )arr;
The same casting you need to use in the condition in the for loop. That is instead of
p <= arr+6
you have to write
p < ( int * )arr+6
Below there is a demonstration program that shows how to output a two-dimensional array as a two-dimensional array using pointers.
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr + 2; p++ )
{
for ( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
If you want to output the two-dimensional array as a one-dimensional array then you can write
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
In
for ( p = arr; p <= arr+6; p++)
the expression arr, as an rvalue, is a pointer to the first element of the array (which is of type int [3], so each time you increment that pointer, it moves three int positions forward ---a whole row---, and so, arr + 6 points just after the sixth row of the array (if the array should ever had six rows) You can do it (with the proper explicit pointer conversions, as you are mixing pointers to int with pointers to int [3]) with the expression arr + 2 which is the addres of the first array element after the second row (and the number of rows of the array).
You can do it also declaring
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux + 1 will be the position of the second
* 2D array after this one */
and then
int *end = (int *)(aux + 1);
or simply
int *end = (int *)(&arr + 1); /* see below */
(Beware that arr and &arr are both pointers and point to the same place, but they are not the same type (arr is of type int (*)[3] and &arr is of type int(*)[2][3])
So let's rewrite your code as
for (p = (int *)arr; p < end; p++)
or
for (p = (int *)arr; p < (int *)&arr + 1; p++)
would work, which seems more natural to do the calculus in complete array units than in rows or single cells (and you can change freely the dimensions of the array)
Your code would be:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p++)
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(Beware that you have to use < operator and not <= as you don't want to print the value pointed by end, because it lies one place outside of the array)
Finally a note: this will work with true arrays, but not with function parameters declared as arrays, because they decay to pointers and then &arr is not a pointer to data the size of the array, but it is the address of the parameter itself, which points to the array somewhere else.
basically I have 2d array in a struct that I access through a pointer and i can't figure out how to access matrix[i][j] in my if statement
struct Matrix{
unsigned int matrix_size;
int matrix [MAX_MATRIX][MAX_MATRIX];
};
short is_matrix_ok(const struct Matrix*n){
for(int i=0;i<n-matrix_size;i++){
for(int j=0;j<n->matrix_size;j++){
if(n->(matrix+i)[j] ?????)
}
}
Thanks for your answer
Use n->matrix[i][j].
matrix is a member of the structure. matrix+i is not, so you cannot use n->(matrix+i). You must first get the member of the structure, n->matrix, and then you can apply operations to that, like n->matrix[i], which is equivalent to (n->matrix)[i], and then you can apply the next subscript, n->matrix[i][j].
If you want to access it using pointers rather than subscripts, then it would be n->matrix + i to calculate a pointer to subarray i. Then *(n->matrix + i) is that subarray. As an array, it is automatically converted to a pointer to its first element, so *(n->matrix + i) + j calculates a pointer to element j of subarray i. Finally, *(*(n->matrix + i) + j) is element j of subarray i.
Never use that pointer expression in normal code without good reason. Use the easier-to-read n->matrix[i][j].
Try the code below:
#include <stdio.h>
#define ROWS 3
#define COLS 2
struct Matrix{
int matrix[ROWS][COLS];
};
short read_matrix(struct Matrix *M){
int tmp = -100;
for(int i=0;i<ROWS;i++){
for(int j=0;j<COLS;j++){
scanf("%d\n", &tmp);
M->matrix[i][j] = tmp;
//printf("tmp is %d\n", tmp);
}
}
return(0);
}
short is_matrix_ok(const struct Matrix *M){
for(int i=0;i<ROWS;i++){
for(int j=0;j<COLS;j++){
printf("n[%d][%d] = %d\n",i,j,M->matrix[i][j]);
}
}
return(0);
}
int main(){
struct Matrix Mat;
read_matrix(&Mat);
is_matrix_ok(&Mat);
return(0);
}
If you input 1 to 6, output is as follows:
n[0][0] = 1
n[0][1] = 2
n[1][0] = 3
n[1][1] = 4
n[2][0] = 5
n[2][1] = 6
I am trying to generate a Fibonacci sequence by allocating space for 2 elements, so I need my array a[0] and a[1] to be constantly updated until it outputs 89 as the final number.
This is my code:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a);
int main()
{
int *pointer;
//allocates space for 2 elements for pointer
pointer = (int*)malloc(2 * sizeof(int*));
//prints first two fibonacci values
printf("0 1 ");
//calls fib2 func and apsses pointer into it
fib2(pointer);
//frees pointer memory
free(pointer);
printf("\n");
return 0;
}
//generates fibonacci sequence
void fib2(int* a)
{
int i;
//allocates space for 2 elements
a = (int*)malloc(2 * sizeof(int*));
//initial fibonacci array initialized
a[0] = 0;
a[1] = 1;
//generates and calculates fibonacci sequence and prints
for(i = 2; i < 12; i++)
{
a[i] = a[i - 1] + a[i - 2];
printf("%d ", a[i]);
}
}
I tried freeing of a[] by doing free(a); but it outputs to the console like this
**edit this is the valgrind output
There are a number of problems.
Problem 1 Wrong malloc
int *pointer;
//allocates space for 2 elements for pointer
pointer = (int*)malloc(2 * sizeof(int*));
^^^^^^^^^^^^
The sizeof should be sizeof(int) as you want to allocate space for a number (2) int. Besides that you don't need the cast. A better way to write this is:
pointer = malloc(2 * sizeof *pointer);
Problem 2 You never use pointer for any thing
You do pass its value to fib2 so that its value goes into variable a. However, immediately after you do:
a = (int*)malloc(2 * sizeof(int*)); // also sizeof wrong again
so you actually overwrite whatever value that passed. Your call of fib2 could just as well be:
fib2(NULL);
In other words: Don't do malloc both in main and in fib2. Select one place.
Problem 3 The memory in malloc'ed in fib2 are never free'ed
Your current code leaks memory because fib2 doesn't end with code like: free(a);
Problem 4 You allocate too little memory
Obviously you want 12 elements in the integer array but you only allocate ! Change code to be:
a = malloc(12 * sizeof *a);
Putting things together it could look:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a, int n);
#define NUMBERS_TO_CALCULATE 12
int main()
{
int *pointer;
//allocates space for NUMBERS_TO_CALCULATE elements for pointer
pointer = malloc(NUMBERS_TO_CALCULATE * sizeof *pointer);
if (pointer == NULL) exit(1);
//calls fib2 func and apsses pointer into it
fib2(pointer, NUMBERS_TO_CALCULATE);
// ... use pointer for other things ...
//frees pointer memory
free(pointer);
return 0;
}
//generates fibonacci sequence
void fib2(int* a, int n)
{
int i;
if (n < 2) return;
//initial fibonacci array initialized
a[0] = 0;
a[1] = 1;
//prints first two fibonacci values
printf("0 1 ");
//generates and calculates fibonacci sequence and prints
for(i = 2; i < n; i++)
{
a[i] = a[i - 1] + a[i - 2];
printf("%d ", a[i]);
}
printf("\n");
}
Note: If you don't want to use pointer for other things in main, I'll suggest that you move the malloc and free into fib2
Edit based on comments from OP
In comments OP tells about a number of restriction like:
Must use malloc
Only allowed to malloc 2 integers (I assume this also means that local variables are not allowed in fib2)
Function prototype must be void fib2(int* a)
Must print values less or equal 89
With those restrictions the program could look:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a);
int main()
{
int *pointer;
//allocates space for 2 integer elements for pointer
pointer = malloc(2 * sizeof *pointer);
if (pointer == NULL) exit(1);
//initialize fibonacci start values
pointer[0] = 0;
pointer[1] = 1;
//calls fib2 func and apsses pointer into it
fib2(pointer);
//frees pointer memory
free(pointer);
return 0;
}
//generates fibonacci sequence
void fib2(int* a)
{
//prints first two fibonacci values
printf("%d %d ", a[0], a[1]);
//generates and calculates fibonacci sequence and prints
while(a[1] < 89)
{
a[1] = a[1] + a[0]; // Calculate next number and save in a[1]
printf("%d ", a[1]); // Print it
a[0] = a[1] - a[0]; // Calculate the number for a[0]
}
printf("\n");
}
Currently, I'm using the iterative method of swapping element by element which seems to be very inefficient. Is it possible to swap two 2D arrays in constant time?
int a[20][100];
int b[20][100];
I want to swap a & b in O(1).
Also, can the same solution be applied if I want to just override b to a?
Below is the code I used to iteratively override 'a' with 'b'.
Below code is used to override a with b:
for(x = 0;x<row;x++){
for(y=0;y<col;y++){
a[x][y] = b[x][y];
}
}
Below is the code I used to swap a and b:
for(x = 0;x<row;x++){
for(y=0;y<col;y++){
temp = a[x][y];
a[x][y] = b[x][y];
b[x][y] = temp;
}
}
You'll need to store them as pointers. For example:
int a_store[20][100];
int b_store[20][100];
int (*a)[20][100] = &a_store;
int (*b)[20][100] = &b_store;
Now it's easy to swap them. You could also allocate them on the heap, or use std::vector in C++.
Is it possible to swap two 2D arrays in constant time?
To swap 2 2D arrays A[N][M],B[N][M] takes O(N*M) time. This is constant time only if N and M are constant.
The alternative strategy is for code to swap pointers to the arrays.
int main(void) {
size_t N = 3, M = 4;
// ...
int A[N][M];
memset(A, 1, sizeof A);
int B[N][M];
memset(B, 2, sizeof B);
int (*Ap)[N][M] = &A;
int (*Bp)[N][M] = &B;
printf("A:%x %x B:%x %x \n", (*Ap)[0][0], (*Ap)[N-1][M-1], (*Bp)[0][0], (*Bp)[N-1][M-1]);
// Swap pointers in O(1)
int (*t)[N][M] = Ap;
Ap = Bp;
Bp = t;
printf("A:%x %x B:%x %x \n", (*Ap)[0][0], (*Ap)[N-1][M-1], (*Bp)[0][0], (*Bp)[N-1][M-1]);
return 0;
}
Output
A:1010101 1010101 B:2020202 2020202
A:2020202 2020202 B:1010101 1010101