News:

Simutrans.com Portal
Our Simutrans site. You can find everything about Simutrans from here.

code::blocks

Started by Roads, September 24, 2012, 03:51:48 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Roads

I'm about to download code::blocks so I can get started with a c++ tutorial.  Any advice on setup.exe or mingw-setup.exe?


Modify:  Nevermind, sorry for the post; downloaded
Dev C++

prissi

Not sure that this is the most easy way to start. If you use windows, MSVC C++ 2010 may be even easier.

Ters

Is Dev C++ still around? Last I heard of it, it seemed dead and rotting.

Personally, I use code::blocks when I really need an IDE for C/C++, though it's not the greatest piece of software by a long shot. I had mingw set up manually long before I started using code::blocks. From way back when I programmed in Notepad. (Actually, way back then, I used DJGPP, but that's also GCC.)

However, I have never seen a C/C++ IDE as good as the major Java IDEs. And though some of them try to support C/C++ also, they can't seem to pull it off. Microsoft Visual C++ does at least seem solid, but I guess it's something about C/C++ that makes IDEs complicated.

Roads

It has been so long did I did any of this stuff ... and I never worked with anything as low level as C, I'm a total newbie.  I'm going to start with "hello world" because I think I need a solid footing.  First thing I did was download MSVC C++ 2010 and it wouldn't even compile "hello world."

I'll switch to MSVC C++ 2010 when I get a little understanding of the most basic stuff...I mean pointers and arrays and such.  Any help along the way will be greatly appreciated.  Right now I just want to get to the point where I can take care of the little sign addon as changes to the game are made.  I realize I should not be depending on y'all to do stuff like that.  Also I think it would be really great to expand that capability a bit, maybe offer one that lights up at night for cinemas and such.

Markohs

 For Windows users Microsoft Visual Studio 2010 express is the best option in my oppinion.

http://www.microsoft.com/visualstudio/eng/products/visual-studio-express-products

Another option is installing mingw:

http://mingw.org/

Or even better, Instal VMWare/VirtualBox and inside there just install a ubuntu and use GCC/Makefile. You can also consider Clang, if you have problems with GPL licenses, as it's usual nowadays sicne last versions are super-restrictive.

http://clang.llvm.org/

I've tried Code::blocks in linux and found it horrible, but that's just my personal opinion.

Roads

Wow!  Thank you.

