Concatenating two integer arrays in C - c

I am trying to concatenate two integer arrays. This method works well for strings (char*), but for integer arrays the content of the second array is changed.
int main() {
int* a = malloc(8); // 2 integers
int* b = malloc(12); // 3 integers
a[0] = 1;
a[1] = 2;
b[0] = 3;
b[1] = 4;
b[2] = 5;
int* c = malloc(20); // 5 integers
memcpy(c, a, 8);
memcpy(c+8, b, 12);
printf("%d\n", c[0]); // Excpected 1. Prints 1.
printf("%d\n", c[1]); // Excpected 2. Prints 2.
printf("%d\n", c[2]); // Excpected 3. Prints something random.
printf("%d\n", c[3]); // Excpected 4. Prints something random.
printf("%d\n", c[4]); // Excpected 5. Prints something random.
return 0;
}

Forget all about hard-coding variable sizes. That's the root of your problems and makes the code brittle.
The specific problem here though, is that c+8 does pointer arithmetic on an int*. So it means "go 8 int forward from c". Not 8 bytes - it is equivalent to &c[8], which is obviously wrong.
You should rewrite your code according to this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int* a = malloc(2*sizeof(int));
int* b = malloc(3*sizeof(int));
a[0] = 1;
a[1] = 2;
b[0] = 3;
b[1] = 4;
b[2] = 5;
int* c = malloc(5*sizeof(int));
memcpy(c, a, 2*sizeof(int));
memcpy(c+2, b, 3*sizeof(int));
printf("%d\n", c[0]);
printf("%d\n", c[1]);
printf("%d\n", c[2]);
printf("%d\n", c[3]);
printf("%d\n", c[4]);
return 0;
}
An optional syntax for malloc is to do int* a = malloc(2 * sizeof(*a)), which is fine too, it's a matter of coding style preference.

Due to the pointer arithmetic in this call of memcpy
memcpy(c+8, b, 12);
there is specified an incorrect destination address.
You allocated an array for 5 elements (provided that sizeof( int ) is equal to 4)
int* c = malloc(20)
So due to the pointer arithmetic c + 0 is the address of the first element, c + 1 is the address of the second element, c + 2 is the address of the third element and so on.
As you are trying to fill the array starting from its third element then you have to write
memcpy(c+2, b, 12);
^^^^
It is the same as if to write
memcpy( &c[2], b, 12);
Also do not use magic numbers like 12 or 20. Take into account that sizeof( int ) is implementation defined. So it would be much better to write for example
int* c = malloc( 5 * sizeof( int ) );
or
memcpy( c + 2, b, 3 * sizeof( int ) ;
Your program could look the following way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
size_t n1 = 2;
size_t n2 = 3;
int *a = malloc( n1 * sizeof( int ) );
int *b = malloc( n2 * sizeof( int ) );
int init_value = 1;
for ( size_t i = 0; i < n1; i++ )
{
a[i] = init_value++;
}
for ( size_t i = 0; i < n2; i++ )
{
b[i] = init_value++;
}
size_t n3 = n1 + n2;
int *c = malloc( n3 * sizeof( int ) );
memcpy( c, a, n1 * sizeof( int ) );
memcpy( c + n1, b, n2 * sizeof( int ) );
for ( size_t i = 0; i < n3; i++ )
{
printf("c[%zu]: %d\n", i, c[i] );
}
putchar( '\n' );
free( c );
free( b );
free( a );
return 0;
}
The program output is
c[0]: 1
c[1]: 2
c[2]: 3
c[3]: 4
c[4]: 5

