extern int x;
extern int y;
占位符
%c 输出单个字符
%s 输出字符串
%p 输出指针地址
%d 直接输出整数
%f 是输出浮点数
%d 以十进制形式输出带符号整数(正数不知输出符号)
%o 以八进制形式道输出无符号整数(不输出前缀0)
%x,%X 以十六进制形式回输出无符号整数(不输出前缀Ox)
%u 以十进制形式输出无符号整数
%f 以小数形式输出单、双精度实数
%e%,E 以指数形式输出单、双精度实数
%g,%G 以%f或%e中较短的输出宽度输出单、双精度实数
%c 输出单个字符
%s 输出字符串
%p 输出指针地址
%lu 32位无答符号整数
%llu 64位无符号整数
printf
printf(" thingy 为 %d , count 为 %d\n", thingy, count);
{
register int miles;
}
寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 ‘register’ 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。
^异或运算:
首先异或表示当两个数的二进e799bee5baa6e58685e5aeb931333433623761制表示,进行异或运算时,当前位的两个二进制表示不同则为1相同则为0.该方法被广泛推广用来统计一个数的1的位数!参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。即: 0^0=0, 1^0=1, 0^1=1, 11=0按位异或的3个特点:(1)00=0,0^1=1 0异或任何数=任何数(2)10=1,11=0 1异或任何数-任何数取反(3)任何数异或自己=把自己置0按位异或的几个常见用途:(1)使某些特定的位翻转 例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。 10100001^00000110=10100111(2)实现两个值的交换,而不必使用临时变量。
sizeof()
sizeof() 返回变量的大小。sizeof(a) 将返回 4,其中 a 是整数。
& 返回变量的地址。&a; 将给出变量的实际地址。
指向一个变量。*a; 将指向一个变量。
? : 条件表达式如果条件为真 ? 则值为 X : 否则值为 Y
无限循环
for( ; ; )
{
printf("该循环会永远执行下去!\n");
}
return_type function_name( parameter list );
int max(int num1, int num2);
//在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int max(int, int);
//声明
double balance[10];
//初始化
double balance[5] = {
1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {
1000.0, 2.0, 3.4, 7.0, 50.0};
//赋值
balance[4] = 50.0;
//多维数组
int threedim[5][10][4];
int a[3][4] = {
0,1,2,3,4,5,6,7,8,9,10,11};
//先定义枚举类型,再定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
//定义枚举类型的同时定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
//省略枚举名称,直接定义枚举变量
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
/指针声明//
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
//使用/
#include
int main ()
{
int var = 20; /* 实际变量的声明 */
int *ip; /* 指针变量的声明 */
ip = &var; /* 在指针变量中存储 var 的地址 */
printf("Address of var variable: %p\n", &var );
/* 在指针变量中存储的地址 */
printf("Address stored in ip variable: %p\n", ip );
/* 使用指针访问值 */
printf("Value of *ip variable: %d\n", *ip );
return 0;
}
/传指针给函数/
#include
#include
void getSeconds(unsigned long *par);
int main ()
{
unsigned long sec;
getSeconds( &sec );
/* 输出实际值 */
printf("Number of seconds: %ld\n", sec );
return 0;
}
void getSeconds(unsigned long *par)
{
/* 获取当前的秒数 */
*par = time( NULL );
return;
}
/从函数返回指针/
#include
#include
#include
/* 要生成和返回随机数的函数 */
int * getRandom( )
{
static int r[10];
int i;
/* 设置种子 */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i)
{
r[i] = rand();
printf("%d\n", r[i] );
}
return r;
}
/* 要调用上面定义函数的主函数 */
int main ()
{
/* 一个指向整数的指针 */
int *p;
int i;
p = getRandom();
for ( i = 0; i < 10; i++ )
{
printf("*(p + [%d]) : %d\n", i, *(p + i) );
}
return 0;
}
/函数指针/
#include
int max(int x, int y)
{
return x > y ? x : y;
}
int main(void)
{
/* p 是函数指针 */
int (* p)(int, int) = & max; // &可以省略
int a, b, c, d;
printf("请输入三个数字:");
scanf("%d %d %d", & a, & b, & c);
/* 与直接调用函数等价,d = max(max(a, b), c) */
d = p(p(a, b), c);
printf("最大的数字是: %d\n", d);
return 0;
}
/回调函数/
#include
#include
// 回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue();
}
// 获取随机值
int getNextRandomValue(void)
{
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10, getNextRandomValue);
for(int i = 0; i < 10; i++) {
printf("%d ", myarray[i]);
}
printf("\n");
return 0;
}
/结构指针/
struct Books *struct_pointer;
//现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:
struct_pointer = &Book1;
//为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:
struct_pointer->title;
#include
#include
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
return 0;
}
main(){
struct bs{
unsigned a:1;
unsigned b:3;
unsigned c:4;
} bit,*pbit;
bit.a=1; /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */
bit.b=7; /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */
bit.c=15; /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */
printf("%d,%d,%d\n",bit.a,bit.b,bit.c); /* 以整型量格式输出三个域的内容 */
pbit=&bit; /* 把位域变量 bit 的地址送给指针变量 pbit */
pbit->a=0; /* 用指针方式给位域 a 重新赋值,赋为 0 */
pbit->b&=3; /* 使用了复合的位运算符 "&=",相当于:pbit->b=pbit->b&3,位域 b 中原有值为 7,与 3 作按位与运算的结果为 3(111&011=011,十进制值为 3) */
pbit->c|=1; /* 使用了复合位运算符"|=",相当于:pbit->c=pbit->c|1,其结果为 15 */
printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c); /* 用指针方式输出了这三个域的值 */
}
//无名位域
struct k{
int a:1;
int :2; /* 该 2 位不能使用 */
int b:3;
int c:2;
};
typedef
typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
C 输入 & 输出
标准输入stdin键盘
标准输出stdout屏幕
标准错误stderr您的屏幕
getchar() & putchar() 函数
gets() & puts() 函数
scanf() 和 printf() 函数
C 文件读写
//打开文件
FILE *fopen( const char * filename, const char * mode );
//在这里,filename 是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个:
//模式描述
//r打开一个已有的文本文件,允许读取文件。
//w打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为/零长度,重新写入。
//a打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。
//r+打开一个文本文件,允许读写文件。
//w+打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。
//a+打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。
//如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式:
//"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
//关闭文件
int fclose( FILE *fp );
//写入文件
int fputc( int c, FILE *fp );
//函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回 EOF。您可以使用下面的函数来把一个以 null 结尾的字符串写入到流中:
int fputs( const char *s, FILE *fp );
//函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF。您也可以使用 int fprintf(FILE *fp,const char *format, ...) 函数来写把一个字符串写入到文件中。尝试下面的实例:
//实例
#include
int main()
{
FILE *fp = NULL;
fp = fopen("/tmp/test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}
//读取文件
//下面是从文件读取单个字符的最简单的函数:
int fgetc( FILE * fp );
//fgetc() 函数从 fp 所指向的输入文件中读取一个字符。返回值是读取的字符,如果发生错误则返回 EOF。下面的函数允许您从流中读取一个字符串:
char *fgets( char *buf, int n, FILE *fp );
//函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
//如果这个函数在读取最后一个字符之前就遇到一个换行符 '\n' 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。您也可以使用 int fscanf(FILE *fp, const char *format, ...) 函数来从文件中读取字符串,但是在遇到第一个空格和换行符时,它会停止读取。
//实例
#include
int main()
{
FILE *fp = NULL;
char buff[255];
fp = fopen("/tmp/test.txt", "r");
fscanf(fp, "%s", buff);
printf("1: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("2: %s\n", buff );
fgets(buff, 255, (FILE*)fp);
printf("3: %s\n", buff );
fclose(fp);
}
//二进制 I/O 函数
//下面两个函数用于二进制输入和输出:
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
size_t fwrite(const void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
//这两个函数都是用于存储块的读写 - 通常是数组或结构体。
//预定义宏
//ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。
//宏描述
//__DATE__当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量。
//__TIME__当前时间,一个以 "HH:MM:SS" 格式表示的字符常量。
//__FILE__这会包含当前文件名,一个字符串常量。
//__LINE__这会包含当前行号,一个十进制常量。
//__STDC__当编译器以 ANSI 标准编译时,则定义为 1。
#include
main()
{
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}
//预处理器运算符
//*宏延续运算符(\)
//一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符(\)。例如:
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
//*字符串常量化运算符(#)
//在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表。例如:
#include
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}
//当上面的代码被编译和执行时,它会产生下列结果:
Carole and Debra: We love you!
//*标记粘贴运算符(##)
//宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。例如:
#include
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
//当上面的代码被编译和执行时,它会产生下列结果:
token34 = 40
//这是怎么发生的,因为这个实例会从编译器产生下列的实际输出:
printf ("token34 = %d", token34);
//*defined() 运算符
//预处理器 defined 运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义,则值为真(非零)。如果指定的标识符未定义,则值为假(零)。下面的实例演示了 defined() 运算符的用法:
#include
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void)
{
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
//当上面的代码被编译和执行时,它会产生下列结果:
Here is the message: You wish!
//引用头文件的语法
//使用预处理指令 #include 可以引用用户和系统头文件。它的形式有以下两种:
#include
//这种形式用于引用系统头文件。它在系统目录的标准列表中搜索名为 file 的文件。在编译源代码时,您可以通过 -I 选项把目录前置在该列表前。
#include "file"
//这种形式用于引用用户头文件。它在包含当前文件的目录中搜索名为 file 的文件。在编译源代码时,您可以通过 -I 选项把目录前置在该列表前。
//定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。
//在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。
//使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。
//使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。
//使用宏 va_end 来清理赋予 va_list 变量的内存。
//现在让我们按照上面的步骤,来编写一个带有可变数量参数的函数,并返回它们的平均值:
//实例
#include
#include
double average(int num,...)
{
va_list valist;
double sum = 0.0;
int i;
/* 为 num 个参数初始化 valist */
va_start(valist, num);
/* 访问所有赋给 valist 的参数 */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* 清理为 valist 保留的内存 */
va_end(valist);
return sum/num;
}
int main()
{
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}
//当上面的代码被编译和执行时,它会产生下列结果。应该指出的是,函数 average() 被调用两次,每次第一个参数都是表示被传的可变参数的总数。省略号被用来传递可变数量的参数。
Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000~
void *calloc(int num, int size);
在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。
void free(void *address);
该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。
void *malloc(int num);
在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。
void *realloc(void *address, int newsize);
该函数重新分配内存,把内存扩展到 newsize。