6

I'm currently trying to make it where an array holds rgba data (0x00000000 → 0xFFFFFFFF) and when I put a value over 2,147,483,647 it overflows, I'm assuming because of some possible conversion (maybe unsigned → signed).

Here's my code:

int main(int argc, char* args[]) {
    uint32_t *background = new uint32_t[1920*1080];

    background[100] = 0xFF0000FF; //red, 4278190335
    printf("%d, ", background[100]);

    return 0;
}

Here's the output:

-16776961

I'm still somewhat new to C++ so if I'm being oblivious to something please point it out.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Pixel
  • 85
  • 1
  • 3
  • 6
    Try `%u` instead of `%d`. – Blaze Oct 19 '18 at 06:50
  • 7
    If you're programming in C++ then use `std::cout` for output, and you won't have any problems. The `printf` function needs very specific format specifiers (if you don't have matching format specifier and argument you will have [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior)). Using `std::cout` is type-safe. – Some programmer dude Oct 19 '18 at 06:52
  • 3
    Your program leaks memory (although collected by the OS after the program exits). Better use a smart pointer (e.g. [`std::unique_ptr[]`](https://en.cppreference.com/w/cpp/memory/unique_ptr)) – hellow Oct 19 '18 at 06:56
  • 6
    @hellow Or better yet [`std::vector`](http://en.cppreference.com/w/cpp/container/vector). – Some programmer dude Oct 19 '18 at 06:56
  • Possible duplicate of [Unsigned int takes negative values](https://stackoverflow.com/questions/11224210/unsigned-int-takes-negative-values) – user202729 Oct 19 '18 at 11:00
  • 1
    Possible duplicate of [C Unsigned int providing a negative value?](https://stackoverflow.com/questions/1831753/c-unsigned-int-providing-a-negative-value) – TobiMcNamobi Oct 19 '18 at 12:40
  • Does the API you're using use that 32 bit integer, per channel, or per pixel? – Andrew Oct 19 '18 at 12:53
  • @Andrew per pixel – Pixel Oct 19 '18 at 18:38
  • Then I think your array size should be [width * height * num_channels] – Andrew Oct 19 '18 at 18:52

3 Answers3

9

First, a quick note:

uint32_t *background = new uint32_t[1920*1080];

Here, background isn't an array (in the stack), rather, you are allocating memory (containing an array) and saving a pointer to the first element. You will need to delete the memory. In C++, it is much easier to use a std::vector:

// at the top: #include <vector>
std::vector<uint32_t> background(1920*1080);

Which will get deallocated automatically (so you don't have to worry about it). Another option is using an array, but in this case, you better not, because it is quite a lot of memory you have there (8 MiB), which may break your stack.

Now, if you want to use printf to print an unsigned int, you need to use %u (or %x if you want it in hexadecimal):

printf("%u, ", background[100]); // or...
printf("%x, ", background[100]);

However, in your code you are using uint32_t, which is a fixed-with type. For this, you would need to use:

// at the top: #include <cinttypes>
printf("%" PRIu32 ", ", background[100]); // or...
printf("%" PRIx32 ", ", background[100]); 

Further, a final note as @Someprogrammerdude commented, you can use std::cout in C++ instead:

// at the top: #include <iostream>
std::cout << background[100] << std::endl; // or...
std::cout << std::hex << background[100] << std::dec << std::endl;
Acorn
  • 24,970
  • 5
  • 40
  • 69
  • 1
    `new uint32_t[1920*1080]` definitely allocates an array. You still save a pointer to the first element of the array, that part is true, and indeed you need to `delete []` it. This rule becomes important when the array members have constructors - if it was merely a memory allocation, constructors would not have been called, but they are. – MSalters Oct 19 '18 at 07:06
  • 1
    @MSalters The comment was intended to explain that it isn't an array *variable* vs. a pointer, which requires more work. Indeed, technically, `new` here still allocates an array of objects according to the standard, so I have edited it to be more precise, but IMO that is irrelevant for beginners: the important part is that they know which type of variable they are defining (which is seems OP doesn't, since it is not deallocated). – Acorn Oct 19 '18 at 07:19
  • I figured I may have messed up somewhere along the print statement so thanks for catching that, also something I failed to mention in the original post is that I'm messing around with a visual API that requires a 32-bit array to make a sort of texture for the screen so this basically eliminates me using a vector unless there's some way to cast a vector as an array. – Pixel Oct 19 '18 at 11:05
  • 1
    @Pixel `std::vector` has a `.data` member function which will give you a `uint32_t*` which points to the beginning of the vector's data – Dexter CD Oct 19 '18 at 11:23
7

Change this:

printf("%d, ", background[100]);

to this:

// #include <cinttypes>
printf("%" PRIu32 "", background[100]);

since you want to print a uint32_t, not an int.

PS: Since this is C++, I strongly suggest using std::cout, which will take care automatically for these issues.

PPS: Since you used new [], don't forget to delete [] afterwards.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
0

It is important to understand the difference between numeric data and its representation when you output it. There is no overflow here. The data is just being printed as a signed value. You are assigning it correctly with the hex literal. You should also print it out as hex rather than as decimal.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • 1
    Actually the hex literal should have an `U` suffix, to make it clear that it's an _unsigned_ literal. As for printing hex rather than decimal, why do you think hex should be printed? If the decimal representation of the value is needed. `PRIu32` (unquoted, no %) is correct. – MSalters Oct 19 '18 at 07:57
  • @MSalters My recommendation to print hex is because it makes sense for human consumption in this context. With `0xFF0000FF`, the value of each color channel and alpha channel are clear. With `4278190335` the meaning is not at all obvious. – Code-Apprentice Oct 19 '18 at 08:01