You have to replace memcpy(c+8, b, 12); to memcpy(c+2, b, 12); because first argument of the memcpy function is mean The pointer to the destination array where the content is to be copied, type-casted to a pointer of type void.*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int* a = malloc(8); // 2 integers
int* b = malloc(12); // 3 integers
a[0] = 1;
a[1] = 2;
b[0] = 3;
b[1] = 4;
b[2] = 5;
int* c = malloc(20); // 5 integers
memcpy(c, a, 8);
memcpy(c+2, b, 12);//
printf("%d\n", c[0]); // Excpected 1. Prints 1.
printf("%d\n", c[1]); // Excpected 2. Prints 2.
printf("%d\n", c[2]); // Excpected 3. Prints something random.
printf("%d\n", c[3]); // Excpected 4. Prints something random.
printf("%d\n", c[4]); // Excpected 5. Prints something random.
return 0;
}

Related

Using `malloc` for dynamical array concatenation in C leads to strange exit code

Problem statement
I want to write a function
int *concat_tab(int n1, int *t1, int n2, int *t2)
in pure C which does the following: Given two arrays of integers (as pointers), the function should return a new array which is the concatenation of the two input arrays.
The input names mean the following:
n1: length of the first array;
*t1: pointer to the first element of the first array;
n2: length of the second array;
*t2: pointer to the first element of the second array.
My code
#include<stdio.h>
#include<stdlib.h>
int *concat_tab(int n1, int *t1, int n2, int *t2){
/*
* Takes two 1D arrays and their lengths as input and outputs their concatenation.
* Input:
* - n1: Length of first array
* - t1: First array
* - n2: Length of second array
* - t2: Second array
* Output:
* - Array of length n1+n2 containing the elements of t1 followed by the elements of t2
*/
int *output = (int*) malloc(n1+n2);
for(int k = 0; k < n1+n2; k++){
if(k < n1) {
*(output + k) = *(t1 + k);
}
else{
*(output + k) = *(t2+k-n1);
}
}
return output;
}
int main(){
int array1[4] = {1, 2, 3, 4};
int array2[5] = {10, 11, 12, 13, 14};
int *output = concat_tab(4, array1, 5, array2);
for(int k = 0; k < 9; k++){
printf("Output[%d] = %d\n", k, *(output+k));
}
return 0;
}
My problem
As output I get, as desired,
Output[0] = 1
Output[1] = 2
Output[2] = 3
Output[3] = 4
Output[4] = 10
Output[5] = 11
Output[6] = 12
Output[7] = 13
Output[8] = 14
However, my program exits with the exit code -1073740940 instead of 0. Why does that happen?
The undesired exit code happens because the input passed to malloc in C denotes the number of bytes (which is not, in general, equal to the length of the array) that will be allocated in memory (for instance, each int in the array requires 4 bytes and not just 1).
Therefore, what happens is that C allocates too little memory for the output array. This can be fixed by replacing the line
int *output = (int*) malloc(n1+n2);
with
int *output = (int*) malloc(sizeof(int)*(n1+n2));
and now the program will exit as desired.
This memory allocation
int *output = (int*) malloc(n1+n2);
is equivalent to
int *output = (int*) malloc( ( n1+n2 ) * sizeof( char ));
But you need to allocate memory for objects of the type int. That is you need to write
int *output = (int*) malloc( ( n1+n2 ) * sizeof( int ) );
Also the function declaration is bad. Firstly the passed arrays are not being changed within the function. So the corresponding parameters should have the qualifier const.
Secondly the parameters that specify the number of elements in the arrays should have the type size_t.
Thirdly the order of parameters should be changed.
So the function declaration should look like
int * concat_tab( const int *t1, size_t n1, const int *t2, size_t n2 );
Pay attention to that you should to check whether the memory was allocated successfully. And you need to free it when the allocated array is not required any more.
Here is shown how your program can look.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int * concat_tab( const int *t1, size_t n1, const int *t2, size_t n2 )
{
int *output = NULL;
if (n1 || n2)
{
output = malloc( ( n1 + n2 ) * sizeof( int ) );
if (output != NULL)
{
memcpy( output, t1, n1 * sizeof( int ) );
memcpy( output + n1, t2, n2 * sizeof( int ) );
}
}
return output;
}
int main( void )
{
int array1[] = { 1, 2, 3, 4 };
size_t n1 = sizeof( array1 ) / sizeof( *array1 );
int array2[] = { 10, 11, 12, 13, 14 };
size_t n2 = sizeof( array2 ) / sizeof( *array2 );
int *output = concat_tab( array1, n1, array2, n2 );
if ( output != NULL )
{
for (size_t i = 0; i < n1 + n2; i++)
{
printf( "Output[%zu] = %d\n", i, *( output + i ) );
}
}
free( output );
}

