Some questions folks asked during office hours, while preparing for E02, and the answers: (1) What does it mean when you use int main(int argc, char *argv[]) instead of int main(void) Answer: I use the first form if I want to take in input from the command line, e.g. to read the values typed after the name of the executable. For example: ./repeatGreet 5 Hello I could have a program repeatGreet.cc (see the file repeatGreet.cc) Inside that program, I can use the variable argc to check how many things were passed in on the command line. For example: ./a.out Here, argc == 1 ./a.out foo bar fum Here, argc == 4 ./lab09 23 45 89 70 23 145 Here, argc = 7 In each case, argv[] is an array of char * values. Each char* is a pointer to one of the command line arguments. For example, for ./a.out foo bar fum argv[0] is a pointer to ./a.out\0 argv[1] is a pointer to foo\0 argv[2] is a pointer to bar\0 argv[3] is a pointer to fum\0 Each command line argument is a null terminated C string. So, in this same example, argv[0][2] is the single character 'a', and argv[3][2] is the character 'm'. The type of argv is char ** The type of argv[1] is char * The type of argv[1][0] is char The type of argc is int Remember that if you are passing in an int or a double using argv, you need to convert from ASCII to int, or ASCII to float. e.g. ./buyTickets 3 8.75 Suppose this is a program that lets you purchase three tickets, and the ticket price is $8.75 per ticket. Inside the program, you'd have to do: int numTickets = atoi(argv[1]); double price = atof(argv[2]); Finally, remember that you should NEVER access argv at all without FIRST checking argc to make sure that the argv elements you are looking for actually exist. If you are accessing argv[1] and argv[2], then argc needs to be at least 3. (2) I remember something related to $? and something about $@ What are those, and what should we know about them? Answer: First, let's distinguish where each is used. $? is only used with "echo" at the Unix command prompt. $@ is only used inside a Makefile, typically on the linking step. Now the details: $@, in a Makefile, appears in a rule like this one: main: timeOfDay.o main.o ${CCC} timeOfDay.o main.o -o $@ The $@ is replaced by the "target" of the rule, i.e. the thing at the left with a colon after it---in this case, "main". So the rule is equivalent to: main: timeOfDay.o main.o ${CCC} timeOfDay.o main.o -o main The reason for using $@ is: (a) laziness... is fewer keystrokes than typing "main" (just kidding) (b) easier to cut and paste rules... fewer things to change (the real reason.) The $? is used after you run an executable, to determine what the return value was. For example, suppose I have a C++ program, with main function like this one: ... int main(void) { return 0; } and that program is in an executable called a.out. If I run it and then type "echo $?", like shown below, I'll see 0 as the output of the echo command. > ./a.out > echo $? 0 On the other hand, if I have: ... int main(void) { return 77; } > ./a.out > echo $? 77 Whatever was in the return (or, as the actual parameter of exit, e.g. exit(3), gets returned as the result of echo $? It is a way to tell whether the program was successful or not, and if it wasn't, which error occured, without having to do cout or cerr. (3) When using functions, I can identify whether a function is "C++-style true pass-by-reference" vs. "pass-by-value" vs. "pass-by-pointer" (aka "C-style", or "simulated" pass by reference) That is, I could fill in the comments below: int foo (int &x); // C++-style pass by reference int bar (int x); // pass by value int fum (int *x); // pass-by-pointer But I'm not so clear on what type of value you should pass into each one as the _actual_ parameter. Answer: For C++-style pass by reference, it is important that whatever I pass in needs to be a valid lvalue. That is, it needs to be variable, or an element in an array, or a member of struct. The reasons is that inside the function, the formal parameter becomes an alias for the actual parameter, and could end up on the left hand side of an assignment statement. So, for example, given the function definitions above: int a, b, c, d; int *p; p = &a; a=1; b=2; c=3; d=4; struct Point_S { int x; int y; }; int nums[10] = {0}; Point_S points[5]; Point_S origin; // for C++ style pass by reference, lvalues are legal a = foo(b); // Legal a = foo(num[0]); //legal a = foo(num[b]); // legal a = foo(points[0].x) // legal a = foo(origin.y); // legal a = foo(*p); // legal; if I dereference p, I get an lvalue a = foo(5); // illegal; 5 is not an lvalue a = foo(p); // illegal; p is "int *", foo takes an int // For pass by value, both lvalues and rvalues are legal a = bar (5); //legal a = bar(b); // legal a = bar (b + nums[5] * points[3].x - 17) // legal // For pass by reference, I need the address of an lvalue a = foo(&b); // Legal a = foo(&num[0]); //legal a = foo(num); //legal, but possibly weird... would operate on num[0] only // unless x is treated inside foo as base of an array. a = foo(&num[b]); // legal a = foo(&(points[0].x) // legal a = foo(&(origin.y)); // legal a = foo(p); // legal; if I DON'T dereference p, p points to an lvalue If you have questions about other expressions and whether they are legal or not, feel free to send email.