• 0

[C++] give me a program idea


Question

I want to try writing a C++ program. I'm going to start with a Windows-based console app as I'm not ready to delve into GUIs. I plan to use MS Visual C++ 2010 but using native C++ (not C++/CLI). Can someone please give me an idea of a simple program? I'd like to incorporate some math, opening/saving text files, and working with more than one function.

Thanks!

Also, when I'm done I will post the source code in hopes of having it reviewed foe possible improvements.

Link to comment
Share on other sites

Recommended Posts

  • 0
As evn pointed out, a lot of compilers will treat pre and post increment counters the same during compilation. Some might even optimise for post increment. No one really knows for sure, and therefore advocating one way or the other should be discouraged. Let the compiler worry about those details.
++i will always be optimal and is the simpler concept. That's reason enough to prefer it to the other form.

Assuming i++ will get optimized away is silly. If i is an iterator or a custom class, you can't assume the compiler to do anything in particular.

Link to comment
Share on other sites

  • 0

Koma was right about ++x over x++ and this is not an optimization since they do different things. Try

a = ++x;

b = x++;

The compiler will most likely not change one to the other because they work differently and if you run the above case, you get different values between a and b.

If you want try something interesting, do this:

a = a+++++a;

Now do it in a different language and see what happens.

______

As for the OP, I suggest implementing the A* algorithm to do shortest path traversal. I recently messed around with it and found simple yet very powerful. It's good to know.

Link to comment
Share on other sites

  • 0

Koma was right about ++x over x++ and this is not an optimization since they do different things. Try

a = ++x;

b = x++;

We're talking about loop counter optimisation. Your example is based on order of precedence. The for loop counters are always evaluated in the same way. Thus:

for (i = 0; i < 10; i++);

is indistinguishable from

for (i = 0; i < 10; ++i);

in terms of behaviour.

The compiler will most likely not change one to the other because they work differently and if you run the above case, you get different values between a and b.

As loop counters, they do both behave the same. That's the point. The compiler knows how to optimise loops better than us high level programmers.

#include <stdio.h>
int main ()
{
	int i, j;
	for (i = 0, j = 0; i < 10; i++, ++j) {
		printf("i=%i, j=%i\n", i, j);
	}

	return 0;
}

Results:

$ gcc -o loop loop.c
$ ./loop
i=0, j=0
i=1, j=1
i=2, j=2
i=3, j=3
i=4, j=4
i=5, j=5
i=6, j=6
i=7, j=7
i=8, j=8
i=9, j=9

Link to comment
Share on other sites

  • 0

To elaborate further, I did a small test.

#include <stdio.h>
int main ()
{
	int i;
	for (i = 0; i < 10; i++);
	return 0;
}

I compiled pre and post increment versions, and GCC at least, generates identical assembly with and without optimisation:

$ gcc -O0 -o pre.s -S loop.c && gcc -O0 -o post.s -S loop2.c

$ diff pre.s post.s

$ <no difference> except: .file "loop.c" / .file "loop2.c"

$ cat post.s

	.file	"loop2.c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$0, -4(%rbp)
	jmp	.L2
.L3:
	addl	$1, -4(%rbp)
.L2:
	cmpl	$9, -4(%rbp)
	jle	.L3
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.6.2 20111125 (prerelease)"
	.section	.note.GNU-stack,"",@progbits

My x86/GAS assembly's a bit rusty, but It doesn't look like GCC uses a temporary variable. It seems to store the value of 'i' in the memory position(stack pointer) -4(%rbp). On each iteration of the loop, it does cmpl $9, -4(%rbp) (i < 10), jle .L3, jump if less than 10 to label .L3's addl $1, -4(%rbp) (increment counter ++i or i++). Pre/Post increment has no effect on GCC's resulting binary code.

Therefore, any assertion that the pre-increment is somehow more efficient than post-increment when operating on primitive datatypes in for loop counters is completely fallacious and should be summarily ignored as misinformed advice.

Link to comment
Share on other sites

  • 0

To elaborate further, I did a small test.

#include &lt;stdio.h&gt;
int main ()
{
	int i;
	for (i = 0; i &lt; 10; i++);
	return 0;
}

I compiled pre and post increment versions, and GCC at least, generates identical assembly with and without optimisation:

$ gcc -O0 -o pre.s -S loop.c && gcc -O0 -o post.s -S loop2.c

$ diff pre.s post.s

$ <no difference> except: .file "loop.c" / .file "loop2.c"

$ cat post.s

	.file	"loop2.c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$0, -4(%rbp)
	jmp	.L2
.L3:
	addl	$1, -4(%rbp)
.L2:
	cmpl	$9, -4(%rbp)
	jle	.L3
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.6.2 20111125 (prerelease)"
	.section	.note.GNU-stack,"",@progbits