This is a lot and I'll read and I'll study it all.  Up until 2-3 days ago my thinking had been to finish a game (I still haven't gotten past 1960), and then concentrate on the graphic and code work I want to do.  I've had a new thought.  It is not the destination in this case that matters.  It is the journey.  With that in mind, I'm no longer going to worry about finishing a game, I'm going to approach this the way I like to do things.  That is, play, study, whatever I want for the day or time, then do something else and let whatever I've been doing "soak" in.  It seems when I do this and come back to it, I have a much better view and understanding of it.

yorkeiser

I don't continuously use c and c++ at work by 3 or 4 years, but until then (2009 I think) I found Code::Blocks the best solution for c/c++ programming IDEs.
I actually use (and used) MS visual studio since 2005 version (always professional editions), and yes, it's a good IDE, but only to code in .NET specific languages imho: I found lacking support for c e and its OO counterpart.
Get rid of Dev c++, it's horrible, buggy and lacking support, its developers still are in debt with me for many missed sleep hours... Also some years ago I seem to remember the project to be died, I don't know if it's reborn, but I wouldn't trust however

Roads

yorkeiser,

I will certainly take your advice and get rid of Dev C++ but not just yet.  I spent probably 30 mins last night trying to figure out why my little program wouldn't compile and I had put a semi colon after the #define statement.  So I'm not even taking baby steps yet, I'm still crawling.  I need some practice with the assignment statements and basic stuff like that.  Dev C++ is very simple to use and should be okay for doing that sort of thing.

Markohs

#8
Yea, take into account #define is a preprocessor directive, that just defines a literal to be substituted with something BEFORE compiling in the whole program. Thus if you are using the defined macro in your program you have to mind the macro will just be substituted, and might need a semicolon depending on wthat you are doing:

This two examples will compile even the first one is preferrable because it's cleaner, the second example will compile but it's considered bad quality code most of the times.


#define ZERO 0

int i = ZERO;



#define ZERO 0;

int i = ZERO


The result of the preprocessing (in both cases) will be:

int i = 0;


This is invalid because it misses a semicolon:


#define ZERO 0

int i = ZERO



The result of the preprocessing will be:

int i = 0


Why is the first example preferable? Because it allows you to write something like that:


#define ZERO 0
#define TEN 10

int i = ZERO + TEN + 7;
int z = ZERO;
int t = TEN;




The result of the preprocessing will be:

int i= 0 + 10 + 7;
int z = 0;
int t = 10;

Roads

Yes Markohs, I understand and thank you.

The only thing I didn't get at first about the #define concept was why have it?  You could just assign those values.  Then it occurred to me if you have several functions, the #define would prevent you from having to make those assignments in every function.  Is this right?

Ters

The whole preprocossesor thing allows metaprogramming that opens up a whole bag of neat and hurtful tricks.

You can also put #define ZERO 0 in a header file that is included in multiple source files, but if you put int zero = 0; in such a header file, you get a multiple definition error during linking as there now are multiple variables with the same name zero. There have been other and arguably better solutions over time for giving constants a global name, but the define-way is still around for backward compatibility and for use with preprocessor metaprogramming (at which point int zero = 0; hasn't been evaluated yet).

A thing to remember is that, all things starting with # is in essence just a lot of copy-paste and search-replace stuff done on the source code before compilation. Though closely associated with C/C++, you can in principle use the preprocessor for any language, from plain text and HTML to assembly code if you invoke it explicitly.

Markohs

 Yea, all the macro processing is one of the things that make C/C++ specially tricky to program, most of modern languages don't have it, and it's better that way.

One of the main useful things in preprocessor defines is defining constants that MIGHT change in future compilations of the program if the programmer decides so. For example you could define MAX_PLAYERS as the number of players your game supports, and define for example an array that stores each player's money:


#define MAX_PLAYERS 8

int player_money[MAX_PLAYERS];

unsigned int bankrupt_players(){
   unsigned int n = 0;

   for (i=0;i<MAX_PLAYERS;i++){
       if (player_money[i]<0)
           n++;
   }

   return n;
}



If in the future you decide you will support up to 16 players for example, you just need to change the #define to 16 and re-compile the program. Since you used MAX_PLAYERS everywere you were sizing data structures of even the for loop, the re-compiled program will be correct.

Using #ifdef, #else, #endif we can also write different code that will be compiled or no depending if some vaiables are defined or not. This allows to write parts of the code that deal with UNIX specific I/O functions, or Win32 functions, and compiling one of another using the macro defining tools in compiler (in gcc it's gcc -DMACRONAME, for example).

it's also useful to avoid including a .h file multiple times, you'll see simutrans files starting like:


#ifndef __CITYCAR_READER_H
#define __CITYCAR_READER_H

...
#endif


If you have simutrans sourcecode at hand, for example you can see karte.cc ("karte" means "map" in german I think, and "welt" "world"). karte.cc implements the map drawing functions in the minimap.

On that file you can see:


// Kenfarben fuer die Karte
#define STRASSE_KENN      (208)
#define SCHIENE_KENN      (185)
#define CHANNEL_KENN      (147)
#define MONORAIL_KENN      (155)
#define RUNWAY_KENN      (28)
#define POWERLINE_KENN      (55)
#define HALT_KENN         COL_RED
#define BUILDING_KENN      COL_GREY3


See? That's where we define the colors wich roads, stops, buildings... will be drawn as in simutrans map. If we want to change their color, we whould just need to alter those defines and re-compile. We could make that colors dinamic, allowing to change that value during program execution, but looks like now it's just static, hard-coded into the program.

So, to make it short, macros are meant to make you able to change some parts of the code that will get hardcoded once the compilation ends. It's all static after the compilation ends, since it's only interpreted  before the program gets compiled, and code is generated.

Markohs

#12
 And by the way, it's a common rule, and followed by almost all C/C++ programmers that macros names are allways written is caps, to distinguish them easily from normal variables.

But nothing is forcing you to do it, you can define a macro name in lowercase.

EDIT: Just read what Ters said and yea, it's like copy-paste. ;)

Ters

For stuff like MAX_PLAYER, const int MAX_PLAYER = 8; is the newer and typesafe version of #define MAX_PLAYER 8. But the different nature of those two means that they are not directly interchangeable. When you write const int MAX_PLAYER, MAX_PLAYER is destined to become a part of the final executable, while a #define disappears during compilation leaving only the number behind in its stead.

However, since having the number directly in the code can be faster than getting it from a variable/constant in memory, modern compilers will sometimes/often replace references to the constant with its value sort of like with define, just at later stage (and with proper scoping rules for C++).

Since this feature is "only" about 20 years old (I think, perhaps even a bit less), older code and code written for old systems don't use it. And old habits (and tutorials and example code) die hard.

prissi

const int bla=8; may create warnings when you want to assign it to an unsigned or char. The would not happen with enums or #defines. On the other hand, such error checking by the compiler is handy.

Actually, it should be "static const int" but this did not work in some compilers in h-files. But I think nowadays all fine with this too.

Ters

The confusing thing is that static const int means different thing depending on where you write it. More specifically, it's the meaning of static that is different, and the two meanings are in a sense opposites, as one enlargens the scope in a sense, thile the other restricts it.

TurfIt

On the topic of Code::Blocks  -setup.exe would be best as mingw-setup.exe has a rather old MinGW included. Best to just get MinGW separately.
The 10.05 version works fine, but is missing some things from the newer nightly releases. However they are terribly buggy - need to know enough to know when it's lying to you and give it a swift kick in the ...

MSVC might be simpler for some, but hard to beat Code::Blocks and MinGW for a completely free, totally portable setup that doesn't mess with your OS install.
Dev C++ lasted < 5mins here. Can't remember why, but it must've been rather bad to toss it that quick.


prissi

dev c++ is easy to install al libaries but refuse to work with the current makefile, last time I tested.

Markohs

#18
but, if you put define a "static const int zero = 0" in a .h and include that .h from different .cc files... Will the compiler generate one entry in the data area for each compiled object (.o) that included the .h? Might the linker resolve this and merge all those const variables in just one int?

EDIT: Thinking about this... ofc it will generate one entry in data for each .cc, even it can optimize it further and just replace the ocurrences by the value itself everywere in the .cc. And I pretty much doubt the linker whould do anything like I menctioned.

I like this definition more than macros.

Markohs

btw, found this interesting, from here

stackoverflow.com has to be one of the last useful techincal pages in the web, found lots of useful stuff there, about system administration and programming.

"
One thing worth pointing out, is that the following declaration:
const int i1 = 0;
is exactly the same as static const int i = 0.  A variable in a namespace declared with const and not explicitly declared with extern is implicitly static.  If you think about this, it was the intention of the C++ committee to allow const variables to be declared in header files without always needing the static keyword to avoid breaking the ODR.
"

Roads

#20
First:  Thank you all!

There is so much here I doubt I can even get close to addressing it all.  That said I'm going to try and absorb it little by little.  Markohs, I copied and pasted your program:

#define MAX_PLAYERS 8

int player_money[MAX_PLAYERS];

unsigned int bankrupt_players(){
   unsigned int n = 0;

   for (i=0;i<MAX_PLAYERS;i++){
       if (player_money[i]<0)
           n++;
   }
   return n;
}



into my compiler and got a couple of errors.  It is likely a compiler problem as y'all did say Dev C++ is crap.  Anyway I got rid of one of the errors by assigning the value i = 0.  The other error is for this "for (i=0;i<MAX_PLAYERS;i++)" and the error is

[linker error] undefined reference to WinMain

This I have no idea why since it looks like to me you've created an array with 8 elements and using that in a "for" statement...
Wondering if I'm even in the ball park on this.


Modify:


Ters, here is the program as I have put it in my compiler:
I can't see why this will not compile:




#include <iostream>


using namespace std;


#define MAX_PLAYERS 8


int player_money[MAX_PLAYERS];


unsigned int bankrupt_players()
{
   unsigned int n = 0;
   unsigned int i = 0;
   
   for (i=0;i<MAX_PLAYERS;i++)
   {
       if (player_money[i]<0)
           n++;
   }
   return n;
}

Ters

Markohs code isn't a full program, hence you can't compile just what he wrote into a runable EXE. It's enough for a DLL, though, but those can't be run directly. Markohs also forgot to declare i as an int. It should be for (int i=0;i<MAX_PLAYERS;i++){. (Older code, or code that needs to know at which i the loop terminated, would put int i; outside the for-loop.) I guess the purpose was to demostrate the #define, so the rest was not as important.

Roads

#22
Okay, it is running:




#include <iostream>


using namespace std;


#define MAX_PLAYERS 8


int player_money[MAX_PLAYERS];
unsigned int bankrupt_players;


int main()


{
   unsigned int n = 0;
   unsigned int i = 0;
   
   for (i=0;i<MAX_PLAYERS;i++)
   {
        if (player_money[i]<0)
             n++;
   }
   return n;
}



I'm guessing what Dev C++ didn't like was either not having a function "main" or didn't like the name "bankrupt_players" as a function name although why that would be is beyond me.


Yes Ters, I realize Markohs was only showing a demonstration.  It was new code to me though and looked like it would run so I thought why not play with it using "cout" and kinda get a feel for it.  I'm guessing arrays are used extensively...


Markohs, many thanks for all this info.  I don't have the source code to the game yet.  I had seen the word "karte" before and had no idea what it meant.  My youngest son reads German very well though so I'll get him to help me once I get to that.

Markohs

as ters pointed out the exaple just included one function, all C/C++ programs are suposed to include a "main" routine that's the one that the operating system will execute when the program it's run, once you exit the main(), the program will end, usually.

about the "i" variable, as ters pointed again, I forgot to declare it.

So it's better to write:


for (unsigned int i = 0 ; i<MAX ; i++){
...
}


than:


unsigned int i=0;
for (i=0;i<MAX;i++){
...
}


Makes more sense to declare inside the loop since I won't need the variable "i" outside the "for" loop, allways try to limit variables to the smallest scope possible, to not over-populate the global namestace (the global variables, that are in most of the cases a bad idea to use and should be minimised.  That example assigns 0 to the variable i twice, too, when just one was needed.

You can see what can possibly happen here:


void test (){
    unsigned int i=0;
    unsigned int j=0;

    for (i=0;i<MAX;i++){
        printf("Hi, I'm at position %u\n",i);
    }

    for (j=0;i<MAX;j++){
        printf("Hi, I'm at position %u\n",j);
    }
}


There is something I did intentionally write wrong on that code that whoudn't happen if you'd have declared the variables in the scope of the for, and not at function level. Can you find it? maybe I amde more than one mistake accidentally too hehe. :)

I didn't compiled the code, I just wrote the algorithm without testing, so I might have done some errors.

If you want to practise, you can extend that code to:

1) Print each player's money and how much of them are bankrupt (have <0 money)
2) add/remove a random amount of money from all players
..

