Dlaczego stała się zmienia ?

0

Napisałem prostą klasę, którym zadaniem jest szyfrowanie stringów, szyfrowanie ma polegać na tym, że stringi są szyfrowane przed kompilacją kodu źródłowego a odszyfrowywanie dopiero przy jego 1 użyciu. Szyfruje zwykłym XOR'em, w STAŁEJ zmiennej trzymam klucz który jest liczbą całkowitą, lecz ta stała liczba zmienia swoją wartość w różnych częściach programu? O to kod:

string.h:

 
#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED

#include <initializer_list>
#include <windows.h>
#include <iostream>
using namespace std;

#define Random(s) ((unsigned long)((s[0] * s[4] * s[6]) ^ (s[1] * s[3] * s[7])))
const unsigned long Key = Random(__TIME__);

class EncryptedString
{
public:
    EncryptedString();
    EncryptedString(std::initializer_list<char> str);
    ~EncryptedString();

    unsigned long Length() const { return _length; }
    operator const char* ();
private:
    void Decrypt();

    bool _isEncrypted;
    unsigned long _length;
    char* _string;
};

template <char c>
struct Encrypt { enum  { Char = c ^ Key }; };

#define E(c) ((char)(Encrypt<c>::Char))
#define EncryptString1(s)  { E(s[0]), ('\0') }
#define EncryptString2(s)  { E(s[0]), E(s[1]), ('\0') }
#define EncryptString3(s)  { E(s[0]), E(s[1]), E(s[2]), ('\0') }
#define EncryptString4(s)  { E(s[0]), E(s[1]), E(s[2]), E(s[3]), ('\0') }
#define EncryptString5(s)  { E(s[0]), E(s[1]), E(s[2]), E(s[3]), E(s[4]), ('\0') }
#define EncryptString6(s)  { E(s[0]), E(s[1]), E(s[2]), E(s[3]), E(s[4]), E(s[6]), ('\0') }


#endif // STRING_H_INCLUDED

string.cpp:

#include "string.h"

#include <iostream>
using namespace std;

EncryptedString::EncryptedString() : _isEncrypted(true), _length(0), _string(NULL)
{
}

EncryptedString::EncryptedString(std::initializer_list<char> str) : _isEncrypted(true)
{
    _length = str.size() - 1;
    _string = (char*)malloc(str.size());
    unsigned long i = 0;
    for(char c : str) _string[i++] = c;
}

EncryptedString::~EncryptedString()
{
    if(_string != NULL) free(_string);
}

EncryptedString::operator const char* ()
{
    if(_isEncrypted == true) Decrypt();
    return _string;
}

void EncryptedString::Decrypt()
{
    cout << "Wartosc stalego klucza w funkcji Decrypt: " << Key << endl << endl;
    for(unsigned long i = 0; i < _length; i++)
    {
        _string[i] = _string[i] ^ Key;
    }
    _isEncrypted = false;
}
 

main.cpp:

#include <iostream>
#include "..\String.h"
using namespace std;

int main()
{
    cout << "Wartosc stalego klucza w funkcji main: " << Key << endl << endl;

    cout << "_____________________________________________" << endl;
    EncryptedString str1 = { E('d'), E('u'), E('p'), E('a'), '\0' };
    cout << "Wyświetl napis zaszyfrowany: " << str1 << endl;

    cout << "______________________________________________" << endl;
    char str2[] = { E('d'), E('u'), E('p'), E('a'), '\0' };
    cout << "Tablica z tymi samymi znakami przed odszyfrowaniem: " << str2 << endl;
    for(int i = 0; i < 4; i++) str2[i] ^= Key;
    cout << "Tablica z tymi samymi znakami po odszyfrowaniu: " << str2 << endl;

    cout << endl;
    cout << "Wartosc stalego klucza w funkcji main: " << Key << endl << endl;

    system("pause");
    return 0;
}

Nie mam pojęcia co jest grane, że stała zmienna ma inną wartość w różnych miejscach :(

0

#include jest niczym innym jak swego rodzaju copy-pastem, więc efektywnie masz oddzielne stałe Key w dwóch plikach cpp.

http://stackoverflow.com/questions/14894698/why-does-extern-const-int-n-not-work-as-expected

1
const unsigned long Key = Random(__TIME__);

Nie trzyma się globalnych zmiennych w pliku .h. Powinno się tam tylko zadeklarować zmienną, ze słowem extern:

// string.h
extern const unsigned long Key;

a właściwą zmienną umieścić w pliku .cpp:

// string.cpp
const unsigned long Key = Random(__TIME__);
0

Ohh tak Panowie zupełnie o tym zapomniałem :( zrobiłem jak @Azarien napisał, lecz teraz muszę sobie poradzić z błędem: the value of 'Key' is not usable in a constant expression. Mam zadeklarowaną zmienną Key dokładnie jak @Azarien kazał, czyli jest ona stała, więc dziwi mnie ten błąd.

Oczywiście chodzi o fragment kodu:

 template <char c>
struct Encrypt { enum  { Char = c ^ Key }; };
0

Wartość w enumie musi być stałą czasu kompilacji (musi być znana kompilatorowi).
Twoje Key jest stałą czasu wykonania, czyli wartość określana jest dopiero podczas uruchomienia programu.

0

A dlaczego to tak?

Taki kod kompiluje się bez problemu:

const unsigned long TempKey = Random(__TIME__);
template <char c>
struct Encrypt { enum  { Char = c ^ TempKey }; };

Natomiast kod:

 
file: string.h
extern const unsigned long Key;
template <char c>
struct Encrypt { enum  { Char = c ^ Key }; };

///
file: file.cpp
const unsigned long Key = Random(__TIME__);
0

Taki kod kompiluje się bez problemu:

Nie wiem jaki masz kompilator, ale

[pi@raspberrypi:~/myprogs]$ clang++ test.cpp --std=c++11
test.cpp:9:33: error: expression is not an integer constant expression
struct Encrypt { enum  { Char = c ^ TempKey }; };
                                ^~~~~~~~~~~
test.cpp:16:13: note: in instantiation of template class 'Encrypt<'A'>' requested here
    cout << Encrypt<'A'>::Char << endl;
            ^
test.cpp:9:37: note: subexpression not valid in an integer constant expression
struct Encrypt { enum  { Char = c ^ TempKey }; };
                                    ^
1 error generated.
0

@Azarien korzystam z minGW C++11, http://ideone.com/CmleVH.

1 użytkowników online, w tym zalogowanych: 0, gości: 1