My x86/GAS assembly's a bit rusty, but It doesn't look like GCC uses a temporary variable. It seems to store the value of 'i' in the memory position(stack pointer) -4(%rbp). On each iteration of the loop, it does cmpl $9, -4(%rbp) (i < 10), jle .L3, jump if less than 10 to label .L3's addl $1, -4(%rbp) (increment counter ++i or i++). Pre/Post increment has no effect on GCC's resulting binary code.

Therefore, any assertion that the pre-increment is somehow more efficient than post-increment when operating on primitive datatypes in for loop counters is completely fallacious and should be summarily ignored as misinformed advice.

How about test for -O1 -O2 -O3, and not just based on O0

Link to comment
Share on other sites

  • 0

Therefore, any assertion that the pre-increment is somehow more efficient than post-increment when operating on primitive datatypes in for loop counters is completely fallacious and should be summarily ignored as misinformed advice.

It might not be more efficient, but it's always as efficient as possible, since it's the smallest operation you can do.

++i;[/CODE]

is shorthand for

[CODE]i = i + 1;[/CODE]

[CODE]i++;[/CODE]

is shorthand for

[CODE]
inline int postIncrement(int& i) {
int temp = i;
i = i + 1;
return temp;
}
postIncrement(i);
[/CODE]

While a smart compiler may very well, in some cases, optimize the whole thing away except for the increment, why should you rely on that when you can simply write ++i and not worry about it. In addition, while the post-increment might be optimized away for integers, it might not be for iterators or custom objects, as I mentionned. Also the behavior may also be suboptimal in other languages that also use post and pre-increment iterators (PHP as mentionned).

Hence a good rule of thumb is to always pre-increment unless you really need the post-increment behavior.

Link to comment
Share on other sites

  • 0

How about test for -O1 -O2 -O3, and not just based on O0

I compiled pre and post increment versions, and GCC at least, generates identical assembly with and without optimisation

Specifically, I tested with -O0 (none) and -O2 (normal optimisation level). Both produced identical assembly code (for the optimisation level).

Link to comment
Share on other sites

  • 0

It might not be more efficient, but it's always as efficient as possible, since it's the smallest operation you can do.

Neither is more efficient than the other, nor is one a smaller operation than the other, as I proved in the previous post.

++i;[/CODE]

is shorthand for

[CODE]i = i + 1;[/CODE]

[CODE]i++;[/CODE]

is shorthand for

[CODE]
inline int postIncrement(int& i) {
int temp = i;
i = i + 1;
return temp;
}
postIncrement(i);
[/CODE]

As shown in the assembly, GCC at least, just uses a single instruction for the incrementation of the counter: addl $1, -4(%rbp) , which just adds one to the stack variable 'i'. There's no temporary variable, or anything like that. Your logic is based on how you would implement it in C, but you see, the compiler reduces it to the machine instruction level. So you see it's quite pointless trying to base such trivial optimisations on how you think the compiler will work internally. GCC, and probably most other compilers too don't work like that.

You are making the mistake of trying to predict what the compiler is going to do. Internal behaviour changes from compiler to compiler. I don't concern myself with those details when writing code.

While a smart compiler may very well, in some cases, optimize the whole thing away except for the increment

If you read my previous post, you'd see that the single addl instruction is generated with no optimisation (-O0). That's right, even without optimisation, it doesn't work the way you think it does. That's why in my humble opinion, it's best to forget trying to second guess the compiler and just write the code how you're most comfortable. Pre or post, it really is inconsequential because they both compile down to the same single instruction for loop counters on primitive datatypes, in most cases at least.

why should you rely on that when you can simply write ++i and not worry about it.

The same can be said in reverse. Write it however you like ;) That's my point. Let the compiler worry about the specifics. I'm only against the spreading of misinformation that pre-increment is some how better or "the right way". Under the case in my previous post, it has no bearing on the resultant assembly/machine code.

In addition, while the post-increment might be optimized away for integers, it might not be for iterators or custom objects, as I mentionned. Also the behavior may also be suboptimal in other languages that also use post and pre-increment iterators (PHP as mentionned).

Hence a good rule of thumb is to always pre-increment unless you really need the post-increment behavior.

Again, this is unproven. I can't say for sure because I haven't tested it on anything but primitive datatypes, but I wouldn't be surprised if the compiler reduced both to the same set of instructions. It's another case of "do this because the compiler behaves a certain way". Even though you don't know how the compiler is working internally, and neither do I, or if the same behaviour applies across different compilers.

A good rule of thumb is to ignore unknowns and write code based on the official documented language, not hearsay, or old wife's tales.

Link to comment
Share on other sites

  • 0

You are making the mistake of trying to predict what the compiler is going to do. Internal behaviour changes from compiler to compiler. I don't concern myself with those details when writing code.