C pointer argument assigned to a parameter with a different value

I was trying to write a seemingly trivial function in C to get the maximum value in an array of integers. I'm trying to do so using pointers to get a better understanding. (I know how to do this passing the size of the array, the question is not how to do this another way)
#include <stdio.h>
int gimme_largest(int *, int *);
int main(void)
{
int arr[] = {1, 22, 3, 44, 5};
int largest;
printf("In main, arr:\t\t\t %p \n", arr);
printf("In main, arr + sizeof(arr):\t %p\n", arr + 5);
putchar('\n');
largest = gimme_largest(arr, arr + sizeof(arr));
// printf("\n\nThe largest is %d", largest);
return 0;
}
int gimme_largest(int *a, int *lastPlusOne)
{
int largest = *a; // let's assume the first element is the largest one
printf("In gimme_largest, a:\t\t %p\n", a);
printf("In gimme_largest, a + 5:\t %p\n", a + 5);
printf("In gimme_largest, lastPlusOne:\t %p\n", lastPlusOne);
while (a < lastPlusOne) {
if (*a > largest)
largest = *a;
a++;
}
return largest;
}
The problem is that lastPlusOne does not equal a + 5 in the invoked function, but a higher address; can't see why that's happening.
This call
largest = gimme_largest(arr, arr + sizeof(arr));
is invalid. sizeof( arr ) in the case of your program is equal to 5 * sizeof( int ) while for the correct pointer arithmetic you need to use only the number of elements in the array.
That is there shall be
largest = gimme_largest(arr, arr + sizeof(arr) / sizeof( *arr ) );
Thus the expression sizeof(arr) / sizeof( *arr ) is equal to the value 5 that you are using in this call of printf
printf("In main, arr + sizeof(arr):\t %p\n", arr + 5);
Pay attention to that the user can call the function with an empty range when a is equal to lastPlusOne. In this case the function will have undefined behavior because for an empty range there is no largest elemenet.
The function should return a pointer to the largest element.
Also as in C there is no function overloading then the function should be called for constant and non-constant arrays.
Here is a demonstrative program that shows how the functipon can be defined.
#include <stdio.h>
int * gimme_largest( const int *first, const int *last )
{
const int *largest = first;
if ( first != last )
{
while ( ++first != last )
{
if ( *largest < *first ) largest = first;
}
}
return ( int * )largest;
}
int main(void)
{
int arr[] = {1, 22, 3, 44, 5};
const size_t N = sizeof( arr ) / sizeof( *arr );
int *largest = gimme_largest( arr, arr + N );
printf( "The largest number is %d\n", *largest );
return 0;
}
The program output is
The largest number is 44
To get the end address of the array, you can do this by arr + sizeof(arr) / sizeof(arr[0]):
#include <stdio.h>
int gimme_largest(int *, int *);
int main(void)
{
int arr[] = {1, 22, 3, 44, 5};
int largest;
printf("In main, arr:\t\t\t %p \n", arr);
printf("In main, arr + sizeof(arr):\t %p\n", arr + 5);
putchar('\n');
largest = gimme_largest(arr, arr + sizeof(arr) / sizeof(arr[0]));
printf("\n\nThe largest is %d", largest);
return 0;
}
int gimme_largest(int *a, int *lastPlusOne)
{
int largest = *a; // let's assume the first element is the largest one
printf("In gimme_largest, a:\t\t %p\n", a);
printf("In gimme_largest, a + 5:\t %p\n", a + 5);
printf("In gimme_largest, lastPlusOne:\t %p\n", lastPlusOne);
while (a < lastPlusOne) {
if (*a > largest)
largest = *a;
a++;
}
return largest;
}
output:
In main, arr: 000000000062FE00
In main, arr + sizeof(arr): 000000000062FE14
In gimme_largest, a: 000000000062FE00
In gimme_largest, a + 5: 000000000062FE14
In gimme_largest, lastPlusOne: 000000000062FE14
The largest is 44