There are lots of things you can do to practise. To print values you need the "printf" function, with will require you to add "#include <stdio>", and to get random values you can use this

Ters

(I wrote this before Markohs posted, so some things get repeated, but also more elaborated.)

Quote from: Roads on September 27, 2012, 05:41:07 AM
I'm guessing what Dev C++ didn't like was either not having a function "main" or didn't like the name "bankrupt_players" as a function name although why that would be is beyond me.

main() is the start of a program (console program on Windows). WinMain() is the start of a Windows GUI program. Without either, you don't have a program. I should perhaps have made that more clear in my previous post. Since you told Dev C++ to compile a (GUI) program, it failed when it couldn't find WinMain() (or main()).

Further more, what you return from main() (which must be an int) should by convention be 0 for success, and anything else if something went wrong. So the program in your last post will report back that it "failed" if there are bankrupt players, which may of may not make sense.

Markohs

 Refined it a bit, now it compiles no problem, tested in visual studio


#include <stdio.h>
#define MAX 300

void test (){
    unsigned int i=0;
    unsigned int j=0;

    for (i=0;i<MAX;i++){
        printf("Hi, I'm at position %u\n",i);
    }

    for (j=0;i<MAX;j++){
        printf("Hi! I'm the second loop, I'm at position %u\n",j);
    }
}

int main(){
   test();
}



Roads

I figured using caps was the convention for constants declared with #define.  It seems you are calling them macros or maybe I'm just not understanding.

Sometime I'll ask why the colors are a number and one I see is COL_RED.  I was under the impression for some reason that colors had to be in hex or base 16, however it should be stated, not sure.

Thanks for explaining that about declaring variables only where they will be used.  Something I programmed in years ago, not sure now if it was FoxPro or Oracle, but it seems now like all variables had to be "initialized" before they could be used and I got into the habit of declaring all those at the beginning of the program.  This actually makes it a lot easier because sometimes those programs would get pretty big and you could spend some time chasing down missing variable names or conflicts.

In your code where you asked if I could find what you did intentionally wrong, the only thing I could find was you didn't #define MAX.  And of course I had to change the function name to main. :)
OOPS, nope, here is the problem you are talking about I bet: "(j=0;i<MAX;j++)"
I didn't find it until I changed the code to "(unsigned int j=0;j<MAX;j++)"

I haven't practised any of this yet but will do so now.  Just wanted to post and say all your help and Ters' help is awesome.

Markohs

#27
Quote from: Roads on September 27, 2012, 08:24:20 PM
I figured using caps was the convention for constants declared with #define.  It seems you are calling them macros or maybe I'm just not understanding.

Macros and #define constants are the same thing. The C/C++ preprocessor is just a macro language.

Quote from: Roads on September 27, 2012, 08:24:20 PM
Sometime I'll ask why the colors are a number and one I see is COL_RED.  I was under the impression for some reason that colors had to be in hex or base 16, however it should be stated, not sure.

any number expressed in digits in C is by default in decimal notation. if it starts with 0, it's octal, and beggining in 0x , hexadecimal. It's a number after all, you can input it in any format to C.

http://www.cplusplus.com/doc/hex/

Atm simutrans represents a pixel as a 16 bit integer number, color and graphs are managed in simgraph16.cc .  it's represented in bits as 5 bits red, 5 bits green and 5 blue (I say this from the top of my head, might be wrong in some details). So that 16-bit number just represents a color.

COL_RED is a macro/#define that must be in some other part of simutrans includes.

Quote from: Roads on September 27, 2012, 08:24:20 PM
Thanks for explaining that about declaring variables only where they will be used.  Something I programmed in years ago, not sure now if it was FoxPro or Oracle, but it seems now like all variables had to be "initialized" before they could be used and I got into the habit of declaring all those at the beginning of the program.  This actually makes it a lot easier because sometimes those programs would get pretty big and you could spend some time chasing down missing variable names or conflicts.

