1

Here is my code:

#include <iostream>
#include <stdint.h>
using namespace std;

//converts high endian to little endian
uint32_t format(const char* &bytes)
{
    return (uint32_t)((bytes[0] << 24) |
        (bytes[1] << 16) |
        (bytes[2] << 8) |
        (bytes[3]));
}

uint32_t normal(const char* &bytes)
{
    return (uint32_t)((bytes[3] << 24) |
        (bytes[2] << 16) |
        (bytes[1] << 8) |
        (bytes[0]));
}

int main()
{
    char bytes[4];
    bytes[0]= 0x01;
    bytes[1]= 0x23;
    bytes[2]= 0x45;
    bytes[3]= 0x67;
    printf("0x%08x\n", normal(bytes);
    printf("0x%08x\n", format(bytes);
}

I have a char array of size 4 called bytes. Each element in bytes stores a byte, which, collectively, I treat as a 32 bit unsigned int. My goal is to pass bytes into format() and this will return the little endian form of the number in bytes (which is currently stored in high endian). My issue is, I want to pass the array as a reference so that it doesn't create extra memory for the function parameters. Not only that, I also want to make it so that the function can't change the elements in bytes. For this, I tried: uint32_t format(const char* &bytes); and passed bytes like this: format(bytes) but this is giving me an error.

When I wrote it like this instead: uint32_t format(char* const &bytes), the error stopped but this is not what I wanted since this is a reference to a constant pointer to a character meaning I can't change the pointer itself but I can change the value it points to. What I want is the opposite: I want a reference to a pointer to a constant character so that I may be able to change the pointer but I can't change the value it is pointing to.

Finally, I want to add that I could have done this easily without a reference, but, as I mentioned earlier, this will cause memory to be allocated for the function parameters each time it is called which is not what I want.

Ak01
  • 362
  • 3
  • 19
  • 1
    Have you looked at `std::array`? – Tas Aug 26 '20 at 05:40
  • Secdonly some comments: 1) References might be implemented as pointers and thus also need some memory, there is no garantuee, that a reference would use less memory than a pointer. 2) You worry about 4 or 8 byte for typical pointer! Or 4 bytes if you pass the thing by value, that's nothing. 3.) The stackframe takes some memory anyway, you shouldn't worry about 4 more flimsy bytes. 4.) On higher optimization leves the whole function is most likely inlined, removing any reason to worry about it. – Lukas-T Aug 26 '20 at 06:36
  • You cannot pass an array by value - it always decays to a pointer. Using just `const char*` as argument type would be sufficient. It's also possible to pass an array by reference: `const char (&bytes)[4]`. (The strange looking parens are necessary - without them it would become an array of references which is not intended.) [Demo on coliru](http://coliru.stacked-crooked.com/a/27042fbaf5e6178f) – Scheff's Cat Aug 26 '20 at 06:40
  • @Scheff - if an array always decays to a pointer, why can't i pass the reference to that pointer instead? why is that illegal? If i had done: const char* p = bytes; and then called format(p) --> this works but sending bytes doesn't? Why? – Ak01 Aug 26 '20 at 09:21
  • If you require a `const char*&` (literally a reference to a pointer pointing to a `const char`) then you may not pass a `char[4]`. (Though it decays to a pointer but this one is a temporary value - it may not be referenced.) I modified my [Demo on coliru](http://coliru.stacked-crooked.com/a/24cb31be98125ad2) (for `format()`) to show under which conditions it would work. ...as you already found by yourself. – Scheff's Cat Aug 26 '20 at 09:36
  • The [Counter Demo on coliru](http://coliru.stacked-crooked.com/a/46f264d51d51bad4) with error _cannot bind non-const lvalue reference of type 'const char*&' to an rvalue of type 'const char*'_ The compiler denotes as `rvalue of type 'const char*'` what I called "temporary value" - the pointer decayed from the array `bytes[4]`. – Scheff's Cat Aug 26 '20 at 09:43
  • @Scheff please tell me if I am wrong. From my understanding, you are saying that when we send an array to a function, it sends its address. And since the address is not contained in variable (it is a temporary value), we cannot create a reference to it because a reference can only be to a variable. Correct? – Ak01 Aug 26 '20 at 10:21
  • 1
    Roughly speaking: correct. Strictly speaking, the standard doesn't say that a reference is an address. (You may imagine it as kind of address if it helps.) What's true: An array has a certain type (based on its element type and size). Arrays may not be passed to a function by value -> just not supported by language. An array may be implicitly converted to a pointer to its first element (which has a related but different type). The implicit conversion yields a temporary (an RValue) which may not be referenced. (Who said that C++ is a simple language?) ;-) – Scheff's Cat Aug 26 '20 at 10:50

0 Answers0