0

Hi I have a sample program

#include <iostream>

int main() {
    int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

Here I am getting the output of 17179869164.

My question is that the array size value should not accept negative values! and if I try giving a[-5], it throws an error. but now how am I getting the output of 17179869164.

I have my assumption too, the -5 is converted to an unsigned int value of 4294967291 and the total size is given as 17179869164 = 4294967291 * 4(size of int).

So I wanted to know why the compiler is typecasting signed int to unsigned int and not throwing a compile-time error. I needed a clear understanding of how the compiler is executing that piece of code?

Karthikgr
  • 81
  • 13
  • 5
    Your program is invalid C++ (no matter the value of `a`), because C++ doesn't have [variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array). – Some programmer dude Jan 10 '20 at 07:01
  • @Someprogrammerdude thanks for the info i didnt know this. But if i execute it has a complete C program with changes i get size as -20% in gcc , But shouldn't give it as a compiler error for providing negative value? – Karthikgr Jan 10 '20 at 07:09
  • Which compiler are you using? Visual Studio 2019 does throw compile errors for both the variable length array (as pointed out by @Someprogrammerdude), and, once you fix that, for `a` being negative. – Frodyne Jan 10 '20 at 07:09
  • @Frodyne i am using Visual studio code with g++ and gcc compiler. – Karthikgr Jan 10 '20 at 07:12

3 Answers3

2

It is something called undefined behavior. To catch that kind of bug you could use the help of a static analyser.

Someone else asked something similar here: Declaring an array of negative length

Michizev
  • 21
  • 1
  • 1
  • 4
1

For C++, Variable Length Arrays are not provide by the standard, but may be provided by compiler extension. For C, the short answer is the standard converts the value to a positive integer value unless it is a constant expression -- in your case resulting in the use of the unsigned value (use of the two's compliment value as a positive value). Specifically:

C11 Standard - 6.7.6.2 Array declarators(p5)

If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

I noticed some interesting behavior in GodBolt.

I took you code and added a second copy where a is declared constant:

#include <iostream>

int foo() {
    int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

int bar() {
    const int a = -5;
    int arr[a];
    std::cout << "Size of arr: " << sizeof(arr) << std::endl;
    return 0;
}

Then I threw GCC, Clang, and MSVC at them.

As far as I know, GCC and Clang both support variable length arrays (VLAs) as an "extra feature", and they both ate foo without a single complaint. Whereas MSVC, who does not support VLAs, complained.

On the other hand, none of them accepted bar on account of a being negative.

As for why GCC and Clang can't tell that ais negative in foo, that I will leave as a question for people more versed in compiler guts than I.

Frodyne
  • 3,547
  • 6
  • 16