You're the one posting dissassemblies here, trying to show how compilers work internally. If you were to apply what you're saying, you'd simply increment your variables rather than post-incrementing them, assuming a particular optimization.
That's right, even without optimisation, it doesn't work the way you think it does.
That's what the specification says it does, i.e. it increments the variable but returns the old value. I posted code to illustrate the behavior, not the implementation. The implementation can be as efficient as you want, it can't be more efficient than simply incrementing the variable, when what you want to do is simply incrementing the variable. And it certainly isn't always as efficient, despite the fact that a particular compiler for a particular language optimizes for a particular type in a particular case - which is all you've shown.
A good rule of thumb is to ignore unknowns and write code based on the official documented language, not hearsay, or old wife's tales.
Yes. That's why you should write your intent in the simplest manner possible, i.e. say "please increment this variable" (++i) rather than "please increment this variable but let the value of the expression be the old value but I hope you're optimizing away that last part because I don't really need it" (i++).
Link to comment
Share on other sites

  • 0

You're the one posting dissassemblies here, trying to show how compilers work internally.

Only to illustrate that you and others here are making invalid assumptions about how C/C++ compiler(s) work, and advocating dogmatically that others should adopt the same erroneous ideas.

If you were to apply what you're saying, you'd simply increment your variables rather than post-incrementing them, assuming a particular optimization.

No doubt i = i + 1 would compile down to the same addl $1, -4(%rbp) instruction, so yes, you could. However, i++ is more elegant because of its brevity. I guess it's equivalent to the C function:

void addl(long source, long *dest) {*dest = *dest + source;}
addl(1, &amp;i);

or something like that. Only, it's executed in a single processor cycle.

That's what the specification says it does, i.e. it increments the variable but returns the old value.

No where in the specification does it say that the compiler creates a temporary variable for the post increment loop counter:

for (i = 0; i &lt; 10; i++);

And that's what we're discussing here.

Yes. That's why you should write your intent in the simplest manner possible, i.e. say "please increment this variable" (++i) rather than "please increment this variable but let the value of the expression be the old value but I hope you're optimizing away that last part because I don't really need it" (i++).

lol. I see I'm not getting anywhere here.

Link to comment
Share on other sites

  • 0

Pre increment will always be faster than post increment and it's prefer if you don't need the old value. You are getting the same assembly code from GCC because most of the modern compiler is smart enough to optimize away the unused old value (temporary). If you were to turn off the optimization then you will see the difference so don't rely on compiler optimization when you don't need the old value. It's more like a good programming habit than premature optimization.

Link to comment
Share on other sites

  • 0
No doubt i = i + 1 would compile down to the same addl $1, -4(%rbp) instruction, so yes, you could. However, i++ is more elegant because of its brevity.
++i is

1) as short as i++

2) expresses your intent better (i.e. "increment i" vs "increment i but returns the old value but hopefully that'll be optimized away")

3) is always optimal whereas i++ depends on compiler optimizations to be optimal, which might not happen depending on the type and language used

That's reason enough to prefer this form to the other, no?

I guess it's equivalent to the C function:

void addl(long source, long *dest) {*dest = *dest + source;}
addl(1, &amp;i);

It's not. Both i++ and ++i are expressions of the same type as i, int in this case, not void. The only difference is that i++ evaluates to the original value whereas ++i evaluates to the new value. However the compiler is implemented, it has to figure out a way to keep 2 values for i++ (the old and the new), and only 1 for ++i. Therefore and for the reasons stated above, prefer ++i.
Link to comment
Share on other sites

  • 0

I can't believe this discussion on pre- vs post-incrementation is still going on...

This x 1000!!

I have read every post in this thread, but it is starting to get both repetitive and off-topic. I do appreciate everybody's replies but I think the only thing we can actually conclude from this whole discussion about ++i vs i++ is that we are not going to agree on this.

Edit: Again, though... It has been an interesting read and I really appreciate everybody for trying to help me learn.

Link to comment
Share on other sites

  • 0
I have read every post in this thread, but it is starting to get both repetitive and off-topic. I do appreciate everybody's replies but I think the only thing we can actually conclude from this whole discussion about ++i vs i++ is that we are not going to agree on this.

Everyone agrees on this. I guess if you want more help you'd better create a new thread at this point :p
Link to comment
Share on other sites

  • 0

How about we move on to something more productive...

...like tabs vs spaces? (spoilers tabs win)

Tabs are garbage. Try posting code with a ton of indention into a pastebin, or any site that shows code. It will look like garbage in return, unlike with spaces.

Link to comment
Share on other sites

  • 0

Tabs are garbage. Try posting code with a ton of indention into a pastebin, or any site that shows code. It will look like garbage in return, unlike with spaces.

Yes, because it makes far more sense to press your space bar 5,000 times instead of pressing your tab key 1,000 times :rolleyes:

Link to comment
Share on other sites

  • 0

Yes, because it makes far more sense to press your space bar 5,000 times instead of pressing your tab key 1,000 times :rolleyes:

Well in my IDE. It converts tabs to spaces. :) Get a modern IDE that isn't garbage ;P

Link to comment
Share on other sites

This topic is now closed to further replies.