In your code where you asked if I could find what you did intentionally wrong, the only thing I could find was you didn't #define MAX.  And of course I had to change the function name to main. :)
OOPS, nope, here is the problem you are talking about I bet: "(j=0;i<MAX;j++)"
I didn't find it until I changed the code to "(unsigned int j=0;j<MAX;j++)"

That's right! :) The thing is, when you reduce the scope, it's easier to catch those errors, with the solution you post, the compiler will complain and in that case with an error, not just a warning. In my version compiler won't complain at all, and that can prolly end in a bug that's undetected for lots of time, since maybe that second "for" loop is just important in some reduced cases, and the crash only shows from time to time, a hard to track down bug.

Ters

Quote from: Markohs on September 27, 2012, 10:55:21 PM
any number expressed in digits in C is by default in decimal notation. if it starts with 0, it's octal, and beggining in 0x , hexadecimal. It's a number after all, you can input it in any format to C.
In the end, they'll all end up as binary numbers anyway.

Quote from: Markohs on September 27, 2012, 10:55:21 PM
Atm simutrans represents a pixel as a 16 bit integer number, color and graphs are managed in simgraph16.cc .  it's represented in bits as 5 bits red, 5 bits green and 5 blue (I say this from the top of my head, might be wrong in some details). So that 16-bit number just represents a color.
On some platforms, it's 5 bits red, 6 bits green and 5 bits blue, which is why there is a function in simsys*.cc to convert from invididual R, G, B values to packed 16-bit color value.

The concept of indexed colors also exist in Simutrans, where one does not specify the color value directly, but as an index into a table with the actual colors. This is typically associated with 8-bit graphics, but Simutrans kind of uses it for player colors and color change due day-night cycle.

Roads

#29
TurfIt,

I'm planning on installing Code::Blocks and MingGW the way you suggested.  That sounds like a good solution for now...maybe go to MSVC 2010 later as I was really put off by the lack of info/support for beginners.  All I got after I installed it was a bunch of screens that led no where.

Markohs,

Just an update...I'm working on the program to print out player money, the number bankrupt, etc.  I've got an idea how to do it but will probably discard it as generally my first idea on how to program something is never the best one.  I could sure use a command reference for syntax on things such as the "if" statement.  The cplus tutorial site either doesn't have it or I've over looked it.


Modify:  Here's my program.  It runs but several problems including the data looks incorrect to me on printout.  I'm just guessing what %u means I thought modulo was just a remainder...  also, rand() is giving the same number every time the program runs.
Also guessed at the usage of "if.[size=78%]"[/size]





#include <iostream>
using namespace std;


#define MAX 8


int main ()
{
    unsigned x = 0;


    for (unsigned int i=0;i<MAX;i++){
        int player_money = rand();
        int luck = rand();
        int account_balance = (player_money - luck);
        printf("player %u\n",i);
        printf("player money %u\n",player_money);
        printf("luck %u\n",luck);
        printf("Account Balance %u\n",account_balance);
        if (account_balance < 0) x++;
    }
    if (x > 0) printf("The number of bankrupt players are %u\n",x);
    return 0;
}

Markohs

This looks like a good place to start reading:

http://www.cplusplus.com/doc/tutorial/

About the %u, inside a printf it's just to tell printf wich format is the parameter you are passing next, and %u means "unsigned int", and %i means "signed int", %s means it's a string. The usage of printf is a bit tricky itself, takes time to undestand at first. here you can find more info..

About the code I'd rearrange it a bit, take this template and try read and finish it. :)


#include <iostream>
using namespace std;


#define MAX_PLAYERS 8
#define STARTING_MONEY 200000;
#define ALTER_ITERATIONS 10;

int player_money[MAX_PLAYERS];

unsigned int get_num_bankrupt_players(){
    unsigned int result = 0;

    for (unsigned int i = 0 ; i < MAX_PLAYERS ; i++ ){
        if (player_money[i] <0 ){
            result++;
        }
    }
    return result;
}

void print_player_money(){
    printf("Account balances:\n");
    for (unsigned int i = 0 ; i < MAX_PLAYERS ; i++ ){
        printf("Player %u has %i SimDollars\n",i,player_money[i]);
    }
    printf ("Number of bankrupt players: %u\n",get_num_bankrupt_players());
}

void reset_player_money(){

    for (unsigned int i = 0 ; i < MAX_PLAYERS ; i++ ){
        player_money[i] = STARTING_MONEY;
    }
}

void alter_player_money(){
    // to be written...
}

int main ()
{

    printf("Starting up...\n");
    printf("Showing players money...\n");
    print_player_money();
    printf("Resetting all players money\n");
    reset_player_money();
    printf("Altering players money...\n");
    alter_player_money();
    printf("Showing players money...\n");
    print_player_money();
}


Markohs

just noted all the examples in that tutorials are done with cout instead of printf, change all printf's to couts if you feel like programming with cout is easier to you, the idea is practising the language. :)

Roads

Using printf is fine.  I've figured out I can use google and find the command I need...


Here's the program.  I doubt it is what you were looking for but it works so maybe it is okay.



#include <iostream>
using namespace std;




#define MAX_PLAYERS 8
#define STARTING_MONEY 200000;
#define ALTER_ITERATIONS 10;


int player_money[MAX_PLAYERS];


unsigned int get_num_bankrupt_players(){
    unsigned int result = 0;


    for (unsigned int i = 0 ; i < MAX_PLAYERS ; i++ ){
        if (player_money[i] <0 ){
            result++;
        }
    }
    return result;
}


void print_player_money(){
    printf("Account balances:\n");
    for (unsigned int i = 0 ; i < MAX_PLAYERS ; i++ ){
        printf("Player %u has %i SimDollars\n",i,player_money[i]);
    }
    printf ("Number of bankrupt players: %u\n",get_num_bankrupt_players());
}


void reset_player_money(){


    for (unsigned int i = 0 ; i < MAX_PLAYERS ; i++ ){
        player_money[i] = STARTING_MONEY;
        // inserting code - Roads
        printf("Player %u has %i SimDollars\n",i,player_money[i]);
        // end insert - Roads
    }
}


void alter_player_money(){
    // to be written...
    // inserting code - Roads
    signed int changed_money;
    int luck;
    for (unsigned int i = 0; i < MAX_PLAYERS; i++){
        changed_money = rand() + 200000;
        luck = rand() % 10;
        if (luck <= 6){
           player_money[i] = (player_money[i]) - changed_money;
           printf("player %u has lost %i SimDollars\n",i,changed_money);
           }
        else{
             player_money[i] = (player_money[i]) + changed_money;
             printf("Player %u has gained %i SimDollars\n",i,changed_money);
        }
        }
        // end of insert - Roads
}


