PDA

View Full Version : The "I'm Finally Teaching Myself C/C++" Thread


Kraetos
2009-06-01, 19:49
It's summer and I have a lot of free time, so rather than continue to bitch, I figured I'd get off my ass and do something about the fact that I don't know C/C++/Objective-C. So I picked up this book (http://www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X) at the recommendation of my professor who uses it to give his computer vision students a crash course in C++, since he uses openCV for the course. I also found this PDF (http://phoenix.goucher.edu/~kelliher/s2009/cs325/cCppForJava.pdf), mainly because it has instructions on how to compile, but the book doesn't.

First, compiling. I wrote this example from the PDF (written in C, not C++):

# include <stdio.h>

int main()
{
printf("Hello World!\n");
}


... and compiled it ...


% gcc hello.c -o hello


... and ran it ...


% hello


... and OH NOES!


-bash: hello: command not found


But then I discovered that I could run it if I specified a full path. Actually, it doesn't even need a full path:


% ./hello
Hello World!


What's that about? Is this just how Mac OS X does it?

I went to the book for help but then I got even more confused. The Hello World! example in the book is as follows (C++):


#include <iostream>
using namespace std;

int main( )
{
cout << "Hello world" << endl;
return 0;
}


gcc hello.cpp -o hello


Small problem: this code wont even compile! "Undefined symbols" was the gist of the output.

So at this point I'm really just confused. Should I be using stdio.h or iostream? What's the difference between printf and cout? Why won't the C++ example compile?

Brad
2009-06-01, 19:58
Oooh, C/C++. :) Congrats on stepping up!

But then I discovered that I could run it if I specified a full path. Actually, it doesn't even need a full path:


% ./hello
Hello World!


What's that about? Is this just how Mac OS X does it?

That's what's called a "relative path". The "." refers to "this directory".

You have to specify the path to your new executable because, well, that's The Unix Way. :) Unix, Linux, and Mac OS X all behave this way. In your shell (ie. Terminal window), you have an environment variable called PATH that specifies a list of locations to look when you enter commands from the command-line. If the executable doesn't live in one of those places, you have to give the full or relative path to the executable.

(PATH is named as such because it's your "search path".)

Try this in the shell:
echo $PATH

That should dump a colon-delimited list of paths. Those paths are where many of Mac OS X's built-in command-line programs live. When you enter a command like "cp", your shell is actually looking in each of those paths for the "cp" program and then executing the first one it finds. To see where "cp" actually lives, try:

which cp

There could be multiple "cp" commands or files on your drive, but this finds the "cp" that would be resolved from your PATH variable.

For what it's worth, you can change the PATH variable to include more (or fewer) locations. For example, mine is set to:
~/Applications/bin:/opt/subversion/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
...but it's probably best to hold off on changing that for now.

Brad
2009-06-01, 20:06
What's the difference between printf and cout?
printf is a function. It takes a parameter, does something, and returns something. cout, however, is a named output stream. When you pipe to it using the << operator, you're feeding data into that stream rather than calling an executable function. It just so happens that the cout stream dumps out to your shell. Streams could go to files, devices, other programs, etc.

Kraetos
2009-06-01, 20:24
That's what's called a "relative path". The "." refers to "this directory".

I should have been more clear: I tried


% hello


because that's what the author of the PDF specified. Adding the relative path was my idea :) I was curious as to why the same command wouldn't work on my machine. Perhaps the author of that PDF modified his PATH variable to include the directory where he keeps his binaries and forgot to mention it to the reader.

printf is a function. It takes a parameter, does something, and returns something. cout, however, is a named output stream. When you pipe to it using the << operator, you're feeding data into that stream rather than calling an executable function. It just so happens that the cout stream dumps out to your shell. Streams could go to files, devices, other programs, etc.

Makes sense. Do you know why my computer appears to dislike iostream? Everything is up-to-date. Here's the version info for my gcc, in case it matters:


i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)

Brad
2009-06-01, 20:26
Should I be using stdio.h or iostream?
stdio and iostream are two different "input/output" header files. stdio is from C whereas iostream is from C++. stdio has a bunch of i/o functions like the printf() one you used above. iostream instead provides a few i/o stream objects for getting data in and out, one of which is stout.

Which you use is mostly a matter of preference. :)

Kickaha
2009-06-01, 20:35
#include <iostream>
using namespace std;

int main( )
{
cout << "Hello world" << endl;
return 0;
}


gcc hello.cpp -o hello


Small problem: this code wont even compile! "Undefined symbols" was the gist of the output.

g++ hello.cpp -o hello

gcc will compile C++ files, but it doesn't do the magic behind the scenes to make C++ *work*. Yeah, I know. Using g++ tells it to treat it as C++ from end to end.

Kraetos
2009-06-01, 20:38
Sure.

Here's the C++ code for reference:

#include <iostream>
using namespace std;

int main( )
{
cout << "Hello world" << endl;
return 0;
}


And the output:


% gcc hello.cpp -v -o hello
Using built-in specs.
Target: i686-apple-darwin9
Configured with: /var/tmp/gcc/gcc-5490~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=i686-apple-darwin9 --with-arch=apple --with-tune=generic --host=i686-apple-darwin9 --target=i686-apple-darwin9
Thread model: posix
gcc version 4.0.1 (Apple Inc. build 5490)
/usr/libexec/gcc/i686-apple-darwin9/4.0.1/cc1plus -quiet -v -D__DYNAMIC__ hello.cpp -fPIC -quiet -dumpbase hello.cpp -mmacosx-version-min=10.5.7 -mtune=generic -march=apple -auxbase hello -version -D__private_extern__=extern -o /var/folders/DO/DOiK7RiIGZOut+Q9kXs91++++TI/-Tmp-//cc0UXkPr.s
ignoring nonexistent directory "/usr/lib/gcc/i686-apple-darwin9/4.0.1/../../../../i686-apple-darwin9/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/include/c++/4.0.0
/usr/include/c++/4.0.0/i686-apple-darwin9
/usr/include/c++/4.0.0/backward
/usr/local/include
/usr/lib/gcc/i686-apple-darwin9/4.0.1/include
/usr/include
/System/Library/Frameworks (framework directory)
/Library/Frameworks (framework directory)
End of search list.
GNU C++ version 4.0.1 (Apple Inc. build 5490) (i686-apple-darwin9)
compiled by GNU C version 4.0.1 (Apple Inc. build 5490).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: d717d63b348495df150b35f29da70e48
/usr/libexec/gcc/i686-apple-darwin9/4.0.1/as -arch i386 -force_cpusubtype_ALL -o /var/folders/DO/DOiK7RiIGZOut+Q9kXs91++++TI/-Tmp-//cccCm696.o /var/folders/DO/DOiK7RiIGZOut+Q9kXs91++++TI/-Tmp-//cc0UXkPr.s
/usr/libexec/gcc/i686-apple-darwin9/4.0.1/collect2 -dynamic -arch i386 -macosx_version_min 10.5.7 -weak_reference_mismatches non-weak -o hello -lcrt1.10.5.o -L/usr/lib/i686-apple-darwin9/4.0.1 -L/usr/lib/gcc/i686-apple-darwin9/4.0.1 -L/usr/lib/gcc/i686-apple-darwin9/4.0.1 -L/usr/lib/gcc/i686-apple-darwin9/4.0.1/../../../i686-apple-darwin9/4.0.1 -L/usr/lib/gcc/i686-apple-darwin9/4.0.1/../../.. /var/folders/DO/DOiK7RiIGZOut+Q9kXs91++++TI/-Tmp-//cccCm696.o -lgcc_s.10.5 -lgcc -lSystem
Undefined symbols:
"___gxx_personality_v0", referenced from:
___gxx_personality_v0$non_lazy_ptr in cccCm696.o
"std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)", referenced from:
__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamI T_T0_ES6_$non_lazy_ptr in cccCm696.o
"std::ios_base::Init::~Init()", referenced from:
___tcf_0 in cccCm696.o
"std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))", referenced from:
_main in cccCm696.o
"std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)", referenced from:
_main in cccCm696.o
"std::ios_base::Init::Init()", referenced from:
__static_initialization_and_destruction_0(int, int)in cccCm696.o
"std::cout", referenced from:
__ZSt4cout$non_lazy_ptr in cccCm696.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Brad
2009-06-01, 20:39
Heh. See Kick's post that quickly outdated mine. ;)

Kraetos
2009-06-01, 20:42
Using g++ tells it to treat it as C++ from end to end.

How do I do that? Is it a flag for the gcc command? Or do I have to install something?

Never mind, Wikipedia to the rescue. (http://en.wikipedia.org/wiki/G%2B%2B)

Thanks all :)

[EDIT]
Whoops, I didn't even see that you changed it to g++ in your example. :o Thanks!

JohnnyTheA
2009-06-02, 00:32
Here is a website that is pretty good for C/C++ library information:

http://www.cplusplus.com/

JTA

Partial
2009-06-02, 23:08
Always gotta give full path unless its in PATH variable. You could add your workspace to the front of the PATH and that will probably do the trick.

C is a bitch, let me tell you. Once you get the hang of it, it's not horrible, though. Not what I'd want to do for my career, though!

Brad
2009-06-02, 23:59
Always gotta give full path unless its in PATH variable. You could add your workspace to the front of the PATH and that will probably do the trick.
No, relative paths work just fine. I'm not sure what you mean by workspace in this context since he's jut compiling files in arbitrary locations. He could always compile in the same directory and add that directory to the PATH variable, but it seems easy enough to just use ./ as "this directory".

Not what I'd want to do for my career, though!
Could be worse… he could be picking up Flex! ;)

Partial
2009-06-03, 00:15
I was including the relative path in my full pathish statement. Should have clarified. Can't execute a command from a dir without giving a path to it or if its in the PATH variable.

Basically, I was saying you can't just call hello. You have to call ./hello ../helloApp/hello, /usr/custombin/hello, etc. Unless of course it's in say /usr/bin, then he could just type hello and since that application is in the PATH, it would work.

See ls, which,cat, etc.

chucker
2009-06-03, 00:34
I should have been more clear: I tried


% hello


because that's what the author of the PDF specified.

To get that behavior, you could add . to your $PATH variable. Your confusion could be from the different behavior in DOS/NT, where the current directory is always in the path, so local files can always be executed that way.

bassplayinMacFiend
2009-06-10, 08:33
Man, I miss programming. I haven't done much programming beyond VBA at work since people stopped sending me ideas for Musical Scales.