Page 9 of 20

Re: The Thread for Programming

Posted: 18 Sep 2014, 05:27
by Ashan
So I made an attempt at translating my program into C++.
http://pastebin.com/c9aFBrbC

I had to look up how to get the length of an array and I'm not sure if there's a better way than the awkward solution I found online.

Code: Select all

int lengthOfWords = sizeof(words) / sizeof(words[0]) - 1;
I guess sizeof() gets you the size of the array in bytes so you have to divide it or something? I don't really know, someone explained it and I skimmed it so whatever.

Oh, also I barely know anything about runtime exceptions in Java in the first place, so I had NO idea what to do in C++ so I just didn't do that part.

Re: The Thread for Programming

Posted: 18 Sep 2014, 17:49
by WhattayaBrian

Code: Select all

static string words[]
static string numToStr(int num)
"static" is a pretty awful keyword in C++ due to its several unrelated uses. You don't need it here, as it doesn't accomplish anything that your program will care about. It means, in a nutshell: "only this file can use this function/variable, and no one else can, even if you use the 'extern' keyword". (This is called "internal linkage".)

In Java, these functions were part of a class. In that instance, the "static" keyword means "I do not need an instance of the class in order to call these functions/use these variables". They only exist once. Because the C++ versions are not in a class, the meaning is completely different.

Confusing!

Code: Select all