int main ()
{


    printf("Starting up...\n");
    printf("Showing players money...\n");
    print_player_money();
    printf("Resetting all players money\n");
    reset_player_money();
    printf("Altering players money...\n");
    alter_player_money();
    printf("Showing players money...\n");
    print_player_money();
}

Markohs

good enough, in my oppinion. :)

Roads

Okay! :)

Many thanks for all your help Markohs.  I'll continue on with the tutorial at cplusplus and there's another site...

Markohs

good, if you have any question you'd like to ask, don't hesetiate to do it, I think teaching is my frustrated prefession. :)

isidoro

Quote from: Markohs on September 29, 2012, 05:33:20 PM
[...] I think teaching is my frustrated prefession. :)

I don't imagine you that old...  Never too late.  Give it a try.   ;)

@Roads:  one small detail: signed int is just the same as int.  In fact, if you don't have a special reason to use unsigned int, I would advise you to always use just int...

Roads

Markohs, you may not teach professionally and if not, then that profession is missing out on a good one!  Isidoro gives good advice. :)


I'm going to take you up on your offer to help whenever I have a question, I'm sure I'll have plenty in the future but will try not to abuse that offer.


Isidoro, thank you.  It is things like that you hardly ever get from tutorials.

Roads

#38
This is a tutorial example program:




// increaser
#include <iostream>
using namespace std;


void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar; pchar=(char*)data; ++(*pchar); }
  else if (psize == sizeof(int) )
  { int* pint; pint=(int*)data; ++(*pint); }
}


int main ()
{
  char a = 'x';
  int b = 1602;
  increase (&a,sizeof(a));
  increase (&b,sizeof(b));
  cout << a << ", " << b << endl;
  return 0;
}



There are several things about as clear as mud to me on this but I need to back track on one of them.  Why is this 'x' declared as a constant?  Wouldn't it have been just as good to declare it as "x"?


Combuijs

What a horrible programming style for a tutorial...  :police:

'x' is a character
"x" is a character array (string) of length 1. (actually it takes two characters: x and a terminating '\0' character, but lets not get into detail here...).
Bob Marley: No woman, no cry

Programmer: No user, no bugs



Markohs

Quote from: isidoro on September 29, 2012, 11:39:48 PM
I don't imagine you that old...  Never too late.  Give it a try.   ;)

hehe, no, I'm *just* 34. :)

Mmmm... Yea, thought about it sometimes, I'll try someday. The few times I've done it I've feelt good. :)

Markohs

#41
Yep, as Cumbuijs stated "x" is an array of characters and 'x' is just one character, one byte.

If you try to compile this:


char x = 'hi';


You will get warnings in compiler


1>c:\users\marcos\documents\visual studio 2010\projects\ttttt\ttttt\ttttt.cpp(10): warning C4305: 'initializing' : truncation from 'int' to 'char'
1>c:\users\marcos\documents\visual studio 2010\projects\ttttt\ttttt\ttttt.cpp(10): warning C4309: 'initializing' : truncation of constant value


That's I think because 'hi' it's interpreted as a integer since it's 2 bytes, one for each character : 0x6869. A int in C is 16-bit by definition. The equivalent, "hi" whould be 3 bytes since it whould be 0x686900, since strings are allways terminated with a 0 byte.

About constants: When you express "hi", the compiler allocates 3 bytes on the memory, just 3. If you later try to write into that buffer let's say 5 bytes, you'd be writing out of bounds of the allocated memory, and unpredictable results will appear. When you declare the variable as const, you make sure the compiler forbids a re-write in that variable, so safer code. But there are many ways of writing to it anyway, as you saw on that example-

Look it that way, when you declare a variable as "const", you make sure you don't write accidentally over it across your code, and you give a hint to the compiler that that variable will never change, so he can optimize the resulting code in certain ways that's hard to explain easily. :)

In the example, 'x' results in that in the binary,  there is one byte of memory, a read-only one that gets allocated with the initial value of 0x78 , that's the ascii code for "x". You'll notice that in C/C++ you can do all kinds of weird stuff, and later in that example they over-write that value. That's not suposed to happen, really.

The default type of 'x' is const char, but it's assigned to a char, later a pointer to it it's passed as (void *), and manipulated in the other function. Weird stuff, but it's designed I guess to show you what kind of "tricks" pointers allow you to use. pointers are very very useful, and the base of any serious C++ program, but are hard to understand fully, and really dangerous. Specially the "(void *)" cast that's the ultimate trick that allows you to manipulate ANYTHING ANYHOW.

Roads

@Combuijs


I had read all this stuff and kinda, sorta, understood it.  You made it really clear in one sentence.  Thank you!


@Markohs


I like this idea of the compiler protecting you from over writing constants.  I can see where that could happen.  I guess you could over write with something with the same number of bytes if I'm understanding this correctly but still it's a good thing.


It looks like about anything can be done with C++.  It sure is a long way from FoxPro and Oracle.


About the void pointer...I think I'm going to put that on the back burner and move on.  I'll come back to it in the future if need be.


It is really very kind of both of you to take the time to do this.  I hope others on the message board are reading this and learning something from it too.

Markohs

#43
Quote from: Roads on October 05, 2012, 12:16:08 PM
It looks like about anything can be done with C++.  It sure is a long way from FoxPro and Oracle.

Yeah, it's a language very close to hardware, that has it's advantages and disadvantages. It's speed light fast, has not much restrictions but in exchange you have to control lots of things manually, and are continually exposed to corrupt memory if you don't know exactly what are you doing.

It's like a swiss knife, useful for everything, reliable, versatile, simple, but... Whould you peel an elephant with a swiss knife? Prolly not a good idea... But you can do anything you want. )

It's hard to master and very prone to programming bugs, anyway this year it recovered #1 rank in most used languages in the world, C alone. If we sum C and C++ programs they almost double the number of java programs written nowadays. You can see it here:

http://langpop.com/

Ters

In C++, void pointers are useful for two things: interfacing with (legacy) C code and as a gateway to black magic. C++ also has better and safer ways to cast, though their verboseness makes them longer to write. (And for an example to combine so C-ish stuff like void pointer casting with streams, that is perhaps the most un-C-ish thing in all of C++.)

Roads

