Understand C/C++ like a pro (compilation of my explanations) 04-16-2012, 08:39 PM
#1
Hi there,
Over the time, I explained a few things about the innards and outards of the C/C++ language in various topics, but because this information may be valuable to these who seek to understand this language better, I decided to compile it into a single topic and polish a bit (rewrite some parts, add some new), that I'll maintain over the time (add more stuff). I packed the various parts into spoilers for your convenience, just expand the topic you're interested in. If you wish for me to explain something else, feel free to ask.
---------------------------------------------------------------------------------------------------------
Some basic questions - what languages are, what do you need for C/C++ and others and more - introduction
---------------------------------------------------------------------------------------------------------
How C and C++ relate - which one should you learn? What are they good for?
---------------------------------------------------------------------------------------------------------
Using C-strings in a switch
---------------------------------------------------------------------------------------------------------
Fractional numbers in C/C++ - learn the difference between integer and floating point math
---------------------------------------------------------------------------------------------------------
Comparing strings in C/C++ and how null terminated strings are handled by the language and preventing program errors when loading strings
---------------------------------------------------------------------------------------------------------
Writing better code - Name your variables/classes/functions properly
---------------------------------------------------------------------------------------------------------
Strings in C versus C++
---------------------------------------------------------------------------------------------------------
How cout and iostream work - brief introduction to operator overloading
---------------------------------------------------------------------------------------------------------
Writing a keylogger like real programmer (requires thinking!)
---------------------------------------------------------------------------------------------------------
Assembler in C/C++
---------------------------------------------------------------------------------------------------------
Beginner mistakes broken apart (includes sources of corrections)
---------------------------------------------------------------------------------------------------------
Understand iterative, recursive and dynamic calculations.
Over the time, I explained a few things about the innards and outards of the C/C++ language in various topics, but because this information may be valuable to these who seek to understand this language better, I decided to compile it into a single topic and polish a bit (rewrite some parts, add some new), that I'll maintain over the time (add more stuff). I packed the various parts into spoilers for your convenience, just expand the topic you're interested in. If you wish for me to explain something else, feel free to ask.
---------------------------------------------------------------------------------------------------------
Some basic questions - what languages are, what do you need for C/C++ and others and more - introduction
Spoiler:
C++ or VB.Net (and many others) are a programming languages: it's a set of rules that describe how to write something meaningful, how to communicate with the computer and tell it what it should do. It's similar to English for example, you have grammar and vocabulary, that defines the rules of communication. In this case, you communicate with the computer using the programming language, you tell computer what to do: perform various operations, draw stuff on the screen, communicate over network, generate sound, perform some operations with files... a lot of stuff. You use the programming language to describe how to do these things.
However, computer doesn't understand this language directly. Instead, there is a program called compiler, which understands the programming language too. It will read what you wrote and "convert" it to a machine code - set of numeric codes, that the computer understands - it's basically some program that you can execute (run) and that will do things, that you told it to, using the language.
You're certainly using many programs: your own operating system, web browser, games, text editors: everything you use on your computer was created using programming languages and you can use the language to create your own programs.
Programming language like C++ or VB.Net makes it easier to create programs, because you don't need to know these numeric codes that computer understands. Instead you need to know just the language which is a lot simpler and the compiler program will generate these codes for you (you don't even need to know about them, you'll get a program that you can run as the result).
C++ is also general purpose, meaning that you can create all kinds of programs in it (this also answers part of question 2 I think) from simple tools, over complex applications or games or even device drivers and operating systems.
There are however some specialized languages, that might for example allow only some mathematical tasks, but you can't create a game with them for example. Programmers often know several programming languages and use the most suitable one for given task.
)Technically to use most languages you need just some text editor (for example notepad, but not Word or Writer with formatted text (fonts, colors and that sort of stuff)!) and a compiler (you need to download compiler for a specific language). You use the text editor to write the code according to the rules of the C++/VB.Net/anything-else language (these rules you need to learn) and then give it to the compiler tool, which will create a program from it.
In case of interpreted languages, you don't need to compile them, you just give the source to some interpreter and it will perform the instructions you wrote.
However, it's way better to use some development environment called IDE, which basically does the same, but handles a lots of tasks for you and provides various tools to make the programming simpler, faster and less error prone. For example, Microsoft provides IDE's both for C++ and VB.Net and also C# (and some others) for free: Look for Visual Studio Express 2010.
If you were wondering, what's the easiest language to learn... well it's very difficult question. Firstly, it's matter of individual perception, one person might find one language easier than the other one does. Additionally, there exist very simple education languages, that are very easy to learn, but are basically useless for practical purpose. So considering practical usage, you might try VB.Net which is very popular (even here, so it might be the best choice) and it's simpler, because it's derived from old language BASIC, which was made so people can learn programming easily, or (Object) Pascal (one of its dialects is known also as Delphi), which was also created for education purposes, but it got very popular even in practical usage. Another interesting tool is Python, which will force you to write a properly formatted code.
However, what's the most important thing, is to learn how to think algorithmically, that is, how to transfer your thoughts, actions and solutions to problems into a computer code - algorithm. That should be independent of programming paradigm, for example the OOP you mentioned, which is just one of many. In fact, that's not entirely true. Just making your thinking process object oriented is useless, unless you know how to algorithmize as well and it's not true at all, that you have to think in OOP for C. That applies only for C++, because C doesn't have any OOP.
Also, it's not true that languages are different only in syntax (that is, semantic rules you use to write your code). Many similar languages also differ in provided features that can be used when writing your code. There's much more important difference in how the actual language works and what's its purpose.
For example, two languages, for example C++ and C# have very similar syntax, but there's a lot of important difference even in how some simple expressions are handled. C++ is quite weakly typed and more low level, so it might permit things that C# doesn't, not to mention that the machine (or intermediate) code generated for the same operation is also quite different, for example C# performs a whole set of additional checks.
C# and C++ also handle strings a lot differently. In C# they're dynamically allocated objects, while standard C++ null terminated strings are much more low level, they're simply series of data of certain datatype, that is operated upon using pointers. While something similar happens under the hood of C#, programmer is pushed further from this behavior because of abstraction.
It's also important to understand how the language, or rather the generated code, works. C++, Java and C# share a lot of syntax and they're very similar to each other from the syntax viewpoint (though of course they differ somewhat in it), however they different significantly: C++ produces a native machine code for given architecture, Java produces a bytecode ("universal" virtua machine code) that's usually interpreted in JVM, while C# produces CIL "machine code" packaged into assembly, which is JIT compiled into native code for given platform just prior to the execution.
Thus it's incorrect to say that all that's different is the syntax. There's much more to each language than its syntax and good programmer must be aware of such differences, because one of the most important tasks when developing a project is to choose the best language for given task.
How long it will take you to learn some language almost impossible to say. It depends on what language you are learning, what do you already know about computing (knowledge of other languages and other related things can speed up the process a lot) and how fast you learn (various people need various amounts of time).
Not to mention, programmers continuously learn something new, so it's not like you would ever stop learning anyway, but to get a firm grasp of the language... like I said, it could take a few weeks or a few years, it depends on a lot of things, but you'll always need patience and give your time to learn the language and also to use it for projects, experiments and such, so you better understand how it works.
However, computer doesn't understand this language directly. Instead, there is a program called compiler, which understands the programming language too. It will read what you wrote and "convert" it to a machine code - set of numeric codes, that the computer understands - it's basically some program that you can execute (run) and that will do things, that you told it to, using the language.
You're certainly using many programs: your own operating system, web browser, games, text editors: everything you use on your computer was created using programming languages and you can use the language to create your own programs.
Programming language like C++ or VB.Net makes it easier to create programs, because you don't need to know these numeric codes that computer understands. Instead you need to know just the language which is a lot simpler and the compiler program will generate these codes for you (you don't even need to know about them, you'll get a program that you can run as the result).
C++ is also general purpose, meaning that you can create all kinds of programs in it (this also answers part of question 2 I think) from simple tools, over complex applications or games or even device drivers and operating systems.
There are however some specialized languages, that might for example allow only some mathematical tasks, but you can't create a game with them for example. Programmers often know several programming languages and use the most suitable one for given task.
)Technically to use most languages you need just some text editor (for example notepad, but not Word or Writer with formatted text (fonts, colors and that sort of stuff)!) and a compiler (you need to download compiler for a specific language). You use the text editor to write the code according to the rules of the C++/VB.Net/anything-else language (these rules you need to learn) and then give it to the compiler tool, which will create a program from it.
In case of interpreted languages, you don't need to compile them, you just give the source to some interpreter and it will perform the instructions you wrote.
However, it's way better to use some development environment called IDE, which basically does the same, but handles a lots of tasks for you and provides various tools to make the programming simpler, faster and less error prone. For example, Microsoft provides IDE's both for C++ and VB.Net and also C# (and some others) for free: Look for Visual Studio Express 2010.
If you were wondering, what's the easiest language to learn... well it's very difficult question. Firstly, it's matter of individual perception, one person might find one language easier than the other one does. Additionally, there exist very simple education languages, that are very easy to learn, but are basically useless for practical purpose. So considering practical usage, you might try VB.Net which is very popular (even here, so it might be the best choice) and it's simpler, because it's derived from old language BASIC, which was made so people can learn programming easily, or (Object) Pascal (one of its dialects is known also as Delphi), which was also created for education purposes, but it got very popular even in practical usage. Another interesting tool is Python, which will force you to write a properly formatted code.
However, what's the most important thing, is to learn how to think algorithmically, that is, how to transfer your thoughts, actions and solutions to problems into a computer code - algorithm. That should be independent of programming paradigm, for example the OOP you mentioned, which is just one of many. In fact, that's not entirely true. Just making your thinking process object oriented is useless, unless you know how to algorithmize as well and it's not true at all, that you have to think in OOP for C. That applies only for C++, because C doesn't have any OOP.
Also, it's not true that languages are different only in syntax (that is, semantic rules you use to write your code). Many similar languages also differ in provided features that can be used when writing your code. There's much more important difference in how the actual language works and what's its purpose.
For example, two languages, for example C++ and C# have very similar syntax, but there's a lot of important difference even in how some simple expressions are handled. C++ is quite weakly typed and more low level, so it might permit things that C# doesn't, not to mention that the machine (or intermediate) code generated for the same operation is also quite different, for example C# performs a whole set of additional checks.
C# and C++ also handle strings a lot differently. In C# they're dynamically allocated objects, while standard C++ null terminated strings are much more low level, they're simply series of data of certain datatype, that is operated upon using pointers. While something similar happens under the hood of C#, programmer is pushed further from this behavior because of abstraction.
It's also important to understand how the language, or rather the generated code, works. C++, Java and C# share a lot of syntax and they're very similar to each other from the syntax viewpoint (though of course they differ somewhat in it), however they different significantly: C++ produces a native machine code for given architecture, Java produces a bytecode ("universal" virtua machine code) that's usually interpreted in JVM, while C# produces CIL "machine code" packaged into assembly, which is JIT compiled into native code for given platform just prior to the execution.
Thus it's incorrect to say that all that's different is the syntax. There's much more to each language than its syntax and good programmer must be aware of such differences, because one of the most important tasks when developing a project is to choose the best language for given task.
How long it will take you to learn some language almost impossible to say. It depends on what language you are learning, what do you already know about computing (knowledge of other languages and other related things can speed up the process a lot) and how fast you learn (various people need various amounts of time).
Not to mention, programmers continuously learn something new, so it's not like you would ever stop learning anyway, but to get a firm grasp of the language... like I said, it could take a few weeks or a few years, it depends on a lot of things, but you'll always need patience and give your time to learn the language and also to use it for projects, experiments and such, so you better understand how it works.
---------------------------------------------------------------------------------------------------------
How C and C++ relate - which one should you learn? What are they good for?
Spoiler:
If you learn C++, you'll basically also learn C, because it's a subset of C++.
Generally C++ is like C extended with object oriented programming, though there are also some subtle differences in the C subset of the C++, but nothing major. This also makes C++ backwards compatible: most C programs are also valid C++ programs.
If you're interested about reverse engineering and disassembling, then pure C might be easier because of less bloat. Also C still might be preferred when programming some embedded devices with very limited resources, but I guess you're going to program PC's. And like I said, if you learn C++, you'll also know C's syntax (because it's part of C++) so it won't be a problem in the future.
It's very powerful general purpose programming language, that's closer to the machine code than many other high level programming languages, but that also makes it more difficult to master and more error/bug-prone, but again, gives you a lot of power over your program and high performance.
Python might be more useful for beginners and smaller projects, because it's easier to use and its syntax enforces good code indentation which increases readability of the code, while in C/C++ code indentation and organization is purely optional.
It's also good to learn both languages (though probably one at the time), but once you know one of them, you can adopt the other one much faster, because you'll find a lot of constructs familiar (I'm not sure now if you already know some programming language).
Generally C++ is like C extended with object oriented programming, though there are also some subtle differences in the C subset of the C++, but nothing major. This also makes C++ backwards compatible: most C programs are also valid C++ programs.
If you're interested about reverse engineering and disassembling, then pure C might be easier because of less bloat. Also C still might be preferred when programming some embedded devices with very limited resources, but I guess you're going to program PC's. And like I said, if you learn C++, you'll also know C's syntax (because it's part of C++) so it won't be a problem in the future.
It's very powerful general purpose programming language, that's closer to the machine code than many other high level programming languages, but that also makes it more difficult to master and more error/bug-prone, but again, gives you a lot of power over your program and high performance.
Python might be more useful for beginners and smaller projects, because it's easier to use and its syntax enforces good code indentation which increases readability of the code, while in C/C++ code indentation and organization is purely optional.
It's also good to learn both languages (though probably one at the time), but once you know one of them, you can adopt the other one much faster, because you'll find a lot of constructs familiar (I'm not sure now if you already know some programming language).
---------------------------------------------------------------------------------------------------------
Using C-strings in a switch
Spoiler:
C/C++ doesn't even support string datatype natively. What it uses are basically arrays of datatype char, terminated with a null character (basically equal to zero). In case of C++, there's a String class in the STL library, which is part of C++ standard, this is however still a library, therefore can't be mixed with the language construct themselves like that.
Keep in mind, that C/C++ are very close to machine language, they are more low level languages than other languages you may now, so they provide less level of abstraction - meaning what some language can do for you (like switch with a string), you have to do it for yourself, as it's something that can't be done directly on the most contemporary hardware.
C/C++ switch needs to be used with a number, which the processor can work with directly. So if you have for example this:
It will get translated into something like this (it's a simple assembly, JNE - Jump Not Equal and CMP - Compare):
Notice the CMP (compare) instructions, that work with numbers. They can't work with a string, because even the most simple type of string is an array of arbitrary size in the memory and I can't remember any specific processor that could work with them natively.
So what is needed to do, is to somehow convert the string to a number. This can be done in C/C++ as following:
The Solution
You basically need to make an list of strings that you expect and make an enumeration with appropriate names for expected strings. Then define a function, that will translate the input string into the number, that corresponds with your enumeration - enumeration names correspond to a integer number, so they can be used with a switch.
This is a working C++ example, using standard C++. If you have any further questions, asks, feel free to alter it to suit your needs and use in any projects.
Keep in mind, that C/C++ are very close to machine language, they are more low level languages than other languages you may now, so they provide less level of abstraction - meaning what some language can do for you (like switch with a string), you have to do it for yourself, as it's something that can't be done directly on the most contemporary hardware.
C/C++ switch needs to be used with a number, which the processor can work with directly. So if you have for example this:
Code:
switch(a)
{
case 3:
...
break;
case 8:
...
break;
default:
...
}Code:
CMP 3, [a]
JNE case_8
...
JMP end_switch
case_8:
CMP 8, [a]
JNE case_default
...
JMP end_switch
case_default:
...
end_switch:So what is needed to do, is to somehow convert the string to a number. This can be done in C/C++ as following:
The Solution
You basically need to make an list of strings that you expect and make an enumeration with appropriate names for expected strings. Then define a function, that will translate the input string into the number, that corresponds with your enumeration - enumeration names correspond to a integer number, so they can be used with a switch.
This is a working C++ example, using standard C++. If you have any further questions, asks, feel free to alter it to suit your needs and use in any projects.
Code:
#include <iostream>
#include <istream>
using namespace std;
// List if strings you want to decode, in textual form
char *input_strings[] =
{
"COPY",
"MOVE",
"BURP",
"HUG",
"GLOMP",
"EXIT"
};
// List of corresponding names for strings you want to decode, MUST match intput_strings
enum decoded_string
{
strCOPY,
strMOVE,
strBURP,
strHUG,
strGLOMP,
strEXIT,
strTERMINATOR // MANDATORY! Must be always at the end of the list and must be always there
};
// decode function - goes trough input_strings and matches it to the input string
decoded_string DecodeString(char *input_string)
{
int i;
for(i = 0; i < strTERMINATOR; ++i)
if(!strcmp(input_string, input_strings[i]))
break;
return (decoded_string)i;
}
int main()
{
char input[256];
// infinite loop, not the best solution but... ah well :P
for(;;)
{
cout << "Enter command: ";
cin.getline(input, 256); // get the user input
// Tamtadadada! Using string with switch? Miracles? Nah, just Frooxius was here x3
switch( DecodeString(input) )
{
case strCOPY:
cout << "Copy what? Where?! I'm confused AAAAARGH\n";
break;
case strMOVE:
cout << "No. YOU move.\n";
break;
case strBURP:
cout << "Ewww, that's disgusting :-/\n";
break;
case strHUG:
cout << "YAAAAY! Hugs! ^^\n";
break;
case strGLOMP:
cout << "*glomps the user*\n";
break;
case strEXIT:
cout << "BYEEEEE\n";
return 0;
default:
cout << "I'm not sure what you mean by that...\n";
break;
}
}
}---------------------------------------------------------------------------------------------------------
Fractional numbers in C/C++ - learn the difference between integer and floating point math
Spoiler:
Given code:
You won't obtain correct result, because what you used in the expression are integer literals, so integer math was performed - it's way faster, but doesn't support fractions - all the parts after the decimal points are "cut off" (they're not even calculated in the first place). To solve this, simply use double literals:
Literal is a fixed value that you type in your program, like a number or a string and by the way it's written, the compiler determines what datatype it is. In order for it to handle it like a fractional number, you need to write it like one, even if the fractional part is zero. Remember that C/C++ won't do more calculations for you than necessary, so if you give it only integer numbers, it will perform integer math - no fractions. This way, you basically force it to use fractional numbers.
Also, double is kind of unnecessary, float has enough precision for this - don't waste space and performance. You can use float literals:
Code:
double y;
y = (1/5) + (2/8);
cout << y; // will print 0Code:
double y;
y = (1.0/5.0) + (2.0/8.0);
cout << y; // will print 0.45Also, double is kind of unnecessary, float has enough precision for this - don't waste space and performance. You can use float literals:
Code:
float y;
y = (1.0f/5.0f) + (2.0f/8.0f);
cout << y; // will print 0.45---------------------------------------------------------------------------------------------------------
Comparing strings in C/C++ and how null terminated strings are handled by the language and preventing program errors when loading strings
Spoiler:
While you technically can use the equality test == operator with null terminated strings (referred to as "C strings" here), which is basically an array of characters (datatype char), with a null character (nothing else but a zero byte) indicating the end, but it doesn't have the meaning you would probably expect.
When a compiler encounters a string literal (simply, any specification of a string like "mystring"), it will store the contents in a string table and the literal will be basically evaluated as a pointer to character array (char *) and you can use == operator on two pointers, however it will be true only if both compared strings are stored at the same address of the memory.
That of course means, that they're will be always the same, however, it doesn't mean that in every case that two null terminated strings are same, that they are at the same position in memory. If you create an array for your own string and you are comparing it to a string stored in a string table, so even in case though both strings are same (contain same text), they are stored in different places of the memory, therefore == operator will tell you that they're not the same, because it compares their addresses, not their contents.
You can use the strcmp function to compare two strings like this:
! inverts the value and strcmp returns zero (false) if they are equal, so you can simply invert it, so it becomes true and in case they are not identical, true becomes false.
When you want to load user input into an array you made, this is a very bad way to do it:
Although it usually works for you, this is a very bad thing to do. If made the array with size of 20 elements, minus the null character, it can store 19 characters. So what if user types 25? 30? More?
Remember that C++ does very little safety checks for you, so it won't even test if you're accessing the array beyond its end. C++ is very close to machine code, so the cin object just gets a pointer to some location in memory, where is the array stored, however it doesn't get any information about size, so it simply writes data there as long as it can. And in case user types 25 characters, it will actually write some data beyond your array, so it overwrites some other data in the memory, which can cause very weird behavior, crash your program and sometimes crash even some less stable OS (but you're unlikely to encounter that last example nowadays).
Proper way to do this is following:
It stores only up to 20 characters (including the null character, so 19 regular characters) in the memory area pointed by Array, so if user writes more, it won't crash the program.
When a compiler encounters a string literal (simply, any specification of a string like "mystring"), it will store the contents in a string table and the literal will be basically evaluated as a pointer to character array (char *) and you can use == operator on two pointers, however it will be true only if both compared strings are stored at the same address of the memory.
That of course means, that they're will be always the same, however, it doesn't mean that in every case that two null terminated strings are same, that they are at the same position in memory. If you create an array for your own string and you are comparing it to a string stored in a string table, so even in case though both strings are same (contain same text), they are stored in different places of the memory, therefore == operator will tell you that they're not the same, because it compares their addresses, not their contents.
You can use the strcmp function to compare two strings like this:
Code:
if (!strcmp(arrayUsername, "UserName") && !strcmp(arrayPassword,"secret"))! inverts the value and strcmp returns zero (false) if they are equal, so you can simply invert it, so it becomes true and in case they are not identical, true becomes false.
When you want to load user input into an array you made, this is a very bad way to do it:
Code:
std::cin >> arrayUsername;Remember that C++ does very little safety checks for you, so it won't even test if you're accessing the array beyond its end. C++ is very close to machine code, so the cin object just gets a pointer to some location in memory, where is the array stored, however it doesn't get any information about size, so it simply writes data there as long as it can. And in case user types 25 characters, it will actually write some data beyond your array, so it overwrites some other data in the memory, which can cause very weird behavior, crash your program and sometimes crash even some less stable OS (but you're unlikely to encounter that last example nowadays).
Proper way to do this is following:
Code:
cin.get(Array, 20);---------------------------------------------------------------------------------------------------------
Writing better code - Name your variables/classes/functions properly
Spoiler:
One common newbie error is naming variables like Variable1, Variable2 and so on:
DON'T name variables as Variable1 or Variable2, it's a very bad habit and it will lead to unreadable, incomprehensible code. Imagine if you write something larger and then you'll have Variable38 and Variable45 there. Would you remember what are they for and why are they there?
Their name should briefly describe what they are for, what's their purpose, also it's good idea to follow a convention and start their names always with a lowercase letter. So instead of
Make it
DON'T name variables as Variable1 or Variable2, it's a very bad habit and it will lead to unreadable, incomprehensible code. Imagine if you write something larger and then you'll have Variable38 and Variable45 there. Would you remember what are they for and why are they there?
Their name should briefly describe what they are for, what's their purpose, also it's good idea to follow a convention and start their names always with a lowercase letter. So instead of
Code:
char Array[20];
char Array2[20];Code:
char username[20];
char password[20];---------------------------------------------------------------------------------------------------------
Strings in C versus C++
Spoiler:
First, while strings in C are called either null terminated strings or "C strings", there are no "C++ strings". C++ has built in null terminated strings (which are the C strings) just like C, however, it has additionally STL strings, they are part of the STL library, that became part of C++ standard, however it's still a library, support for these strings is not integrated into C++ itself. They actually use Cstrings internally, but add a lot functionality. You can use relational operators (==, >=, <=, <, >) with them, you don't need to use quite ugly .compare method for simple comparing or the strcmp like in C. C++ allows this because of operator overloading, which allows to change meaning of an operator with respect of some class.
So following code will work just fine and dandy:
However, this IS a reason to use Cstrings. STL strings add additional overhead, various runtime checks, plus they are allocated dynamically from the heap and have much more memory footprint. Using them when they're not needed, especially in C++ which is often chosen as high performance language, is quite a dirty and bad habit. Plus like I said, these strings are provided as an library, albeit they are part of the standard, they are not part of the language itself, null terminated strings however are.
Additionally, null terminated strings are very often used to store arbitrary binary data, working as an buffer, because the char type corresponds to a single byte.
So following code will work just fine and dandy:
Code:
string myString0, myString1;
cin >> myString0;
cin >> myString1;
if(myString0 == myString1)
cout << "They're the same, yaaay! :3";
else
cout << "Aww, they're different >.>";However, this IS a reason to use Cstrings. STL strings add additional overhead, various runtime checks, plus they are allocated dynamically from the heap and have much more memory footprint. Using them when they're not needed, especially in C++ which is often chosen as high performance language, is quite a dirty and bad habit. Plus like I said, these strings are provided as an library, albeit they are part of the standard, they are not part of the language itself, null terminated strings however are.
Additionally, null terminated strings are very often used to store arbitrary binary data, working as an buffer, because the char type corresponds to a single byte.
---------------------------------------------------------------------------------------------------------
How cout and iostream work - brief introduction to operator overloading
Spoiler:
Let's look at following simple hello world example in C++
Pre-processor directives aren't technically part of the C/C++ language, so when you write an
the C++ compiler doesn't really even see this part, instead, the pre-processor takes the contents of the file iostream and puts them at the place of directive and then passes the result to the compiler. File iostream contains various functions and declarations already made for you to use, including the cout.
cout isn't a print statement, it's an object from the standard library, that's linked to the stdout stream, which is linked to the console output by standard. It's because C++ is object oriented language. Because of that, when you send any data to the cout, it will send them to the stdout stream (you can imagine it a bit like a pipe, trough which the data travel), which normally sends it to the console, where user can see it.
The operator << isn't a shift operator in this case (it doesn't shift anything really), it's an overloaded operator for the ostream class (maybe not exactly ostream, I would have to check docs, but it doesn't matter really) - the type of object cout is. C++ allows you to overload operators in relation to classes - change their meanings for variables that hold objects of certain glasses and it's basically a nicer way to call a function, so if you write:
Then what happens behind the scenes is, that it basically calls this method of the cout object:
Which handles the printing and returns the cout, so it can be used in chain statements and expressions.
What it does, is that it calls the overloaded operator method of the cout object and passes it the right operand. However, it's possible that it's not defined for the class itself, but that the overloaded operator is defined as a friend, so the cout is passed to the method as well as an argument, otherwise it's passed implicitly and accessible via this pointer.
It's a almost the same as calling printf("Hello World"); in C, except that it's more fancy and it's object oriented (it's called in relation to a specific object). Think of using cout << "Hello World"; as more fancy way of calling a function, like cout.printf("Hello World"); It is also very benefitial, because you can substitute other objects for the cout, for example a file, so instead of writing the text to the screen, it will be written to a file, but you send the data using exactly the same way, instead of having a million and one ways to do the same thing.
Also, endl is iostream manipulator, if you pass this object to cout (and others), it somehow manipulates the input or output stream. For example
Prints the number in hexadecimal. The hex is another IO stream manipulator, just like endl.
Code:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World";
return 0;
}Pre-processor directives aren't technically part of the C/C++ language, so when you write an
Code:
#include <iostream>cout isn't a print statement, it's an object from the standard library, that's linked to the stdout stream, which is linked to the console output by standard. It's because C++ is object oriented language. Because of that, when you send any data to the cout, it will send them to the stdout stream (you can imagine it a bit like a pipe, trough which the data travel), which normally sends it to the console, where user can see it.
The operator << isn't a shift operator in this case (it doesn't shift anything really), it's an overloaded operator for the ostream class (maybe not exactly ostream, I would have to check docs, but it doesn't matter really) - the type of object cout is. C++ allows you to overload operators in relation to classes - change their meanings for variables that hold objects of certain glasses and it's basically a nicer way to call a function, so if you write:
Code:
cout << "Hello World";Code:
ostream operator<<(const char *message_to_print);What it does, is that it calls the overloaded operator method of the cout object and passes it the right operand. However, it's possible that it's not defined for the class itself, but that the overloaded operator is defined as a friend, so the cout is passed to the method as well as an argument, otherwise it's passed implicitly and accessible via this pointer.
It's a almost the same as calling printf("Hello World"); in C, except that it's more fancy and it's object oriented (it's called in relation to a specific object). Think of using cout << "Hello World"; as more fancy way of calling a function, like cout.printf("Hello World"); It is also very benefitial, because you can substitute other objects for the cout, for example a file, so instead of writing the text to the screen, it will be written to a file, but you send the data using exactly the same way, instead of having a million and one ways to do the same thing.
Also, endl is iostream manipulator, if you pass this object to cout (and others), it somehow manipulates the input or output stream. For example
Code:
cout << hex << 15;---------------------------------------------------------------------------------------------------------
Writing a keylogger like real programmer (requires thinking!)
Spoiler:
It's very important to determine what OS are you targeting. I hope you want it only for educational purposes, ideally to learn how to detect them and protect against them, or at least some not-harmful usage.
Though if I was to make a simple one (I almost never use tutorials, instead come up with some way to solve the problems myself), I would do the following:
-Search given OS's documentation for reading raw keyboard input even without focus (should be okay for simple one, but I think it's not so reliable, more complex one might probably try to find a way to detect input at lower levels (inject itself into the kernel if possible? Modify the driver?).
-Look for a way to hide the application from the system (no visible GUI, ideally hide it from process list)
-Decide what exactly I want to capture and how I'll store it. Do I want to store also some additional information about the computer? Do I store raw scancodes or decoded key codes (that's usually affected by keyboard layout)?
-Write a code that would capture the keyboard input and store it somewhere (would harddrive be a good idea? It might be easier to found if it keeps writing on the drive often, so probably large cache in RAM?)
-Look up some libraries for network communication
-Write a code that would, once in a time (not very often so it's not visible) send the recorded data to given location.
Of course, it's needed to elaborate each of these points, however, when designing application, it's important to decompose it into logical units, each performing certain task. You should learn to decompose the problem yourself, instead of being told by others each one of the steps. Realize what the software should do, what it needs to achieve to do that and then research information required to create various components. You learn much more by this process than by simply following pre-made solution.
Though if I was to make a simple one (I almost never use tutorials, instead come up with some way to solve the problems myself), I would do the following:
-Search given OS's documentation for reading raw keyboard input even without focus (should be okay for simple one, but I think it's not so reliable, more complex one might probably try to find a way to detect input at lower levels (inject itself into the kernel if possible? Modify the driver?).
-Look for a way to hide the application from the system (no visible GUI, ideally hide it from process list)
-Decide what exactly I want to capture and how I'll store it. Do I want to store also some additional information about the computer? Do I store raw scancodes or decoded key codes (that's usually affected by keyboard layout)?
-Write a code that would capture the keyboard input and store it somewhere (would harddrive be a good idea? It might be easier to found if it keeps writing on the drive often, so probably large cache in RAM?)
-Look up some libraries for network communication
-Write a code that would, once in a time (not very often so it's not visible) send the recorded data to given location.
Of course, it's needed to elaborate each of these points, however, when designing application, it's important to decompose it into logical units, each performing certain task. You should learn to decompose the problem yourself, instead of being told by others each one of the steps. Realize what the software should do, what it needs to achieve to do that and then research information required to create various components. You learn much more by this process than by simply following pre-made solution.
---------------------------------------------------------------------------------------------------------
Assembler in C/C++
Spoiler:
Well if you want to write something completely in assembly, then you simply enter the instructions (with syntax following a convention) in some plain-text file (as with most programming languages) and then give the file to assembler, which will produce appropriate machine code. That of course depends on what processor architecture you want to program, because they differ. There are several assemblers for x86 (what PC's usually use), for example MASM32 or NASM. You need to check their documentation for syntax details.
If you don't want to use even the assembler, then you'll have to get instruction table for given processor and find the opcodes yourself, although this is very tedious and usually pointless. You can use some hex-editor (HxD for example) to write raw binary data into some file, than you can then load in the memory and let the processor execute it, that of course depends on architecture you want to program - in some (usually MCU's) you usually just flash the machine code into ROM, but on Windows for example, you would have to add header and other additional info to form a PE executable (tautology I know).
However! To make it somewhat simple, you can actually write assembly code in C/C++ using the asm statement. It's quite advanced feature, since it requires a knowledge of what's going on in the language and processor. However, you still don't need to handle other needed stuff, because C/C++ compiler sets up the wrapping code and data for you. You can do it like this:
If this doesn't work with some compilers, add double underscores before the asm keyword:
If you don't want to use even the assembler, then you'll have to get instruction table for given processor and find the opcodes yourself, although this is very tedious and usually pointless. You can use some hex-editor (HxD for example) to write raw binary data into some file, than you can then load in the memory and let the processor execute it, that of course depends on architecture you want to program - in some (usually MCU's) you usually just flash the machine code into ROM, but on Windows for example, you would have to add header and other additional info to form a PE executable (tautology I know).
However! To make it somewhat simple, you can actually write assembly code in C/C++ using the asm statement. It's quite advanced feature, since it requires a knowledge of what's going on in the language and processor. However, you still don't need to handle other needed stuff, because C/C++ compiler sets up the wrapping code and data for you. You can do it like this:
Code:
// C/C++ code
asm
{
// assembly code here
}
// C/C++ codeIf this doesn't work with some compilers, add double underscores before the asm keyword:
Code:
// C/C++ code
__asm
{
// assembly code here
}
// C/C++ code---------------------------------------------------------------------------------------------------------
Beginner mistakes broken apart (includes sources of corrections)
Spoiler:
Because these examples are quite long, I'll point you to their respective topics. Information might be quite useful if you're starting with C/C++ and will help you avoid various mistakes in your code:
http://www.hackcommunity.com/Thread-1st-C-Program
http://www.hackcommunity.com/Thread-made...2#pid41472
http://www.hackcommunity.com/Thread-C-pr...7#pid67777
http://www.hackcommunity.com/Thread-1st-C-Program
http://www.hackcommunity.com/Thread-made...2#pid41472
http://www.hackcommunity.com/Thread-C-pr...7#pid67777
---------------------------------------------------------------------------------------------------------
Understand iterative, recursive and dynamic calculations.
Spoiler:
In C/C++, you can do the same thing in multiple ways, including various calculations, such as factorial as following examples show:
Iterative way
Recursive way
Dynamic way
Results of the calculation itself should always be exactly same (it will calculate exactly the same series of numbers no matter which version you use), however there are important differences in the side effects.
Iterative calculation is often the best, but also the most difficult one to implement, especially if you're dealing with something more complex. It uses least memory and is usually the fastest. That's because you have just one copy of the variables and it keeps changing over the time, with each iteration of the loop, the following element is calculated, the old records are overwritten.
Recursive calculation is often the easiest to implement, as it often directly relates to a mathematical way something is described, which is for factorial (you can see the relation to the code, it's written basically the same, as a product of the number N you're calculating and factorial of N - 1.
However, it is somewhat slower and in case you want to calculate a lot of values, your program might eventually crash. That's because recursive calculation always calculates one element and in order to calculate it, it will call usually itself again, but with different input parameter. This newly called function will need to calculate another element and again, call itself with different parameter to calculate and it keeps on calling itself until some condition is satisfied and the function at the end will return a number, then it starts returning results and cascading back, until you get the final result.
Problem is, that for each call of a function a copy of the variables it needs (including the input parameters) is made, as well as information about where the function should return to. This information needs to be stored somewhere, usually on an internally created stack (a memory construct), that has fixed size, so if the recursive calls go too deep, it won't be able to hold all these copies and your program will crash because of stack overflow.
Additionally, making copies of the variables, calling the function for each element, returning and such cause additional overhead, that slow the whole algorithm down.
That being said, recursive functions still have great use, some calculations are really difficult to implement in an iterative way, so recursive calls might be the only way to go.
Now the dynamic way uses a dynamic memory construct such as the vector from the STL library. These constructs store the values in dynamically allocated memory space called heap. Dynamic means, that you can allocate and reallocate memory when the program is running in a rather arbitrary manner, as opposed to static allocation, that's used for variables or arrays in your program that you declare in the usual way. Size of these is known at the compile time and they're just static - they can't move, they can't change in size.
Dynamic allocation allows you to for example change the size of the dynamic array (which is called vector) on the fly. If the array is too small and unable to hold the new element, it is simply resized - more memory is allocated automatically for you, assuming the system has some free memory.
The dynamic calculation presented in that example is similar to the iterative way, except for the fact that it stores all the calculated values in the dynamic array - it doesn't only calculate you the n-th value in the series, but instead, it creates a dynamic array that contains the whole series up to the n-th value. For this, you obviously need much more memory (storing 100 values for example as opposed to just one + few work variables), but heap is usually much much bigger than the internal stack, so you would usually run into out of memory trouble only if you were to calculate I dunno... at least a few hundred millions values.
The dynamic way would be probably used if you need to have the whole series stored somewhere. You can think of it as the iterative way, that simply stores each calculated element, instead of discarding it (by overwriting it by the following element). In the example above, both iterative and recursive ways are called only once for each of the numbers, so the calculation is done twenty times, which is a bit waste, however the dynamic calculation is called only once, it stores all the results from one to twenty and then just prints them. It could be said that for calculating a whole series, not just one final result, the dynamic way is the fastest one.
Iterative way
Code:
#include <iostream>
using namespace std;
double factorial(int n)
{
double product = 1.0;
for(int i = 2; i <= n; i++)
product *= i;
return product;
}
int main()
{
for(int i = 1; i <= 20; i++)
cout << "Factorial of " << i << " is " << factorial(i) << endl;
return 0;
}Recursive way
Code:
#include <iostream>
using namespace std;
double factorial(int n)
{
if(n <= 1)
return 1.0;
return n*factorial(n-1);
}
int main()
{
for(int i = 1; i <= 20; i++)
cout << "Factorial of " << i << " is " << factorial(i) << endl;
return 0;
}Dynamic way
Code:
#include <iostream>
#include <vector>
using namespace std;
vector<double> factorial(int n)
{
vector<double> result;
result.push_back(1); // first value
for(int i = 2; i <= n; i++)
result.push_back( i * result.back() );
return result;
}
int main()
{
vector<double> results = factorial(20);
for(int i = 0; i < results.size(); i++)
cout << "Factorial of " << i+1 << " is " << results[i] << endl;
return 0;
}Results of the calculation itself should always be exactly same (it will calculate exactly the same series of numbers no matter which version you use), however there are important differences in the side effects.
Iterative calculation is often the best, but also the most difficult one to implement, especially if you're dealing with something more complex. It uses least memory and is usually the fastest. That's because you have just one copy of the variables and it keeps changing over the time, with each iteration of the loop, the following element is calculated, the old records are overwritten.
Recursive calculation is often the easiest to implement, as it often directly relates to a mathematical way something is described, which is for factorial (you can see the relation to the code, it's written basically the same, as a product of the number N you're calculating and factorial of N - 1.
Code:
N! = N*(N-1)!However, it is somewhat slower and in case you want to calculate a lot of values, your program might eventually crash. That's because recursive calculation always calculates one element and in order to calculate it, it will call usually itself again, but with different input parameter. This newly called function will need to calculate another element and again, call itself with different parameter to calculate and it keeps on calling itself until some condition is satisfied and the function at the end will return a number, then it starts returning results and cascading back, until you get the final result.
Problem is, that for each call of a function a copy of the variables it needs (including the input parameters) is made, as well as information about where the function should return to. This information needs to be stored somewhere, usually on an internally created stack (a memory construct), that has fixed size, so if the recursive calls go too deep, it won't be able to hold all these copies and your program will crash because of stack overflow.
Additionally, making copies of the variables, calling the function for each element, returning and such cause additional overhead, that slow the whole algorithm down.
That being said, recursive functions still have great use, some calculations are really difficult to implement in an iterative way, so recursive calls might be the only way to go.
Now the dynamic way uses a dynamic memory construct such as the vector from the STL library. These constructs store the values in dynamically allocated memory space called heap. Dynamic means, that you can allocate and reallocate memory when the program is running in a rather arbitrary manner, as opposed to static allocation, that's used for variables or arrays in your program that you declare in the usual way. Size of these is known at the compile time and they're just static - they can't move, they can't change in size.
Dynamic allocation allows you to for example change the size of the dynamic array (which is called vector) on the fly. If the array is too small and unable to hold the new element, it is simply resized - more memory is allocated automatically for you, assuming the system has some free memory.
The dynamic calculation presented in that example is similar to the iterative way, except for the fact that it stores all the calculated values in the dynamic array - it doesn't only calculate you the n-th value in the series, but instead, it creates a dynamic array that contains the whole series up to the n-th value. For this, you obviously need much more memory (storing 100 values for example as opposed to just one + few work variables), but heap is usually much much bigger than the internal stack, so you would usually run into out of memory trouble only if you were to calculate I dunno... at least a few hundred millions values.
The dynamic way would be probably used if you need to have the whole series stored somewhere. You can think of it as the iterative way, that simply stores each calculated element, instead of discarding it (by overwriting it by the following element). In the example above, both iterative and recursive ways are called only once for each of the numbers, so the calculation is done twenty times, which is a bit waste, however the dynamic calculation is called only once, it stores all the results from one to twenty and then just prints them. It could be said that for calculating a whole series, not just one final result, the dynamic way is the fastest one.
I love creativity and creating, I love science and rational thought, I am an open atheist and avid self-learner.
![[+]](https://sinister.ly/images/modern/collapse_collapsed.png)