Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Sunday, November 28, 2010

printf cheatsheet

Format string

  % [flag]* [minimum_field_width] [precision] [length_modifier] <conversion_specifier>

Flags

Flag Description  
# The value should be converted to an "alternate form".  
0 zero padded. By default, blank padded  
- left adjusted  
' ' (A single space) A blank should be left before a positive number (or empty  string)  produced by a signed conversion.  
+ A sign is always placed before a number produced by a signed conversion.  

Minimum Field Width

"a decimal digit string (with  non-zero first digit). If the value has fewer characters, it will be padded.  In no case does a nonexistent or small field width cause truncation of a field."

Precision

a period ('.')  followed by an optional decimal digit string. It has different meanings for different conversions.

Precision Description  
d, i, o, u, x, and X minimum number of digits to appear printf("%.2d", 1) ==> "01"
a, A, e, E, f, and F number of digits to appear after  the radix  character printf("%.2f",0.1) ==> "0.10"
g and G maximum number of significant digits  
s and S maximum number of characters to be printed from a string printf("%.2s","hello") ==> "he"

Length Modifier

For each conversion specifier, there is expected argument type. For example, for conversion d,  and i, type of arguments should be int. Length Modifiers can be used to specify argument types rather than expected type by default.

Modifier Conversion Argument types
hh d, i, o, u, x, or X signed char or unsigned char
n signed char*
h d, i, o, u, x, or X short int or unsigned short int
b short int*
l d, i, o, u, x, or X long int, or unsigned long int
n long int*
c wint_t
s wchar_t
ll d, i, o, u, x, or X long long int, or unsigned long long int
n long long int*
L a, A, e, E, f, F, g, or G long double
j d, i, o, u, x, or X intmax_t, uintmax_t
z d, i, o, u, x, or X size_t, ssize_t
t d, i, o, u, x, or X ptrdiff_t

Conversion specifier

conversion arguments notation  
d, i int argument signed decimal notation  
o, u, x, X unsigned int unsigned octal, unsigned decimal, unsigned hexdec notation abcedf are used for x.
ABCDEF are used for X.
e, E double rounded and converted in the style [-]d.ddde±dd precision is 6 by default.
f, F double rounded  and  converted  to  decimal  notation in the style [-]ddd.ddd precision is 6 by default.
g, G double converted in style f or e (or F or E for G  conversions).
Style e  is  used  if the  exponent from its conversion is less than -4 or greater than or equal to the precision.
 
a, A double converted to hexadecimal notation.
for a, (using the letters abcdef) in the style [-]0xh.hhhhp±d;
C99;  not in SUSv2
c int converted to an unsigned char, and the resulting character is written  
s const char* Characters from the array are written.  
p void * printed in hexadecimal (as if by %#x or %#lx)  
n int * The number of characters written so far is stored into the integer  indicated  by  the int * (or variant) pointer argument.  

Saturday, May 03, 2008

Differences of array and pointer in C/C++

(1) Array

int main(){
    char *p = "hello,world";
    char *p2 = "hello,worldc";
    char str[] = "hello,world";
    char str2[] = "hello,world";    
    printf("%x %x %x %x\n", p, p2, str, str2);

}

Sample output(compiled with GCC 4.1.2 on Ubuntu 6.06.1LTS):

804856c 8048578 bf879674 bf879668

Conclusions:
<1> Strings pointed by pointers p and p2 are allocated in different places from strings of str and str2. The first and second strings are allocatd to static memory area and these two strings can not be modified. So the following statement makes the program crash(run time error instead of compilation time):
    p[0] = 'd'
The third and fourth strings are allocated on stack.  They can be modified. They just exist in current function call and after this function is executed they are discarded and should not be referenced any more.
<2> Pointers can be modified arbitrarily while array variables can not be modified.
Following code is illegal:

    char str[] = "hello,world";
    char str2[] = "abcdefgh";
    str = str2;    //illegal, can not be compiled successfully.
str++; //illegal
str+1; //legal, just like an ordinary addition.

In other words, array name is a reference to an array and it represents the array.  It is kind of a contant.
<3> Array name cannot be used a left value. Array name can be used as pointer if it acts as right value. Pointer can not be cast to array!!!
<4> Apply sizeof to array name, you will get size of the array. Apply sizeofi to a pointer, you will get size of the pointer(generally, four bytes).
<5> Array must be initialized and corresponding memory is allocated.
<6> void function(type array[]) is equivalent to void function(type *pointer).

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。
不能对数组名进行直接复制与比较。示例7-3-2中,若想把数组a的内容复制给数组b,不能用语句 b = a ,否则将产生编译错误。
当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针.
对数组名sizeof()得到的是数组所占的大小,而对指针sizeof()得到的是指针内容所占的字节数。
数组定义时必须初始化并分配空间,而指针定义时可以不初始化。
如果将数组或指针作为自定义函数的形参,此时数组名和指针完全等价.在函数体内可以用数组名进行自增或赋值等运算,因为在一般的编译程序中,将函数的形参数组编译成指针.既f(char Data[])====>f(char *Data)