This kept nagging at me in the back of my mind while I was learning and doing other things.  Why did they use the word char and int when declaring pchar and pint as void pointers?  Couldn't they just have used the word void instead?  The reason I'm asking is if a void pointer can point to any data type, why declare them as char and int?

Hope my question makes sense.

Ters

I'm not quite sure what you meant in your second sentence, but you should use char * instead of  void * so you know what data type it is. It's called type safety. Otherwise, you may pass a pointer to an char to something expecting an int.

Roads

Thanks Ters.  Let me see if I got this.  Since a void pointer can point to any data type, then you could use void instead of char or int?  It is purely a convention or safety thing?

Markohs

It's because as void * you don't know the size of the data, so the compiler forbids you to use any indirection to access its contents until you cast it back to a known data pointer.

Try to compile this code to ilutstrate your doubt, and check what the compiler has to tell you:


int main(){

   char c = 'd';
   int i = 10;

   void *vp;

   vp = &c;

   *vp++;

   vp = &i;

   *vp++;

}


Markohs

If you try this:

#include <stdio.h>

int main(){

   char c = 'd';
   int i = 10;

   void *vp;

   vp = &c;

   char *cp;

   cp = vp;

   *cp++;

   vp = &i;

   int * ip;

   ip = vp;

   *p++;

}



it won't compile either, for a different reason(try it), and finally, this will compile:


#include <stdio.h>

int main(){

   char c = 'd';
   int i = 10;

   void *vp;

   vp = &c;

   char *cp;

   cp =  (char *) vp;

   *cp++;

   vp = &i;

   int * ip;

   ip = (int *) vp;

   *ip++;

}





Roads

C++ forbids incrementing a pointer of type void.

Okay, I think I've got it now.  As always, many thanks!


Modify:  You've added some stuff while I was posting.  I'll check it all out.  That first example and explanation was really good.

Markohs

Yea, to amke it short a pointer are (most of the times, and nowadays) just a 32 or 64-bit number representing one point of the memory. A void* is just that, a number, but you don't know what are you pointing at, it can be anything, a int, a char, a struct, a union,a object... You need to cast it to something so the compiler knows what are you pointing at, before manipulating it.

Roads

Well, I'm going to have to do a lot more thinking on this.  At first it looked like your second example should compile...it's pretty vague in my mind but I'm beginning to understand.  Doubt I would have ever figured this out without your help.

Ters

Simple rule: DON'T use void* unless you KNOW what you're doing. With void pointers, you're basically all the way down at the hardware level where everything is just bits of random data.

Some library functions accept void*, but they also ask for the size of the data and are made to operate on all kinds of data, and were written by people who (mostly) knew what they were doing. malloc also returns void pointer, but you're supposed to cast it to a pointer of the right type immediately. It is however the C way. The C++ library usually use templates, or some other C++ feature, instead (though sometimes just as a wrapper).

Markohs

If you are feeling overhelmed with C pointers you are in the right way, this **** is not easy to understand. Now you are learning.

To show us your grattitude Roads, I'd ask you to get us the brunette on the left of this video:

http://www.youtube.com/watch?v=vDRnkTSdbRE

I'd be happy just with that. ;)

Ters

As a warning, this was just pointers to data. There is also pointers to functions, which aren't any different if you think like a computer, but the type of these pointers are long to write. And in C++ there is also pointers to member functions, which inexperienced humans seem to have a hard time understanding why are different from regular function pointers, but they are very different from the point of view of the computer.

Roads

QuoteTo show us your gratitude Roads, I'd ask you to get us the brunette on the left of this video:


Picky. :)


If any of the three of them said, "hey old man, you wanna come play with me?"  I'd be like, anytime, anywhere, any place.


Guys, unless this void pointer is used in Simutrans, I seriously doubt I'll ever use it.  It's not like I'm going to give up retirement and look for a job. I like sleeping in and playing way too much.

Markohs


Ters

There are probably void pointers in Simutrans, as there is quite some low level stuff in there. There's even assembly code in Simutrans. Custom stuff to get things running as fast as possible. That kind of code is not suited for someone just starting to learn C++ (I'm not sure what knowledge you have in computer science), nor is it the kind of code one would write unless necessary.

isidoro

Quote from: Roads on October 14, 2012, 12:20:49 PM
C++ forbids incrementing a pointer of type void.
[...]

Not only it forbids it, it also makes no sense.  I'll explain it:  a pointer is a variable that holds a memory address.  For instance:

  int a; // An integer variable
  int *ip; // A pointer...
  ip=&a;   // ...that holds the address where a is stored


So, for instance, ip may hold the address 1024, where the data of a is located.

If I do: ip++; what is the address that is now in ip?

One is tempted to say the following address.  But that is wrong.  An integer in my machine needs 4 consecutive memory locations to be stored.  In this case, ip will point to the next integer, i.e., four positions ahead: 1024+4=1028.

Finally, if we have a void *, how many positions will the compiler advance?  It doesn't know...  That's the reason it is forbidden.

So a pointer is a memory address (a location if you want) and a surname, indicating what lays there.

Roads

Isidoro, when I began reading your post I was thinking, "I understand this stuff and it has been said, why is he saying it again?"  Then I got to the part about the following address.  I thought it would be 1025.  Thank you very much for explaining that.

Ters, what you said is good to know.  Hopefully the few things I want to do eventually will not involve void pointers and if it does no doubt I'll be posting my code if it is not too long asking y'all to take a look at it.

Ters

Another thing. Though pointers come technically unchanged from C, in C++ a pointer is a type of iterator, a concept that doesn't exist in C. This is-a relationship is no in a sense of class inheritance, but conceptually. There are other iterators that aren't pointers, but classes, usually one or two types associated with each container. Iterators can be used for moving forwards through a collection of items (by incrementing the iterator: ++iterator), getting the item at the current position (dereferencing it: item = *iterator), possibly moving backwards (by decrementing it: --iterator), and possibly skipping several items (by addition or subtraction: iterator += 7).

What an iterator can do depends on what kind of iterator it is, progressing for very simple iterators to more capable ones. Pointers are of the most capable kind, where you can move in both directions and skip several items in one go. The C++ library contains many utility functions and classes that accept certain kinds of iterators, of which pointers is a match.

Many other programming languages also have iterators, but while still used for moving through collections, I have not seen anyone behave like C++ iterators. Most languages don't have pointers either, just something similar called references. C++ also has this pointer-like thing called references, but having pointers, the references in C++ are a bit more special than references in languages like Java (but more like those in Fortran).

