0

I have a problem here :( I create here multiple global variables and put them into an array. In funktion extractLabel() I fill these variables with binary code values per variable = binarycode. I print them out and everything is alright. Then I print the same variables out from the array. But there the variables have the values 0. But shouldn't these variables have the same value in the array, too? If not, how I could fix this?

Thank you for helping!

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <array>
#include <math.h>
#include <algorithm>
#include "Client.hpp"



static long long a_word = 4294967295;
static long long c_word;
static long long c_label1;
static long long c_label2;
static long long c_label3;
static long long c_label4;
static long long c_label5;
static long long c_label6;
static long long c_label7;
static long long c_label8;
static std::vector<bool> binCode;
static std::array<long long, 8> c_tokens = {c_label1, c_label2, c_label3, c_label4, c_label5, c_label6, c_label7, c_label8};



void executeClient() {
    receiveValue();
    calculateDecBin();
    extractLabel();
}

void receiveValue() {
    c_word = a_word;
}

void calculateDecBin() {
    while (c_word) {
        int rest = c_word % 2;
        c_word = c_word / 2;
        binCode.push_back(rest);
    }
    std::reverse(binCode.begin(), binCode.end());
}

void extractLabel() {

    std::cout << "Label values:" << std::endl;
    for(int i = 0; i < 8; i++) {
        c_label1 = stoll(std::to_string(c_label1) + std::to_string(binCode[i]));
    }
    std::cout << c_label1 << std::endl;

    for(int i = 8; i < 10; i++) {
        c_label2 = stoll(std::to_string(c_label2) + std::to_string(binCode[i]));
    }
    std::cout << c_label2 << std::endl;

    for(int i = 10; i < 26; i++) {
        c_label3 = stoll(std::to_string(c_label3) + std::to_string(binCode[i]));
    }
    std::cout << c_label3 << std::endl;

    for(int i = 26; i < 27; i++) {
        c_label4 = stoll(std::to_string(c_label4) + std::to_string(binCode[i]));
    }
    std::cout << c_label4 << std::endl;

    for(int i = 27; i < 28; i++) {
        c_label5 = stoll(std::to_string(c_label5) + std::to_string(binCode[i]));
    }
    std::cout << c_label5 << std::endl;

    for(int i = 28; i < 29; i++) {
        c_label6 = stoll(std::to_string(c_label6) + std::to_string(binCode[i]));
    }
    std::cout << c_label6 << std::endl;

    for(int i = 29; i < 31; i++) {
        c_label7 = stoll(std::to_string(c_label7) + std::to_string(binCode[i]));
    }
    std::cout << c_label7 << std::endl;

    for(int i = 31; i < 32; i++) {
        c_label8 = stoll(std::to_string(c_label8) + std::to_string(binCode[i]));
    }
    std::cout << c_label8 << std::endl;


    std::cout << "array values:" << std::endl;
    for(int i = 0; i < c_tokens.size(); i++) {
        std::cout << c_tokens[i] << std::endl;
    }
}
Coop4Free
  • 35
  • 5
  • 3
    If I understand the question correctly, I think you need to learn about [value vs reference semantics](https://akrzemi1.wordpress.com/2012/02/03/value-semantics/). – 0x5453 Jun 15 '20 at 13:41
  • 2
    Why do you say the "same variables"? Aren't `c_tokens` and, say, `c_label1` completely different variables? Isn't `c_tokens` an array of `long long` *values*? – David Schwartz Jun 15 '20 at 13:41
  • 1
    `c_tokens` does not contain variables, it contains values, and it contains the values `c_label1` et al had when it was initialised (that is, zeros). – molbdnilo Jun 15 '20 at 13:43
  • 1
    `static std::array c_tokens = {c_label1, c_label2, c_label3, c_label4, c_label5, c_label6, c_label7, c_label8};` initializes your array with the current value of these variables. After initialization there is no connection between their values. Meaning if you change c_tokens[0] it does not modify c_label1 or vise versa. Same with the rest. – drescherjm Jun 15 '20 at 13:43
  • [This question](https://stackoverflow.com/questions/1164266/why-are-arrays-of-references-illegal) may be helpful. – David Schwartz Jun 15 '20 at 13:45
  • @DavidSchwartz thanks! Always annoying me, this part. Changed my answer to talk about reference_wrapper – Jeffrey Jun 15 '20 at 13:52

4 Answers4

1

C++ has copy semantics.

When you do:

static std::array<long long, 8> c_tokens = {c_label1, c_label2, c_label3, c_label4, c_label5, c_label6, c_label7, c_label8};

(this gets executed early on)

The value of the variables are copied into a new c_tokens variable. From this point on, changing either c_tokens or c_label... will not affect the other.

You could store references in the array using reference wrappers:

static std::array<std::reference_wrapper<long long>, 8> c_tokens = {c_label1, c_label2, c_label3, c_label4, c_label5, c_label6, c_label7, c_label8}; // actually works, but heavy 

In that case, what the array would contain is a reference (a sort of link) to the specified variable. Access via either the array or individual variable would immediately affect the other.

But without a larger look at your project it's not clear whether that's the right approach or not. Having a list of variables with a number at the end is a code smell.

Jeffrey
  • 11,063
  • 1
  • 21
  • 42
  • I'd remove the bit about an array of 'real' references then, since it doesn't work. `reference_wrapper` can be OK if e.g. you pass elements to functions taking real references, as it has a conversion operator, or similarly if you iterate by `for (long long&: c_tokens)`, etc. – underscore_d Jun 16 '20 at 09:10
1

You are making a confusion between values and references. The c_tokens array is initialized with the current values of the c_labeli variables. As they are static, they are initialized to 0, which explains that you find 0 values in the array.

But when you later change the values of the c_labeli variables, they are completely distinct from the array, and nothing is changed in c_tokens.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

The variables are not in the array! You created an array from the values of the variables that they had at the time you created the array. You can be lucky, that the values are 0 and not something else, because the variables were uninitialized when you used them to fill the array. The variables and the array are in two different memory areas, if you change one, the other one remains unchanged.

JoKing
  • 430
  • 3
  • 11
  • Luck is not required here. `static` objects are zero-initialised. However, sure, I would recommend that one made that explicit in the code, anyway, to encourage proper code hygiene and not cause bugs if that code is transplanted later and those objects aren't static anymore. :-) – underscore_d Jun 15 '20 at 13:47
0

Here is a slightly less verbose way of writing that code, which sidesteps the variable question entirely and makes it clear what goes where: (assuming c_tokens is a vector. If you want a static array just assign to indices)

long long pack(std::vector<bool>::const_iterator it, int count) {
    long long res = 0;
    while (count-- > 0) {
        res = res * 10 + *it;
    }
    return res;
}

void foo() {
    c_tokens.emplace_back(pack(binCode.cbegin() + 0, 8));
    c_tokens.emplace_back(pack(binCode.cbegin() + 8, 2));
    c_tokens.emplace_back(pack(binCode.cbegin() + 10, 16));
    c_tokens.emplace_back(pack(binCode.cbegin() + 26, 1));
    c_tokens.emplace_back(pack(binCode.cbegin() + 27, 1));
    c_tokens.emplace_back(pack(binCode.cbegin() + 28, 1));
    c_tokens.emplace_back(pack(binCode.cbegin() + 29, 2));
    c_tokens.emplace_back(pack(binCode.cbegin() + 31, 1));
}
Botje
  • 26,269
  • 3
  • 31
  • 41