C#学习C语言,知识点记录篇(摘抄自菜鸟教程)

  1. .extern
    函数内声明变量 x 和 y 为外部变量
extern int x;
extern int y;
  1. 占位符

    %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位无符号整数
    
  2. printf

printf(" thingy 为 %d , count 为 %d\n", thingy, count);
  1. register 存储类
    register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)。
{
     
   register int  miles;
}

寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 ‘register’ 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

  1. ^异或运算:
    首先异或表示当两个数的二进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)实现两个值的交换,而不必使用临时变量。

  2. sizeof()
    sizeof() 返回变量的大小。sizeof(a) 将返回 4,其中 a 是整数。
    & 返回变量的地址。&a; 将给出变量的实际地址。

  3. 指向一个变量。*a; 将指向一个变量。
    ? : 条件表达式如果条件为真 ? 则值为 X : 否则值为 Y

  4. 无限循环

 for( ; ; )
   {
     
      printf("该循环会永远执行下去!\n");
   }
  1. 函数申明
return_type function_name( parameter list );
int max(int num1, int num2);
//在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:
int max(int, int);
  1. 数组申明
//声明
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};
  1. 枚举
//先定义枚举类型,再定义枚举变量
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;
  1. 指针
/指针声明//
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;
}
  1. 结构
/结构指针/
struct Books *struct_pointer;
//现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:
struct_pointer = &Book1;
//为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,如下所示:
struct_pointer->title;
  1. 共用体
#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;
}
  1. 位域
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;
};
  1. typedef
    typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
    typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

  2. C 输入 & 输出
    标准输入stdin键盘
    标准输出stdout屏幕
    标准错误stderr您的屏幕
    getchar() & putchar() 函数
    gets() & puts() 函数
    scanf() 和 printf() 函数

  3. 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);
//这两个函数都是用于存储块的读写 - 通常是数组或结构体。
  1. C 预处理器
    #define定义宏
    #include包含一个源代码文件
    #undef取消已定义的宏
    #ifdef如果宏已经定义,则返回真
    #ifndef如果宏没有定义,则返回真
    #if如果给定条件为真,则编译下面代码
    #else#if 的替代方案
    #elif如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
    #endif结束一个 #if……#else 条件编译块
    #error当遇到标准错误时,输出错误消息
    #pragma使用标准化方法,向编译器发布特殊的命令到编译器中
//预定义宏
//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!
  1. C 头文件
//引用头文件的语法
//使用预处理指令 #include 可以引用用户和系统头文件。它的形式有以下两种:
#include 
//这种形式用于引用系统头文件。它在系统目录的标准列表中搜索名为 file 的文件。在编译源代码时,您可以通过 -I 选项把目录前置在该列表前。
#include "file"
//这种形式用于引用用户头文件。它在包含当前文件的目录中搜索名为 file 的文件。在编译源代码时,您可以通过 -I 选项把目录前置在该列表前。
  1. 可变参数
    需要使用 stdarg.h 头文件~
//定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。
//在函数定义中创建一个 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~
  1. C 内存管理
    C 语言为内存的分配和管理提供了几个函数。这些函数可以在 头文件中找到。
    序号函数和描述
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。

你可能感兴趣的:(C语言,指针,字符串,c语言)