PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label implicit-conversion. Show all posts
Showing posts with label implicit-conversion. Show all posts

Wednesday, July 6, 2022

[FIXED] why do I see different values of array size in main vs other function

 July 06, 2022     c++, implicit-conversion, pass-by-reference, pass-by-value, pointers     No comments   

Issue

I created an array of ten integers and print its size 1. in main 2. in a function named print

#include <iostream>
using namespace std;
void print(int *a)
{
    cout<<sizeof(a);
}
int main()
{
    int arr[10];
    cout<<sizeof(arr)<<endl;
    print(arr);
}

The output is :

40

8

I was expecting 40 in both cases (as size of 1 integer=4 times 10 ) but the second case shows size of a single pointer and not the whole array. What's happening here?


Solution

As you can see from the function declaration

void print(int *a)
{
    cout<<sizeof(a);
}

the function deals with a pointer. So this statement

cout<<sizeof(a);

outputs the size of the pointer that is equal either 4 or 8 bytes depending on the used system.

Pay attention to that even if you will declare the function like

void print(int a[])
{
    cout<<sizeof(a);
}

you will get the same result because the parameter is implicitly adjusted by the compiler to the type int *.

That is the previous and this function declarations are equivalent.

If you want that the function would deal with the original array instead of a pointer that points to the first element of the passed array as an argument then declare the function at least like.

void print( int ( &a )[10] )
{
    cout<<sizeof(a);
}

That is declare the parameter as a reference.

Or you can make the function a template function like

template <size_t N>
void print( int ( &a )[N] )
{
    cout<<sizeof(a);
}

As the passed array is not being changed in the function then the parameter should have the qualifier const

template <size_t N>
void print( const int ( &a )[N] )
{
    cout<<sizeof(a);
}

Here is a demonstrative program.

#include <iostream>

template <size_t N>
void print( const int ( &a )[N] )
{
    std::cout << sizeof( a ) << '\n';
}

int main() 
{
    int arr[10];

    std::cout << sizeof( arr ) << '\n';

    print( arr );

    return 0;
}

Its output is

40
40

Or you could define the template function with a type template parameter. But again the function parameter has a referenced type.

#include <iostream>

template <typename T>
void print( const T &a )
{
    std::cout << sizeof( a ) << '\n';
}

int main() 
{
    int arr[10];

    std::cout << sizeof( arr ) << '\n';

    print( arr );

    return 0;
}

The program output will be the same as shown above.



Answered By - Vlad from Moscow
Answer Checked By - Senaida (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] Why is my array being passed with an incorrect size?

 July 06, 2022     arrays, c++, implicit-conversion, pass-by-reference, pass-by-value     No comments   

Issue

I am just starting to learn C++ and I was playing around with functions. I am trying to pass an integer array as a parameter, and have the function print every element of the array. My issue however is that I have an array initialized to a seize of 10, but when I pass it to the function it only reads it as a size of 2. Any help would be appreciated! You can find my program below.

#include <iostream>
#include <cmath>

using namespace std;

void Max(int Arr[])
{
    for (int i=0; i<sizeof(Arr)/sizeof(Arr[0]); i++)
    {
        cout<< Arr[i]<<endl;
    }
}


int main()
{
    int Arr[]={1,2,3,4,5,6,7,8,9,10};

    Max(Arr);

    return 0;
} 

Thank you all for the help in advance!


Solution

When an array is passed by value it is implicitly converted to pointer to its first element.

On the other hand a function parameter declared as having an array type is adjusted by the compiler to pointer to the array element type.

So for example these function declarations

void Max(int Arr[]);
void Max(int Arr[1])
void Max(int Arr[10])
void Max(int Arr[100]);

declare the same function and are adjusted by the compiler to the declaration

void Max( int *Arr );

As a result within the function the parameter Arr is a pointer and this expression

sizeof(Arr)/sizeof(Arr[0])

is equivalent to

sizeof( int * ) / sizeof( int )

that yields either 1 or 2 depending on the size of the type int *.

When you passing an array by value to a function you should also pass its size explicitly.

So the function could be defined like

void Max( const int Arr[], size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        cout << Arr[i] << endl;
    }
}

And the function can be called like

Max(Arr, sizeof( Arr ) / sizeof( *Arr ) );

Another approach is to declare the function parameter as having a referenced type. In this case it is better to use a template function that it could be called for an array at least of any size.

template <size_t N>
void Max( const int ( &Arr )[N] )
{
    for ( size_t i = 0; i < N; i++ )
    {
        cout << Arr[i] << endl;
    }
}

Or the function could be defined like

template <typename T, size_t N>
void Max( const T ( &Arr )[N] )
{
    for ( size_t i = 0; i < N; i++ )
    {
        cout << Arr[i] << endl;
    }
}

And the both functions can be called like

Max(Arr);

Pay attention to that you could use the standard class template std::array declared in the header <array>. For example

#include <iostream>
#include <array>

