asmmo
asmmo

Reputation: 7100

Why doesn't `sizeof()` work as expected when the argument is a dereferenced pointer pointing to an array?

My problem is when using sizeof(), the result is the pointer size not the array pointed to.

Please, help me.

Here is the code.

The first function creates a 2d matrix and the second displays it while the main function performs a test.

 #include<iostream>
 template<typename T>
    T** Mat(T vals[],size_t m, size_t n){

        T** mat=new T*[m];

        for(size_t i=0;i<m;i++) mat[i]=new T[n];

        for(size_t mi=0;mi<m;mi++){

            for(size_t ni=0;ni<n;ni++){
                mat[mi][ni]=vals[mi*(n-1)+ni];

            }
        }
        return mat;
    }


template<typename T>
void dispMat2d(T** mat){

    for(size_t mi{};mi<sizeof(*mat)/sizeof(mat[0]);mi++){

        std::cout<<"I'm here "<<sizeof(*mat)/*/sizeof(mat[0])*/<<"\n";

            for(size_t ni{};ni<sizeof(*mat[0])/sizeof(mat[0][0]);ni++){
                std::cout<<"o"<<mat[mi][ni]<<"\t";

            }
            std::cout<<std::endl;
    }
}
int main(int c, char* arr[]){

    double v[]={1.0,2,3,4,5,6};

    auto myMat=Mat<double>(v,2,3);


    dispMat2d(myMat);

    return 0;
}

I tried to use std::size() but it doesn't accept the arguments *myMat1 and **myMat1. Thanks in advance

Upvotes: 1

Views: 93

Answers (2)

Ted Lyngmo
Ted Lyngmo

Reputation: 117328

Arrays decay into pointers when passed as arguments to functions, so the size information is lost.

One way to make it work is to take the argument as a reference to an array of a specific size.

Example:

#include<array>
#include<iostream>

// helper
template<typename T, size_t Y, size_t X>
using mat_t = std::array<std::array<T, X>, Y>;

template<typename T, size_t Y, size_t X, size_t N>
auto Mat(const T (&vals)[N]) {
    static_assert(Y*X<=N, "vals[] too small"); // compile time assertion
    mat_t<T, Y, X> mat;

    for(size_t mi=0; mi<Y; ++mi) {
        for(size_t ni=0; ni<X; ++ni) {
            mat[mi][ni] = vals[mi*X+ni];       // bugfix
        }
    }
    return mat;
}

template<typename T, size_t Y, size_t X>
void dispMat2d(const mat_t<T, Y, X>& mat){

    for(size_t mi=0; mi<Y; ++mi){
        for(size_t ni=0; ni<X; ++ni) {
            std::cout << 'o' <<mat[mi][ni] << '\t';
        }
        std::cout << '\n';
    }
}
int main(){
    double v[]={1,2,3,4,5,6};
    auto myMat=Mat<double,2,3>(v);
    dispMat2d(myMat);
}

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 311038

Pointers do not keep the information whether they point to a single object or first element of an array.

Compare

int *p = new int();

and

int *p = new int[10]();

So sizeof( *p ) in the both cases is equivalent to sizeof( int ).

So you have to pass sizes of arrays explicitly.

Pay attention to that the function Mat has a bug.

Instead of

mat[mi][ni]=vals[mi*(n-1)+ni];

there must be

mat[mi][ni]=vals[mi * n + ni];

Upvotes: 3

Related Questions