Concat Arrays in C

I'm exercising a bit in programming C.
One task is to concat two dynamic arrays. The elements of the second array should be added to the end of the first array. The following is given:
void concatArrays(int* numbers1, int length1, int* numbers2, int length2)
{
//code
}
And that is my code to solve the task:
#include <stdio.h>
#include <stdlib.h>
void concatArrays(int* numbers1, int length1, int* numbers2, int length2)
{
numbers1 = (int*)realloc(numbers1, sizeof(int*) * (length1 + length2));
for (int count = 0; count < length2; count++)
{
numbers1[length1 + count] = numbers2[count];
}
}
int main()
{
int* num = (int*)malloc(sizeof(int*) * 6);
num[0] = 1;
num[1] = 2;
num[2] = 3;
num[3] = 4;
num[4] = 5;
num[5] = 6;
int* numbers = (int*)malloc(sizeof(int*) * 4);
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
concatArrays(num, 6, numbers, 4);
for (int count = 0; count < 10; count++)
{
printf("%d - ", num[count]);
}
return 0;
}
Unfortunately, it doesn't work. I do know that the code does work if I used a pointer to a pointer:
void concatArrays(int** numbers1, int length1, int** numbers2, int length2) { //code }
Nonetheless, that seems to be not allowed regarding the task requirements.
Do you have any idea how I could change my code meeting the requirements to solve the task?
Thank you in advance.
Edit:
I forgot:
The output:
1 - 2 - 3 - 4 - 5 - 6 - 2054454589 - 32767 - -1280384664 - 32767 -
void concatArrays(int* numbers1, int length1, int* numbers2, int length2)
Given prototype is pass by value for your case.
Hence when you reallocate the memory.
numbers1 = (int*)realloc(numbers1, sizeof(int*) * (length1 + length2));
You are allocating for local copy not for original copy.
Note that it is not guaranteed that new pointer returned by realloc
will be same as old.
code does work if I used a pointer to a pointer.
That is because you will be passing by reference any modification inside function will update the original variables.
Thus allocate the more memory in the main itself.
int* num = (int*)malloc(sizeof(int) * 10);
There is a failure in the memory allocation, respective on type.
Note that the values of array are ints, so by the allocation they occupy not a pointer size memory more likely int size spaces:
so the allocation should look like this for int arrays:
void concatArrays(int** numbers1, int* length1, const int* numbers2, const int length2)
{
*length1 = *length1 + length2;
*numbers1 = (int*)realloc(*numbers1, sizeof(int) * (*length1));
...
}
Note that the size of an int pointer (int*) may be different than the size of a pure int type.

Walk-through of a simple c program

I have this question to walk through and show the output when this program is run. The one thing I don't understand is how f is found to be four or even found at all.I know the correct answer is
7 falcon 3
9 RK 4
_
I just dont know how they found the f value to be 4 ,once i have that I can do the rest fine
#include <stdio.h>
#include <string.h>
void falcon(int f);
char a[20];
int main() {
int i, j;
a[3] = 'G';
a[1] = 'K';
i = 3 + 2 * 3;
j = 4;
a[2] = 'Y';
falcon(j);
printf("%d %s %d\n", i, a, j);
}
void falcon(int f) {
int j;
j = 11 % f;
printf("%d falcon %d\n", f+3, j);
a[2] = '\0';
a[0] = 'R';
}
Let's walk through the program together (with some of the irrelevant bits cut out).
#include <stdio.h>
#include <string.h>
void falcon(int f);
char a[20];
int main() {
int i, j;
j = 4;
falcon(j); // in other words, falcon(4). Now, let's go down to the
// falcon function where the first argument is 4.
printf("%d %s %d\n", i, a, j);
}
void falcon(int f) { // Except here we see that in this function,
// the first argument is referred to by 'f',
// which, as we saw, is 4.
int j;
j = 11 % f; // here, j is equal to the remainder of 11 divided by
// f, which is 4.
printf("%d falcon %d\n", f+3, j);
}
Now you see why code should not have is and js for variable names except in probably, loops.
Anyways,
char a[20]; on the top says that a is a globally declared character array.
int main()
{
int i, j; // declares two local stack variables, i and j
a[3] = 'G'; // sets 4th location in 'a'(remember, arrays start at 0) to 'G'{useless}
a[1] = 'K'; // sets 2nd location in 'a' array to 'K'
i = 3 + 2 * 3; // i is now 9 {remember, multiplication before addition}
j = 4; // j is now 4
a[2] = 'Y'; // a[2] is now 'Y'
falcon(j); // call to falcon, with argument 4, explained next
printf("%d %s %d\n", i, a, j); // prints "9 RK 4"
//return 0; -- this should be added as part of 'good' practices
}
void falcon(int f)
{
// from main(), the value of 'f' is 4
int j; // declares a local variable called 'j'
j = 11 % f; // j = 11 % 4 = 3
printf("%d falcon %d\n", f+3, j); // prints 7 falcon 3
a[2] = '\0'; // a[2] contains null terminating character, overwrites 'Y'.
a[0] = 'R'; // sets a[0] to 'R'. At this moment, printf("%s",a); must yield "RK"
}

C - malloc array in function and then access array from outside

Here is how I malloc an int var and then access this var outside of the function
int f1(int ** b) {
*b = malloc(sizeof(int));
**b = 5;
}
int main() {
int * a;
f1(&a);
printf("%d\n", *a);
// keep it clean :
free(a);
return 0;
}
Using same logic above, how do I malloc a 1 dim array inside a function and then access it outside of the func?
Please help, I am bit confused with pointers to array.
In exactly the same way but with some different arithmetic. You can think of what you are doing now as allocating an array with one element. Just multiply sizeof(int) by the number of elements you want your array to have:
int f1(int ** b, int arrsize) {
*b = malloc(sizeof(int) * arrsize);
// then to assign items:
(*b)[0] = 0;
(*b)[1] = 1;
// etc, or you can do it in a loop
}
int main() {
int * a, i;
int size = 20;
f1(&a, size); // array of 20 ints
for (i = 0; i < size; ++i)
printf("%d\n", a[i]); // a[i] is the same as *(a + i)
// so a[0] is the same as *a
// keep it clean :
free(a);
return 0;
}
(untested, but I believe it'll work)
int f1(int ** b) {
*b = malloc(sizeof(int)*4);
(*b)[0] = 5;
(*b)[1] = 6;
(*b)[2] = 7;
(*b)[3] = 8;
}
int main() {
int * a;
f1(&a);
printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]); // should be "5 6 7 8"
// keep it clean :
free(a);
return 0;
}
You are almost there *b = malloc(sizeof(int)); allocates space for a single int ( a bit pointless since the pointer is at least as big as this)
The more normal usage is *b = malloc(number_of_ints*sizeof(int));
Remember that the [] syntax just does the array maths for you (a+10) and a[10] point to exactly the same thing memory location, so you can allocate it using malloc, pass the poitner and refer to it as an array.
The only things about arrays and pointers that is complicated (apart from remembering when to use * and &) is that malloc() works in bytes, so you need to tell it the sizeof an int. But the int * it returns knows about ints so to get to the next value you only need to do a++ or a+1 or a[1] even though it is really 4 or 8 bytes different in value.
Instead of malloc()ing a single int, malloc the array.
int f1(int * b) {
b = malloc(ARRAY_LENGTH * sizeof(int));
*b = 5;
b[1] = 6;
*(b + 2) = 7;
}
You'll want to use a calloc call instead of malloc (See this: http://www.manpagez.com/man/3/calloc/)

Resources