Roads

Ters, this is way beyond me now but I do appreciate the time you took to write and will likely be referring back to it at some point.  I've got this thread on my permanent links list.

You mentioned earlier you didn't know the extent of my programming knowledge.  I guess it would be kind of unusual nowadays but was pretty common when computers first became popular.  Lots of people like me bought a computer or else had access to one at work and learned Dbase.  From that some of us graduated to FoxPro and a few later on to Oracle.  At the time I worked for a large maintenance facility doing all kinds of inspection and testing work - ultrasound, mag particle, welding, coatings...

At the time the shops did everything the old fashioned way with pen and paper.  We kept the calibrated equipment due dates listed on a white board.  Time sheets were filled out by the foreman and sent to payroll.  Even the shop orders were kept in a binder.  I began writing applications to replace all that and quite a bit more stuff.  By the time I retired it was all done on the computer.  So my experience as far as low level programming is nil but as far as making use of a high level language it is extensive.

Markohs

Simutrans coding style recomends not using void pointers.

From documentation/coding_styles.txt

Quote
- Avoid void * if possible. This is especially dangerous when used for
  pointers to objects, because the compiler can't call the destructor of the
  object through a void pointer. Also all type checks are impossible on
  void *. Use of void* is tolerated in C code, but not in C++ code.
  -> try using templates instead of void pointers.

prissi

The most use of void simutrans does is when it uses the memory allocation in freelist. If you want to look at some pointer code, you could lok at dataobj/freelist.cc . But there are certainly more rewarding places to study.

Roads

Prissi, You can believe I will take your advice and only be looking at the more rewarding places. :)

I only wanted a basic understanding since it was covered in the tutorial and now I'm wondering why the author even bothered doing it and doing it half **** at that.

Roads

#66
This is the intro statement of an example tutorial:

QuoteHere you have an example that overloads the addition operator (+). We are going to create a class to store bidimensional vectors and then we are going to add two of them: a(3,1) and b(1,2). The addition of two bidimensional vectors is an operation as simple as adding the two x coordinates to obtain the resulting x coordinate and adding the two y coordinates to obtain the resulting y. In this case the result will be (3+1,1+2) = (4,3).

and here is the program:



1  // vectors: overloading operators example
2  #include <iostream>
3  using namespace std;
4
5  class CVector {
6  public:
7     int x,y;
8     CVector () {};
9     CVector (int,int);
10    CVector operator + (CVector);
11  };
12
13  CVector::CVector (int a, int b) {
14   x = a;
15   y = b;
16  }
17
18  CVector CVector::operator+ (CVector param) {
19  CVector temp;
20  temp.x = x + param.x;
21  temp.y = y + param.y;
22  return (temp);
23  }
24
25  int main () {
26    CVector a (3,1);
27    CVector b (1,2);
28    CVector c;
29    c = a + b;
30    cout << c.x << "," << c.y;
31    return 0;
32  }


Actually I sort of understand most of the program but one thing I don't have a clue about is "param."
If anyone can shed some light on this or say anything about the program it would help me greatly as even the things I understand I only vaguely understand...


Modify:  added line numbers

Ters

param is just the name for the parameter to the method called operator +, just like x is in f(x) = x+x.

When the compiler encounters the following program

Foo a, b, c;
a = b + c;

it will see if the second line can be transformed to

a = f(b, c);

to match some existing function f(x, y), or

a = b.f(c);

to match a method f(y) in class Foo except that the function or method isn't called f, but operator +.

Roads

Thank you, Ters

I'm sure I do not understand all you said but it is certainly helpful.

Let's see if I'm anywhere in the ball park or just wandering around trying to find the park.  It looks like in line 19, "temp" is declared as an object of CVector.  Then this function called "operator+" is accepting the values of "x" and "y" which in the first instance would be 3 and 1, and adding them because that is how the operation is declared for the class?

isidoro

In fact, it is quite simple.  As Ters pointed out, when you have:

26    CVector a (3,1);
27    CVector b (1,2);
28    CVector c;
29    c = a + b;

the last line is equivalent to:

29    c = a.operator+(b);

if that were legal in C++.  You just have to imagine that operator+ is just a funny name for a method in CVector.

Once you think that operator+ is just another method, all you are doing is calling it.  Variable param gets a copy of variable b, and variables x and y are just those properties of variable a.  Variable temp is only a placeholder where to build the return value before actually returning it.

By the way, return is not a function and, thus, the parenthesis can be dropped in line 22.  A matter of style...  8)

Roads

Thanks Isidoro.

Guys, I'm having a real hard time with this and one reason finally occurred to me.  It is because of all the application work I did with FoxPro and Oracle.  Sure those things gave me an understanding loops, arrays and some other stuff.  The problem is variables as I understood them and I don't think until now did I really understand that C++ is a whole different animal and I need to forget everything I ever knew about variables as defined by FoxPro and Oracle.  It seems like to me now there is only data in C++ and pointers to data.  Guess I'm thinking out loud.  At any rate maybe eventually this will make sense to me.

VS

You're spot on, Roads - with both observations :) And eventually it will make sense!

My projects... Tools for messing with Simutrans graphics. Graphic archive - templates and some other stuff for painters. Development logs for most recent information on what is going on. And of course pak128!

Ters

Makes me wonder what variables are in FoxPro.

While I risk confusing you more with this: A pointer in C and C++ is also itself a form of data. It can be viewed as simply a number. One can to arithmetic on it. Looking at it from the hardware side, it makes perfect sense. In the end, it's that way for all programming languages, as everything is numbers on a computer, but most of them hide this low level stuff from the programmer. But C, and C++ in turn, doesn't do much to hide the underlying mechanics, which has good and bad conseqences. C++ also has something it calls references, which can be thought of as a pointer, but doesn't really behave like one (from the programmers perspective). References in other languages are more like pointers in C/C++.

Roads

With your help (all of you), eventually or at least partial eventuality only took a couple days.  It seemed like a lot longer!  I have a much better understanding of this and something that also helped a lot was inserting a lot of cout into the code and watching how the program executed.

What you do in FoxPro is declare variables, say x=1.  If you ever say x=2, then x=1 is lost forever.  It is over written.  This made it real difficult to see that x could be equal to 3 and also later equal to 1 and the program remember both values.