int lengthOfWords = sizeof(words) / sizeof(words[0]) - 1;
The "sizeof" operator (yes, it's an operator, just like + or -, but it cannot be overloaded) always does the exact same thing: gives you the number of bytes of the type of whatever you pass in (you can also just pass in a type: like sizeof(int)).

"words" here has a type of string[51] (the compiler automatically fills in that 51 based on the number of elements specified in the initializer list). This can be a bit surprising, that the number of elements is part of the type itself: that string[5] and string[6] are as different to the compiler as int and float are. (Of course they can both be intrinsically coerced to a string*, so perhaps they're not as different.)

The point remains: the sizeof(string[51]) is 51*sizeof(string), so if you divide by sizeof(string), they cancel out and you're left with 51. Can you see why sizeof(words[0]) is equivalent to sizeof(string)?

However, "lengthOfWords" is a very bad name here, because you're not storing the length of the words array, which is 51. You're storing 50. It should be named "maxNumber" or something.

Also--don't feel like you need to use exceptions to handle error cases, at least in C++. It is just one way to go about it, and many projects do not use them at all. UE3/UE4 don't.

Re: The Thread for Programming

Posted: 18 Sep 2014, 20:40
by WhattayaBrian
Yeah exceptions are somewhat...clunky. Though, that said, I should make it very clear that "structured exceptions" are completely different and one should be around the main loop of every real project. (It allows you to catch system exceptions like null pointer accesses.)

And STL containers are great, and I personally think the hate against them for "real" projects is completely unwarranted. They're super fast, and super well tested. They are remarkably slow in debug though, but you can turn that off if it's really hurting your dev cycle. Plus, everyone knows how to use them already. I really hate Unreal's TArray and FString types.

That said, I still think C++ programmers should know the ins and outs of raw arrays. They're important, and they never go away. Even in projects that use smart containers like std::vector or some replacement, no one ever really uses std::array. They probably should, but no one ever does.

C++14 should be adding dynarrays, but I have no idea when I'd ever use them.

Rambles!

Re: The Thread for Programming

Posted: 18 Sep 2014, 21:01
by Ashan
Thanks for the help!

Yeah, so I got rid of the "static"s and renamed the "lengthOfWords" integer to "maxNumber". And I'll definitely look into the smart pointers/smart arrays and whatnot sometime soon. I still don't know a ton about C++ syntax and proper etiquette, so I guess this is good for me as a learning experience.

Re: The Thread for Programming

Posted: 18 Sep 2014, 21:55
by WhattayaBrian
PSA: Please don't use shared_ptr. Use unique_ptr instead.

By using a shared_ptr you're declaring that this piece of data does not have an owner that is responsible for its destruction. This is a very dangerous paradigm to work under.

Thank you and have a nice day.

Edit: names are hard

Re: The Thread for Programming

Posted: 18 Sep 2014, 22:09
by devil†zukin
do you mean shared_ptr?

Re: The Thread for Programming

Posted: 18 Sep 2014, 22:11
by WhattayaBrian
Whoops. Good catch.

Re: The Thread for Programming

Posted: 18 Sep 2014, 22:25
by WhattayaBrian
Of course. It's a tool in your toolbox. It, like goto, has its place sometimes.

But the addition of rval refs and unique_ptr means it's much harder to find those places. And code bases that use shared_ptr haphazardly are extremely difficult to work in. It's like spaghetti code, but it's more like...spaghetti ownership?

Re: The Thread for Programming

Posted: 20 Sep 2014, 03:57
by WhattayaBrian
That's pretty cool!

While I would never suggest premature optimizing, I do feel it's prudent to point out that all of your range-based for loops should be either const refs or refs so you don't do a bunch of needless copies (especially in buildStateMap where you're copying the list each recursion).

Re: The Thread for Programming

Posted: 20 Sep 2014, 04:03
by devil†zukin
that's probably a good idea

i've been using java a lot lately lol

Re: The Thread for Programming

Posted: 20 Sep 2014, 15:12
by docopoper
Man. I haven't posted in this topic in a while. Mostly because debugging this stupid thing I'm working on is so freaking hard! It's one of those bugs where no matter how hard you look everything seems right.

If I can get this working though it'll be cool and I'll post it. I'm making the ability to have dynamically morphing collision meshes that will push each other apart. This will let me do things like have rotating blocks in a platformer at the simplest and crazy things like blocks rippling in a sine wave at the other end.

Hopefully implementing this won't end up crushing my brain any more than it already has. :D

Re: The Thread for Programming

Posted: 20 Sep 2014, 16:17
by SAJewers
Ooh. Can't wait to see that. I actually had an idea come to me this morning of a pltformer where you had to manipulate platforms and blocks to make the player reach the end. Kinda wish I took up programming in College.

Re: The Thread for Programming

Posted: 20 Sep 2014, 18:39
by docopoper
If you wish you'd taken up programming then take up programming. College isn't necessary for that at all since pretty much everything you will ever need is on the internet. Just go and look up some tutorials.

Python is my favourite language. :D I't just plain fun to use.

Re: The Thread for Programming

Posted: 21 Sep 2014, 05:34
by Ashan
So I just watched a thing on the unary scope resolution operator in C++ and to clarify:
is it basically just the C++ equivalent of "this" in Java? Cause that's what it seemed like to me.

Like, when you have 2 variables of the same name, one in and one outside a class and you want to set the one equal to the other in Java, you would do like
this.x = x;
And it seems like that's a similar thing to the :: thing? I think?

Re: The Thread for Programming

Posted: 21 Sep 2014, 05:53
by WhattayaBrian
Actually, "this" is the C++ equivalent of "this" from Java. :)

Scope resolution is all about names.

The dot operator is all about instances.

Example:

Code: Select all

namespace First
{
	int x; //global
}

namespace Second
{
	int x; //global
}

class Third
{
public:
	int x; //instanced
	static int y; //not instanced
};

int main()
{
	// First::x exists only once under this name.  You cannot make additional First::x's
	First::x = 0;
	
	// Second::x additionally exists only once and cannot be recreated.  However, this one is distinct from First::x due to having a different name
	Second::x = 1;
	
	// This is a compile error!  Third::x is the name of that variable, but it cannot be accessed this way as it is created with each instance of the class
	// Third::x = 2;
	
	// But this is fine.  See here we use the dot operator to access the x specifically made for myThird
	Third myThird;
	myThird.x = 3;
	
	// And here's a completely different x made for a different Third instance, once again accessed through the dot operator
	Third myOtherThird;
	myOtherThird.x = 4;
	
	// However, y is "static", which means it exists outside of any individual instance of Third.  We access this by name
	Third::y = 5;
	
	return 0;
}

Re: The Thread for Programming

Posted: 22 Sep 2014, 02:48
by Ashan
Thanks!

Oh, also I found out recently that Apple has its own, free IDE for OSX called Xcode and it's pretty nice.
WAY nicer than CodeBlocks, in the very least.
I messed around with it for a bit today and figured out some basic stuff in C++ I still didn't know. Mainly putting functions in other .cpp files and passing things between those functions.

Coming from Java, the header files seem like a silly extra step that's kind of a pain, but I guess it's probably more convenient for managing visibility of all of your functions? I'm just assuming that's the case, I don't really know cause I've never made a "legit" project where I'd have to do something like that.

For most of the object making stuff and whatnot, I've been able to feel my way through with my Java knowledge since it seems as if Java took a lot of cues from C++.

Re: The Thread for Programming

Posted: 22 Sep 2014, 02:55
by sonicspin
headers are for class management
cpps are for methods (class functions) &&/|| function management
I've always been afraid to use them tho

Re: The Thread for Programming

Posted: 22 Sep 2014, 03:56
by WhattayaBrian
Headers suck.

They're 100% necessary, but they suck nonetheless. C++ headers were inherited wholesale from C, which is a very old language.

The idea behind them was sound: we needed a way to enable files ("translation units") to use stuff defined elsewhere. Put another way, we want to separate declaration from definition. So, if you had a global int called x that you wanted every file to be able to see and manipulate, you'd do something like this:

Code: Select all

//x_is_only_defined_here.cpp
int x;

Code: Select all

//include_this_to_see_x.h
extern int x;

Code: Select all

//main.cpp
#include "include_this_to_see_x.h"

int main()
{
	// manipulating our global x
	x = 5;

	return 0;
}
You can do this with functions too, though the syntax is slightly different.

There's some really complicated concepts in this discussion, so for the sake of simplicity, I'll just say that humans are really bad at this, and that module-based systems like C# are so much better.

Complicated concepts:
When you build a project, you're actually doing a bunch of different operations, but we'll only talk about three:

1. Preprocess
2. Compile
3. Link

Preprocess

The preprocessor, well, "processes" all of your source files prior to actually handing them off to the C/C++ compiler. Any line that begins with a pound sign ("#") is a preprocessor directive. It is not C/C++! By far the most common directive is #include. All it does is take the file it finds and pastes it wholesale into whereever the directive was. That's it. It doesn't know a thing about headers, it's just a strict text replacement. You can #include a cpp file if you're so inclined (and this is done on occasion).

Compile

We use the word "compile" to refer to this whole series of steps. But, strictly speaking, it is one distinct step. The compiler runs through all your source files individually, and makes sure they make syntactic sense, then generates most of the bytecode for the instructions, before passing them off to the linker. This guy makes sure you have all your semicolons in the right places, and is where most of your warnings hail from (like "using uninitialized variable"). The compiler needs to be able to resolve every identifier. Read that part again, because that is why we need headers. If the compiler sees an identifier that has not yet been declared in that translation unit (file), that's an error. The compiler will not let you proceed. This is why we need declarations. Declarations are a promise to the compiler: "There exists a function that returns an int and takes two ints and is called "max" somewhere else in the project. Trust me." This would be the line "int max(int x, int y);" It doesn't need the body, since it's just a promise.

The compiler generates an intermediary file for each translation unit that the linker can consume. In visual studio these are called object files and have a file extension of ".o". They are named based on the original source file: "main.cpp" would generate a "main.o". These are then all passed to the linker.

Link

This guy takes all of those promises and holds you to your word. It finds where "int max(int x, int y)" is actually defined, then it takes that function address and replaces it in all of the object files where max is being referenced, so that when it's actually called, execution correctly proceeds to the bytecode for max's definition. It then "stitches" all the object files together into an exe/dll/lib/whatever you're making. If you fail a promise, you get some of the worst error messages known to man. I suggest you try it for yourself and see, just declare a function that doesn't exist and try to use it.

This has all been heavily simplified, and it's up to each individual compiler manufacturer to determine how they generate the final artifact (exe/dll/lib/etc), but it should give you an idea of how it's generally done.

So, basically, headers are there to batch a bunch of promises to each file so we don't have to write them out more than once.

Re: The Thread for Programming

Posted: 22 Sep 2014, 10:16
by docopoper
Oh. So that's what linking is. Ok. I always thought that that was part of compiling and that linking was some other weird thing.

Why can't header files be automatically generated though? Like if they made #include import all the definitions from a source file and something like #import paste the whole source file in. I know it would break the modularity they've got going where the preprocessor doesn't know the syntax but damn it would be so much less of a pain.

Re: The Thread for Programming

Posted: 22 Sep 2014, 16:14
by Ashan
Couldn't the IDE just generate them instead of building the auto-generation into the build process itself?

Re: The Thread for Programming

Posted: 22 Sep 2014, 18:02
by WhattayaBrian
So, the concept of the separation of declaration/definition (also known as interface vs implementation) is great and foundational to all modern programming.

The problem is implementing such a system via #include (and the fact that C++ doesn't allow for partial classes, but that's relatively minor by comparison). It means you cannot guarantee that different translation units won't get different versions of your types, due to preprocessing.

Code: Select all

// first.h

#pragma pack(push, 1)

// my types

//whoops, forgot my pop!

Code: Select all

// second.h

// normal stuff that doesn't care about packing

Code: Select all

// main.cpp

#include "first.h"
#include "second.h" // uh oh, now second's declarations are totally out of whack with the rest of the program!  This will compile fine, but prepare for segfaults!
Due to the vast complexity and sheer magnitude of real projects, shit like this happens all the time, and it's incredibly difficult to figure out. It looks like modules will fix this, but I'll remain cynical until we get our hands on it. :D

Re: The Thread for Programming

Posted: 22 Sep 2014, 21:11
by Ashan
Got my first assignment today. It was pretty simple, just a thing that converts tons to a bunch of different units.

I spent more time [double and triple checking everything to make sure I'm not submitting a corrupt file or something, making sure I added as much documentation as possible, and making sure the photo is a jpg even though he didn't specify it had to be one] than it took to write the program itself.

e: that last sentence is like sentence gore. I'm adding square brackets to help make sense of it.

Re: The Thread for Programming

Posted: 22 Sep 2014, 23:29
by WhattayaBrian
You're turning in an image for a beginner programming assignment?

Re: The Thread for Programming

Posted: 22 Sep 2014, 23:41
by Ashan
Hahaha, oh yeah, I should have explained that.

For assignment submissions, you send your .cpp file and either a screenshot of an example input/output, or a .txt file with the log. I did the screenshot cause I don't know, it was fast and easy.

Re: The Thread for Programming

Posted: 22 Sep 2014, 23:45
by Ashan
Because I was on my laptop and I know the hotkey for screenshots and couldn't recall the name of the stupid little notepad equivalent in OSX and didn't want to spend all of 5 seconds looking for it.