First of all, I see no one has made an
extremely important point: This thread is about C++, not C (I took the liberty to change the thread's title but the OP still talks about C). They are different languages; C isn't a subset of C++. If your C code even compiles with a C++ compiler, it will likely not mean the same thing because there are many semantic differences between the two languages. That said, my answers will be about C, not C++, because I know the former much better.
suslik wrote:To fix this replace "a + b > 6" with "(int)a + b > 6".
You can never do this in C; that overflow has undefined behavior.
suslik wrote:2) Choose the minimal integer type that can hold all possible values of your variable, i.e: if my variable will be 0..300 that I should use short. 0..65535 then I should use int (not unsigned short! See item1) . There is one exception in this rule: use int (which represents word size of CPU) for loop counters and similar (i.e. for variables that are used in loops).
This generalization is nonsense; it will lead to all sorts of problems. The thing about the loop counter is just as terrible---use whatever you need and don't worry about performance (let the compiler optimize it away; C itself makes no performance requirements). For instance, your loop may require size_t because you're using the counter to index an array, possibly for string processing.
suslik wrote:I agree with this. But what about putc (int ch)? In docs I see "ch will be converted to unsigned char" Why not "putc (unsigned char ch)"?
The rationale is that putchar/putc/fputc's argument was made to match getchar/getc/fgetc's return value, which is int due to the fact that it may also return EOF. Note that putc does not have the prototype you wrote there.
pauldinhqd wrote:(3) why use "char*" to present string, instead of "unsigned char*"? can a character be negative?
Yes. Also, note that char is not the same as signed char. It can refer to either a signed or an unsigned type, depending on the C implementation (e.g., GCC allows for both). This is not true for other types, like int.
turdus wrote:The advice "always use signed int for numbers" leads to funny errors, like negative memory addresses in E820 map
That's true, but the example isn't a good one because you should be using fixed-width types there to begin with, such as uint32_t.
suslik wrote:- I suspect the same, but I've no clear explanation.
This is possibly (it was never officialy explained) the reason for which there are no char literals (e.g., unlike in C++, 'a' is an int literal). Something like toupper('c') in traditional C (i.e., pre-C89) caused an int to be passed. So as not to break older code, they did not make 'c' a char because, without prototypes, converting the value to the argument's expected type can be problematic.
EDIT: Damn, Griwes made the comment about char's default signedness as I was typing this response.