Arrays are passed to C ++ functions, giving different lengths

I want to say first - I am interested in what is going on "behind the scenes" to cause this issue, since I am in a blind fix for the code. Perhaps the C ++ standard or something I don't know dictates what is causing it :-)

Anyway...

I am trying to pass 3 arrays A, B, C

to a function that will concatenate A

and B

store the result in C

.

Function declaration: void merge(int* a, int* b, int* c)

Transferred from main()

by:

int A[] = {1,2,3,4};
int B[] = {6,7,8,9};
int* C;  //this could be wrong, btw!

merge(A, B, C);

      


Problem 1. What's strange in main()

, if I print the result sizeof(A)/sizeof(A[0])

, it gives me the correct result for the "length" of the array - 4

- and the same for B. But when I pass the arrays to the function, I try to calculate the size again, by the same method, but i am getting the result 2

for both arrays. First lines merge()

:

void merge(int* a, int* b, int* c)
{
    int sizeA = sizeof(a)/sizeof(a[0]);
    int sizeB = sizeof(b)/sizeof(b[0]);
    int totalsize = sizeA + sizeB;

    std::cout << "size A = " << sizeA << std::endl;      //prints 2
    std::cout << "size B = " << sizeB << std::endl;      //prints 2
    std::cout << "total  = " << totalsize << std::endl;
...

      


Problem 2. Just for fun, I tried looping through A

and B

passed to merge()

(inside the merge function):

for (int i = 0; i < 4; ++i)
    std::cout << a[i]; //prints "1234" as expected

      

Everything is awesome. But when I increase the index limit to 8 ...

for (int i = 0; i < 8; ++i)
    std::cout << a[i]; //prints "12346789" - A and B concatenated!

      

Increasing the max index a couple more times, because why not:

for (int i = 0; i < 10; ++i)
    std::cout << a[i]; //prints "1234678900"
...
for (int i = 0; i < 11; ++i)
    std::cout << a[i]; //prints "1234678900-444896443"

      

Undefined behavior due to the limits of indexing and accessing other memory I guess.

Printing is B

similarly similar:

  • looping to i = 4

    prints the array -6789

  • to 6

    adds two zeros -678900

  • to 8

    adds another material -678900-126926969126613

Printing C does nothing, of course.


Are these oddities the result

  • the fact that I am using C ++ Shell (with options -std=c++14 -Wpedantic -O2

    )?
  • incorrect transfer of arrays to merge()

    ?
  • incorrect initializations in main()

    ?
  • arrays requiring a terminator like char arrays?
  • all of the above?
+3


source to share


5 answers


  • In the first case, you have an array that is not the same as a pointer . Thus, it sizeof

    is calculated correctly. Whereas it int*

    is a pointer, and the array passed to the function always decays to a pointer (except when it is passed by reference). Also, sizeof(int*)/sizeof(int)

    is the size of the pointer on your computer divided by the size int

    , so if your system is 64-bit (8 bytes) and int

    is typical size 4

    , you get 8/4=2

    .
  • Typical behavior is undefined by indexing out of bounds.


Tip: use std::vector<int>

instead and you will avoid allocating memory for C

and using sizeof

. You can just use a member function std::vector::size()

to get the size of the vector.

+8


source


When you pass an array in void merge(int* a, int* b, int* c)

a and b

here are no longer arrays but pointers. So when you calculate its size using

int sizeA = sizeof(a)/sizeof(a[0]);

here sizeof(a)

will give you the size of the pointer and sizeof(a[0]

will give you the size int

. Hence the result.



And for your second problem, when you increment the indices and connect both arrays, it only happens because a contiguous block of memory is allocated in both arrays, but not necessarily that they will always be assigned contiguous blocks of memory, and other exits due to the behavior of Undefined ...

+3


source


You cannot calculate the size of an array with a simple pointer passed to a function.

sizeof(integers) / sizeof(integers[0])


will simply be replaced with sizeof(pointer on integer) / sizeof(integer)

.

But you can calculate it earlier and then pass the size to the function as shown below.

#include <iostream>
using namespace std;

void doSomeWork(int* integers, const size_t size)
{
    for (size_t i = 0; i < size; ++i)
    {
        std::cout << integers[i] << std::endl;
    }
}

int main()
{
    int integers[] { 0, 1, 2, 3 };
    const size_t size = sizeof(integers) / sizeof(integers[0]);

    doSomeWork(integers, size);

    return 0;
}

      

std::vector<int>

Much better than playing with C arrays, as stated below .

0


source


  • you need to remember that sizeof is a keyword that expands at compile time to the appropriate size. sizeof(T)

    will expand to byte size (T). inside the main function sizeof (a) will give you the number of bytes int[4]

    , inside another function the array decays to a pointer. sizeof(T*)

    not sizeof(T[4])

    ! you are calculating the size of the pointer (after decay), not the size of the real array. now let's say my object weighs 1 MB, does sizeof(OBJ) == sizeof(OBJ*)

    ? of course not.

  • you have Undefined beaviour. in this particular example A

    and B

    sit just after another on the stack. so in this super specific case, when you iterate over the stack, you are actually printing both arrays because they sit one after the other. but again, this is the Undefined beaviour. different compilers may padd the area between the array, or another OS may even kill your program.

0


source


There are many good answers here already. In short, C ++ arrays are of a fixed size. If you want to change it, you must use pointers and dynamic allocation. It can be tiresome. the reason for most people is here to advise you to use vectors.

Vectors are built for dynamic and variable size. You can use them almost like arrays. Here's your code adapted:

void merge(vector<int> &a, vector<int>& b, vector<int> &c) // pass by reference
{
    int sizeA = a.size(); 
    int sizeB = b.size();
    int totalsize = sizeA + sizeB;
    c.resize(totalsize);           // easy !

    // ...
}
int main() {
    vector<int> A{1,2,3,4};
    vector<int> B {6,7,8,9};
    vector<int> C;         

    cout <<A[2]<<endl;   // access elements exacly like arrays
    merge(A, B, C);
}

      

0


source







All Articles