const size_t N = 10;

std::ostream & Max( const std::array<int, N> &a, std::ostream &os = std::cout )
{
    for ( const auto &item : a )
    {
        os << item << ' ';
    }

    return os;
}


int main()
{
    std::array<int, N> a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    Max( a ) << '\n';

    return 0;
} 

The program output is

1 2 3 4 5 6 7 8 9 10 


Answered By - Vlad from Moscow
Answer Checked By - Mildred Charles (PHPFixing Admin)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Sunday, June 26, 2022

[FIXED] Why can I pass 1 as a short, but not the int variable i?

 June 26, 2022     c#, compiler-errors, implicit-conversion, int, type-conversion     No comments   

Issue

Why does the first and second Write work but not the last? Is there a way I can allow all 3 of them and detect if it was 1, (int)1 or i passed in? And really why is one allowed but the last? The second being allowed but not the last really blows my mind.

Demo to show compile error

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}

Solution

The first two are constant expressions, the last one isn't.

The C# specification allows an implicit conversion from int to short for constants, but not for other expressions. This is a reasonable rule, since for constants the compiler can ensure that the value fits into the target type, but it can't for normal expressions.

This rule is in line with the guideline that implicit conversions should be lossless.

6.1.8 Implicit constant expression conversions

An implicit constant expression conversion permits the following conversions:

  • A constant-expression (§7.18) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.
  • A constant-expression of type long can be converted to type ulong, provided the value of the constant-expression is not negative.

(Quoted from C# Language Specification Version 3.0)



Answered By - CodesInChaos
Answer Checked By - Clifford M. (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Thursday, April 28, 2022

[FIXED] How can we solve conversion problem that loses precision ? (Xcode 11.2)

 April 28, 2022     implicit-conversion, precision, swift5, warnings, xcode11     No comments   

Issue

Since Xcode 11.2, I have this warning: Implicit conversion loses integer precision: 'const GULLoggerLevel' (aka 'const enum GULLoggerLevel') to 'int'.

This warning refers me to this line:

dispatch_async(sGULClientQueue, ^{
    asl_log(sGULLoggerClient, NULL, level, "%s", logMsg.UTF8String);
  })

This line is part of this block:

     NSString *logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr];
  logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg];
  dispatch_async(sGULClientQueue, ^{
    asl_log(sGULLoggerClient, NULL, level, "%s", logMsg.UTF8String);
  });

Can anybody help me with this warning ?


Solution

you just have to replace"level" by "(int)level"



Answered By - Sukhoi
Answer Checked By - Mary Flores (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to detect implicit conversion losses integer precision on std::vector::emplace_back

 April 28, 2022     c++, emplace, implicit-conversion, vector, warnings     No comments   

Issue

I compiled the following code with -Wconversion compiler option to detect implicit conversion loses integer precision:

#include <vector>
#include <cstdint>

int main() {
    std::vector<std::uint16_t> v;
    std::uint32_t a = 0;
    v.emplace_back(a);  // no warning
    v.push_back(a);     // warning: implicit conversion loses integer precision
}

Compiling Demo https://wandbox.org/permlink/K5E4sUlfGBw6C5w8

The vector's value_type is std::uint16_t. If I push_back std::uint32_t value to the vector, then I got the following warning as I expected.

prog.cc:8:17: warning: implicit conversion loses integer precision: 'std::uint32_t' (aka 'unsigned int') to 'std::__1::vector<unsigned short, std::__1::allocator<unsigned short> >::value_type' (aka 'unsigned short') [-Wimplicit-int-conversion]
v.push_back(a);     // warning: implicit conversion loses integer precision
  ~~~~~~~~~ ^
1 warning generated.

However, if I emplace_back the same value to the vector, no warning is detected.

I've tested it clang++ 10.0.0, clang++ 9.0.0, and g++ 9.3.0 and got the same result.

Is there any good way to detect implicit conversion losses integer precision on std::vector::emplace_back ?


Solution

There is no implicit conversion when you call v.emplace_back(a). There would be an implicit conversion if you called v.emplace_back<const std::uint16_t &>(a).

A key difference between push_back and emplace_back is that the latter is a template while the former is not. If you do not specify a template argument for emplace_back, the compiler deduces it from the function argument, which means no conversion will be necessary at the point of call. Within emplace_back the conversion happens in a system header, which suppresses the warning.

So in your example,

v.emplace_back(a);

is deduced as

v.emplace_back<const std::uint32_t &>(a);

where the function argument is expected to be a std::uint32_t. Perfect match, no conversion necessary outside the system header. If you were to enable warnings within system headers, you could end up with a bunch of spurious warnings

To get an implicit conversion in your code, you need to force emplace_back to expect a std::uint16_t, which can be done via

v.emplace_back<const std::uint16_t &>(a);

This would implicitly convert a to std::uint16_t before calling emplace_back, triggering the compiler warning in the same way that push_back does.



Answered By - JaMiT
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing