Sunday, October 30, 2011

why can we use printf without including stdio.h

I read the c programming language again to mourn Dennis Ritchie who passed away recently.

I noticed below statements in section "4.2 Functions Returning Non-integers", which explains the question, why can we use printf without including stdio.h.

The function atof must be declared and defined consistently. If atof itself and the call to it in main have inconsistent types in the same source file, the error will be detected by the compiler. But if (as is more likely) atof were compiled separately, the mismatch would not be detected, atof would return a  double that  main would treat as an  int, and meaningless answers would result. 
In the light of what we have said about how declarations must match definitions, this might seem surprising. The reason a mismatch can happen is that if there is no function prototype, a function is implicitly declared by its first appearance in an expression, such as
   sum += atof(line)
If a name that has not been previously declared occurs in an expression and is followed by a left parentheses, it is declared by context to be a function name, the function is assumed to return an  int, and nothing is assumed about its arguments. Furthermore, if a function declaration does not include arguments, as in
   double atof();
that too is taken to mean that nothing is to be assumed about the arguments of atof; all parameter checking is turned off. This special meaning of the empty argument list is intended to permit older C programs to compile with new compilers. But it's a bad idea to use it with new C programs. If the function takes arguments, declare them; if it takes no arguments, use
void.

So, let's take a look at the hello world sample below:

1 //#include  <stdio.h>
2
3 int main(int argc, char *argv[])
4 {
5     printf("hello world!\n");
6     return 0;
7 }

When the code is compiled, the statement on line 5 implicitly declares the printf function because it's not declared explicitly. It's the same as if we declared printf as:
  int printf();
And there is no assumption about its argument, so the code can pass the compile phase.

In link phase, unlike c++, only the function name (function signature doesn't matter) affects the symbol name. So the printf symbol name can be found from the standard c library which is linked automatically. As a result, the code above can compile and run successfully.

Sunday, October 23, 2011

stream audio via udp on android

In this post, I tried to play small audio data chunks with AudioTrack to show the feasibility of streaming audio. It's not straightforward enough. So I updated the sample code to actually transfer audio data with udp.
As the image below shows, the application is not too complicated.


The two buttons will each create a new thread to send and recv audio data respectively. And the sender will read audio data from the file /data/1.wav. Then, it sends the data to udp port 2048 on localhost. The receiver reads on 2048 port and feed data received to AudioTrack object.
Full code is available at:
http://code.google.com/p/rxwen-blog-stuff/source/browse/trunk/android/streaming_audio/src/rmd/media/StreamingAudio/UdpStream.java

Wednesday, October 12, 2011

microsoft's ifstream automatically removes carriage return

By default, the ifstream class in miscrosoft's STL converts a carriage return and new line (0x0d0a or crlf) pair to a single new line (0x0a) automatically while reading a text file.

Take the following code for example:


 #include    <cstdlib>
 2 #include    <fstream>
 3 #include    <iostream>
 4 
 5 using namespace std;
 6 
 7 int main ( int argc, char *argv[] )
 8 {
 9     ifstream fs("crlf.txt");
10     fs.seekg(0, ios::end);
11     int len = fs.tellg();
12     fs.seekg(0, ios::beg);
13 
14     char* buf = new char[len];
15     fs.read(buf, len);
16     cout << hex;
17     // dump buf in hex format
18     for(int i = 0; i < len; ++i)
19         cout << static_cast<int>(buf[i]) << " ";
20     cout << endl << dec << buf << endl;
21     cout << "file size: " << len
22         << " actual read len: " << fs.gcount() << endl;
23     return EXIT_SUCCESS;
24 }               // ----------  end of function main  ----------



And let's suppose the content of crlf.txt is:
hello\r\n
world\r\n

If we compile the code with microsoft's vc++ compiler, and run the executable against the preceeding text file, we get below output:
68 65 6c 6c 6f a 77 6f 72 6c 64 a 0 0
hello
world


file size: 14 actual read len: 12

As we can see, the 0x0d0a has been changed to 0x0a, and the number of bytes actually read is 12, other than 14. But if we compile the code with g++ and run the test, we get different output:

68 65 6c 6c 6f d a 77 6f 72 6c 64 d a
hello
world


file size: 14 actual read len: 14
The number of bytes actually read is now the same as the text file's size. And the bytes read into memory is the same as the original file's on disk.

In very rare cases, we may appreciate the microsoft ifstream's behavior, which saves our time from making such conversion our-self. But in most cases, it has negative consequence and incurs subtle bugs that are hard to debug.
Not sure why is it, just to be alerted by this specific behavior exhibited by microsoft's STL.