Hello,
I've been studying my C++ textbook and working through some examples.
I had a few questions:
An excerpt from a code in the book:
#include <iostream>
int main()
{
//...
using std::cout;
using std::endl;
//...
}
The operator :: refers to the 'scope resolution'
The book doesn't seem to go into detail on this (at least not where I'm currently at)
Wondering what is exactly meant by 'resolution'?
Also what is meant by 'standard' in std::cout?
Another question:
Regarding bit shift left and right '<< and >>'
Example in code:
//...
cout << "Enter an integer: "; /*guessing similar to Serial.print("Enter an integer: ")
prints "Enter an integer: " to console or serial monitor */
cin >> inputNumber; /* guessing similar to Serial.write(inputNumber)
used to 'enter' or input a variable. In this case some number. */
I noticed on cout there is a bit shift left (<<) and for cin there is a bit shift right (>>).
The "<<" insertion operator is a pipe sort of thing. It means that the thing on the right is sent to the ostream object on the left. Conversely for the ">>". It's defined in the ostream class, http://www.cplusplus.com/reference/iostream/cout/. One thing about C++ that takes some getting used to is that you can redefine operators like that for specific classes.
"using std::cout" tells the compiler which version of several possible "cout" routines to use. See Grey Wolf's posts at what is this operator? - C++ Forum.
Here is an explanation of using Declarations and using directive:
using Declarations, ie:
1
2
3
using std::cout;
using std::cin;
using std::endl
add names to the scope in which they are declared. The effect of this is:
» a compilation error occurs if the same name is declared elsewhere in the same scope;
» if the same name is declared in an enclosing scope, the the name in the namespace hides it.
The using directive, ie using namespace std;, does not add a name to the current scope, it only makes the names accesable from it. This means that:
» If a name is declared within a local scope it hides the name from the namespace;
» a name in a namespace hides the same name from an enclosing scope;
» a compilation error occurs if the same name is made visible from multiple namespaces or a name is made visible that hides a name in the global name space.
Global scope resolution (::Name) tells the compiler to look for the name at global scope rather than local or any other. If you have used a using directive in the global scope all the names are accessible via that scope.
full scope resolutions (namspace::name) tells the compiler exactly where to look.
C was first designed for use with the Unix (known as Linux on the PC's) each program on Unix is allocated 3 "files", Standard input (stdin), Standard out (stdout) and Standard error. In the first versions of Unix file names had a very limited size this lead to standardio becoming stdio and password becoming passwd.
<< is not a shift operator (in this case) it's an example of operator overloading. C++ allows the redefinition of operators when you define Classes.
holmes4:
C was first designed for use with the Unix (known as Linux on the PC's) each program on Unix is allocated 3 "files", Standard input (stdin), Standard out (stdout) and Standard error. In the first versions of Unix file names had a very limited size this lead to standardio becoming stdio and password becoming passwd.
What?
C was designed to write unix, which is different from linux (linux is a unix clone, but other less popular versions of unix such as mac OS X and FreeBSD exist).
From what I've heard, there used to be a 14 character limit on filenames in very early unix, but "password" and "standardio" are both less than that. The reason they're shorter is just to save typing.
The first version of Unix that I recall using was System 3 circa 1982 and (I no longer have the man's) but as I recall it was six plus an extension, with a max file name length including all directory names of 256 chars. This was a huge amount for the era!
Yes Unix was written in C. But C was written in C.
The 'std::' has nothing to do with I/O. It refers to the 'namespace' 'std', a reserved namespace that all of the C++ Standard Library functions reside.
'::' is the namespace resolution operator. It exists to allow for the partition of symbol names to cut down on the collision of symbol names that are like to happen in todays projects.
'cout', 'cin' and 'cerr' are objects the conform to the 'stream' object paradigm available as part of the C++ Standard Libraries 'std' namespace.
You can create your own namespace where you are free to have symbol names the same as those in the 'std' namespace without fear of collisions which lead to linker errors.
#include <iostream>
//...
int main()
{
using std::cout;
using std::endl;
//...
}
//...
And another:
#include <iostream>
using namespace std;
//...
//...
**I had another question regarding functions:
more specifically "void functionName()" and non-void functions.
The book states that "void functions are functions that aren't required to make decisions or return success or failure status. Also void functions cannot return a value..."
#include <iostream>
using namespace std;
void MultiplyNumbers ()
{
cout << "Enter the first number: ";
int FirstNumber = 0;
cin >> FirstNumber;
cout << "Enter the second number: ";
int SecondNumber = 0;
cin >> SecondNumber;
// Multiply two numbers, store result in a variable
int MultiplicationResult = FirstNumber * SecondNumber;
// Display result
cout << FirstNumber << " x " << SecondNumber;
cout << " = " << MultiplicationResult << endl;
}
int main ()
{
cout << "This program will help you multiply two numbers" << endl;
// Call the function that does all the work
MultiplyNumbers();
// cout << FirstNumber <<" x " << SecondNumber;
// cout << " = " << MultiplicationResult << endl;
return 0;
}
Here the function "void MultiplyNumbers ()" makes a calculation and is later invoked inside "int main()"
So wouldn't this be returning a value to "MultiplyNumbers();" inside of "int main()" ?
void functions don't have a return value, that's all.
They can however have side-effects, as in your example it asks for numbers, multiplies them and displays the result.
Example:
void foo (int a, int b)
{
// you can do things with a and b here
return; // you cannot return a value
} // end of foo
int bar (int a, int b)
{
return a + b; // you must return an int
} // end of bar
To call those:
int main ()
{
foo (1, 2); // call foo, there is no return value
bar (4, 5); // call bar, discard the return value
int fubar = bar (6, 7); // call bar, get its return value
} // end of main
a void function can "return" a value. Example:
there's two ways to return more than one variable. The first is to make a struct to hold two values and return the struct:
struct fooReturn {
int x;
int y;
int z;
};
fooReturn foo(int x, int y) {
fooReturn ret = {x, y, x+y};
return ret;
}
void setup() {
Serial.begin(115200);
fooReturn fr;
fr = foo(3, 6);
Serial.print("Sum is ");
Serial.println(fr.z);
}
void loop() {}
The other is to pass the function an argument telling it where in memory to put the return value. This is called a pointer.
void foo(int* z, int x, int y) {
*z = x + y;
}
void setup() {
Serial.begin(115200);
int z;
foo(&z, 3, 6);
Serial.print("Sum is ");
Serial.println(z);
}
void loop() {}
In C++ there's also references which can do the same with slightly different syntax, but it's not advisible because the person calling the function won't know if it could change the value. But here's an example:
void foo(int& z, int x, int y) {
z = x + y;
}
void setup() {
Serial.begin(115200);
int z;
foo(z, 3, 6);
Serial.print("Sum is ");
Serial.println(z);
}
void loop() {}
Without wishing to nitpick, your first example "fooReturn foo(int x, int y)" isn't a void function.
The other ones are not returning the value, that is a side-effect (they are modifying data pointed to by a pointer, or a reference passed into the function). To return a value you literally have to use the "return" statement.
void functions can certainly change things outside themselves. Your examples do that, plus they can simply modify a global variable.
Thanks again for the replies.
Fubar... hehe sounds like most of the code I write
So here:
int main ()
{
foo (1, 2); // call foo, there is no return value
bar (4, 5); // call bar, discard the return value
int fubar = bar (6, 7); // call bar, get its return value
} // end of main
In the function "void foo(int a, int b)", you're assigning the number 1 and 2 to "int a" and "int b" respectively.
In the function "int bar(int a, int b)", you're assigning the number 4 and 5 to "int a" and "int b" respectively, resulting in a value of int a + int b (4 + 5) which equals 9, but discarding the return value.
Then using the variable "int fubar", int fubar = bar(6, 7) to get a return of "13" ?
Just as a curiosity, I saw a bit of code from maniacbug in an example sketch that configured stdout to use Serial. I suppose it would have been possible to hook up the stdin and stderr file descriptors in the same way, but I've never tried it. I also haven't tested to see whether the standard i/o streams followed the same path. Anyway, I thought it was a neat technique.
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* @file printf.h
*
* Setup necessary to direct stdout to the Arduino Serial library, which
* enables 'printf'
*/
#ifndef __PRINTF_H__
#define __PRINTF_H__
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#endif // __PRINTF_H__
[quote author=Nick Gammon link=topic=138443.msg1040972#msg1040972 date=1356140884]
It doesn't particularly make sense for the Arduino IDE to support stdin and stdout (or stderr) as they don't have any real meaning in the environment.
Just as a curiosity, I saw a bit of code from maniacbug in an example sketch that configured stdout to use Serial. I suppose it would have been possible to hook up the stdin and stderr file descriptors in the same way, but I've never tried it. I also haven't tested to see whether the standard i/o streams followed the same path. Anyway, I thought it was a neat technique.
[/quote] http://arduino.cc/forum/index.php/topic,120440.0.html http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html