1

Having simple c++ program like so:

#include <stdio.h>
#include <limits.h>

template <typename T>
char BinVal(T SrcVal) {
    
    //short BitsCount = sizeof(T)*CHAR_BIT;
    short BitsCount = sizeof(T)*CHAR_BIT;
    short SeparatorCount = sizeof(T)*2-1;
    short SeparatorSize = CHAR_BIT/2+1;
    static char BinValStr[ BitsCount + SeparatorCount ] = {0};
  
    printf("BitsCount: %d\n", BitsCount);
    printf("SeparatorCount: %d\n", SeparatorCount);
    printf("BinValStr size: %d\n", BitsCount + SeparatorCount);
    
    int i = 0;
    int j = 0;
    
    for ( i=BitsCount+SeparatorCount-1; i>=0; i-- ) {

        if( (j+1)%SeparatorSize == 0) {
            BinValStr[i] = ' ';
        }
        else {
            if( SrcVal&1 == 1 )
                BinValStr[i] = '1';
            else
                BinValStr[i] = '0';
                SrcVal >>=1;
        }
        j++;
    
    }
    
    char y='o';
    return y;
    //return BinValStr;
    //printf("\nStr: %s", BinValStr);
}

int main(){
    
    short val = 0b0000'0100'0001'0110; //18 dec
    printf("\nStr: %c", BinVal(val) );
}

i get "storage size of ‘BinValStr’ isn’t constant" error.

When i make the BinValStr var "normal", local everything is OK. Why does making the variable static gives me the error?

DarosRT10
  • 31
  • 6

2 Answers2

3

This is not an answer to your question, "Swift - Friday Pie" has already covered that. Instead I want to point out a small issue in some of your other code:

if( SrcVal&1 == 1 )

While this works, it may not work like you think. In short: == binds harder (has higher precedence) than &.

https://en.cppreference.com/w/cpp/language/operator_precedence

This means that the above if goes like this:

1 == 1 => true. SrcVal & true => SrcVal & 1 => does the bitwise AND and returns 1 or 0. That number is then interpreted as a truth value and gives the result you want. So why is it a problem when it works? Well, lets say that you want the same test again, but now you are looking for when the first bit of ScrVal is 0, so you write:

if( SrcVal&1 == 0 )

And now it just never works because: 1 == 0 => false. ScrVal & false => ScrVal & 0 => 0.

How to fix it? The two easy options:

  • Wrap the bitwise AND in parenthesis: if( (SrcVal & 1) == 1 )
  • Omit the comparison: if( SrcVal & 1 )
Frodyne
  • 3,547
  • 6
  • 16
2

You attempted to use varaibles as size of array, while you need compile-time values. ISO C++ doesn't allow to allocate array dynamically (GNU extension for variable length arrays is an exception), thus expression for size of array should be constexpr

template <typename T>
char BinVal(T SrcVal) { 
    constexpr short BitsCount = sizeof(T)*CHAR_BIT;
    constexpr short SeparatorCount = sizeof(T)*2-1;
    
    constexpr short SeparatorSize = CHAR_BIT/2+1;
    static char BinValStr[ BitsCount + SeparatorCount ] = {0};

Pre-C++11 variant could be just static const or using integral_constant or similar construct.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • 2
    Also, [``](https://en.cppreference.com/w/cpp/container/array). – DevSolar Aug 10 '20 at 06:40
  • @DevSolar if allowed (and supported), yes, of course. It also a good learning experience to peek into implementation of those simple templates, `std::array`, `integral_constant` essentially do something like this inside. – Swift - Friday Pie Aug 10 '20 at 06:43
  • While `std::array` probably is a better idea than []-array, not that it also requires its size to be a compile-time constant. So this answer applies there too. – Frodyne Aug 10 '20 at 07:57
  • Thx. guys for help, i suspected that the key is just making the variables `const`, but what's REALLY bizarre - when i remove `static` keyword form _BinValStr_ definition (making it `local`) the code DO WORKS (no errors or warnings) even there is no`const` medifier for the variables!??? – DarosRT10 Aug 10 '20 at 15:10
  • @DarosRT10 you likely use GNU compiler then, or compatible. That's VLA, a C feature which isn't supported by C++ standard. Essentislly it's a dynamic array in stack with limitation that you cannot pass it out of function. VLA cannot be static or global. E.g. g++ supports it by default – Swift - Friday Pie Aug 10 '20 at 16:34