No Ters you did not confuse me more.  I kinda understood pointers were data because you can increment them.  The tut sometimes mentions passing stuff by value which is almost always pretty clear and passing stuff by reference which is often pretty much unclear.  I have a feeling it is going to be awhile before I have a handle on this stuff enough that I can actually create something useful with it.

Ters

Quote from: Roads on December 07, 2012, 04:03:33 AM
What you do in FoxPro is declare variables, say x=1.  If you ever say x=2, then x=1 is lost forever.  It is over written.  This made it real difficult to see that x could be equal to 3 and also later equal to 1 and the program remember both values.

Sounds like it doesn't have scoping. That if you declare a variable, it is available from everywhere, whereas most other languages limit the variable to the scope it's declared in, and those scopes nested within that scope.

Roads

Yeah.  It has been a long time since I did any FoxPro and have forgotten a lot about it but there was no scope.  What I would always do is create programs and UDF's (user defined functions) to do specific things and call them as needed.

One thing I wanted to say about C++ and the data/pointers thing - is what I was thinking when I said C++ is only data and pointers - is that it seems the addresses of data is always saved and can be accessed with pointers.  As obvious as this appears now it was never stated in any tut I've read and with my back ground it was not at all obvious.

Ters

Quote from: Roads on December 07, 2012, 04:57:00 PM
One thing I wanted to say about C++ and the data/pointers thing - is what I was thinking when I said C++ is only data and pointers - is that it seems the addresses of data is always saved and can be accessed with pointers.

Data doesn't so much have an address that is saved, as the program needs the address for the data in order to access it. That's an inherent property of data on a computer (at least the kind we deal with here), but many (most) programming languages don't expose this to you. However, you can have data in C/C++ that doesn't have an address, or at least not in the sense that you can create a pointer to it. But then we're into low level hardcore optimization techniques.

Markohs

C++ is all about pointers and data, yep. It's a low level language after all.

isidoro

Quote from: Roads on December 07, 2012, 04:03:33 AM
[...]
The tut sometimes mentions passing stuff by value which is almost always pretty clear and passing stuff by reference which is often pretty much unclear.
[...]

The problem is, as Markohs points out, that C++ (and C) is a pretty much low level language.  The historical goal of C was to devise an assembly language independent of a concrete processor, so that you didn't have to rewrite entire software, especially OSes, each time you bought a new machine.

Passing by value/by reference is a clear example of that.  There isn't pass by reference in C.  There is only pass by value.  If you want pass by reference, you have to build it manually yourself.  That is, you have to pass (by value) a pointer (i.e. a memory address) so that the function/method can play with the bowels of the variable and, thus, modify it.

prissi

But C++ can be done without using pointers directly. You can even use garbage collection libraries. The power of C++ is the possibility to do low level as well as highly object oriented code ignoring pointer completly (apart from this object).

Roads

As odd as it might seem, What you guys are saying is helpful because all too often I want to say to heck with this.  As soon as I kind of understand one concept, the next is equally difficult.

Then y'all remind me I'm wrestling a bear, not playing with a puppy.  So thanks to everyone for the things you have said.

Roads

A couple of things - about pointers - this from one of the tut sites:

QuoteC++ offers two mechanisms for dealing with addresses:  references (&) and pointers(*).  Pointers are an older mechanism that C++ inherited from C, while references are a newer mechanism that originated in C++.   Unfortunately, many C++ library functions use pointers as arguments and return values, making it necessary for programmers to understand both mechanisms.

The other thing - I'm wondering if when working with arrays you guys use #include <vector> or I guess in the case of MSVC #include <apvector>?

asaphxiix

hey, I'm just starting a c++ tutorials on learn cpp.com. It's pretty nice so far, but I'm only at the beginning. I have no programming experience whatsoever. Started using MSVC Express, which is working out nicely so far.

Ters

Quote from: Roads on December 22, 2012, 12:51:13 AM
The other thing - I'm wondering if when working with arrays you guys use #include <vector> or I guess in the case of MSVC #include <apvector>?

I've never heard of apvector, and googling it doesn't yield much information about where it's from. They may not even be about the same apvector. One page mentions it as deprecated. One thing is certain: vector is standard C++. Whether apvector is a Microsoft extension, some 3rd party thing Microsoft ships with their compiler, or an old relic from some ancient C++, I can not tell.

Roads

#84
Ters, Thank you very much!  This was from the mathbits.com site.  When I tried to use some of the stuff they were using I got lots of errors.  It is good to know <vector> is standard C++.  From now on if it doesn't work with <vector> I'll just assume it is non standard and avoid using it.


Modify:  Hope you the best in your effort asa.  If XIIX is your age, then IMO, you are getting a very early start on this stuff - at least compared to me.

Roads

According to tut at learncpp.com which is the best I have found BTW, the following:


QuoteThe letter 'e' or 'E' is used to separate the two parts. Thus, a number such as 5e2 is equivalent to 5 * 10^2, or 500. The number 5e-2 is equivalent to 5 * 10^-2, or 0.05.


This all seemed obvious until I began playing around with it in code.



float x = 10e1;
cout << x << endl;
float y = 10^1;
cout << y << endl;



cout prints, in the first case 100, second case, 11.  Maybe I need to go back to first year high school algebra but I was thinking both cases should be 10. 

Ters

^ is not used for power in C++. No power operator exists. Other languages have it, and it is also used in plain text on computers where superscript is not supported.

10e1 is short for 10 x 101, which is 100. When using scientific notation (a x 10b), the absolute value of a should normally be less than ten.

Roads

Thank you Ters!  Often I feel like I'm barefoot in a blackberry patch and briars are everywhere.  For every bucket of berries I gather I donate so much blood. :(

Ters

In C, C++ and some other languages, ^ is the operator for bitwise xor. 10 ^ 1 = 1010b ^ 1b = 1011b = 11.

Roads

Ters!  OMG.  I can't pick the big juicy berries yet!  Not only are there briars in the blackberry patch but there are snakes as well.  xor sure looks like a snake to me.  That said, thank you for the post anyway as it is probably something I'll encounter someday.

Ters

XOR, like all other logical operators are quite simple. It's just remembering what the rule is for the name. The tricky part is remembering what random symbol is used for each operation in each programming language (I remember AND/&, OR/| and NOT/!, but had to look up what ^ means).

AND, OR and NOT is somthing you'll have to deal with relatively early on. XOR is more rare, more useful for clever tricks than normal human logic. Bitwise logical operators, where all the bits in a value are treated in parallel, are something that creeps up when dealing with bitfields, like ribi's in Simutrans.