栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

CLanguage

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CLanguage

C 1.什么是C语言

1.1 二进制指令—>汇编语言(一些助记符,例如英文字母)—>高级语言

1.2 编译器,编辑和翻译。编辑,即对代码进行剪切、复制一些文本操作;翻译,将代码翻译(变成计算机能够识别的语言,还需要链接器)

2.第一个C语言程序

2.1 函数分为两部分,函数头和函数体。函数头又由声明、函数名和输入参数组成。int 声明函数返回类型,同时申请int类型数据所占空间大小(int,4个字节);函数名,整个项目只能有一个main函数,而且整个项目的代码都是从main函数开始;输入参数,一开始也是要先声明。

2.2 main()里面无参数(或者由viod),这表示不用输入参数。如果有的函数名前面有viod,表示可以不用有输出

2.3 stdio.h 为标准输入输出库文件。std:standard;i:input;o:output. 使用scanf(输入函数)也需要引此文件

#include 
int main()   
{
    printf("hello")
    return 0;
}
3.数据类型

3.1 C语言中没有字符串类型。字符串,也就是由单个字符组成。这matlab不一样,matlab中字符串是作为一个整体存在,而字符组成的叫做字符数组

3.2 计算机存储字符是以ASCiLL码存储的

4.变量和常量

4.1 定义变量。定义变量的第一步就是先定义变量,即申请空间,而这个空间的名字就是变量名。“=”后面是常量,即把常量存储在名叫变量名的空间中。在C语言中,使用变量的第一步就是先声明变量(也是说先申请空间)。定义变量的同时也初始化了变量,如果指定一个值,那就是把指定的值存储进去,如果定义时不指定,系统会随机指定一个值放进去。

int a=0;

4.2 在同一个{}中,同一个变量不能重定义,即变量名不能被定义两次,即使是被不同数据类型所定义。

// 这不算在同一{}中
{
    int a=0;
    {int a=1;} //这有点类似全局变量和局部变量的关系
}
// 重定义
{
    int a=0;
    char a='e'; //这也算重定义
}

4.3

  • 局部变量:{}内部所定义。
  • 全局变量:所有的{}外部所定义。全局变量,一个源文件定义后,可以在同一项目的其他的源文件使用,但需要先声明
test1.c
int a=0;
{
}
test2.c 
extern int a //后面的数据类型和变量必须和全部变量被声明保持一致

4.4 变量名是个标识符,但有时可以表示地址。scanf和printf函数,会在缓存区读取数据。

  • int a 变量a就是个标识符。
  • char a[] 变量a可以表示地址。

4.5

  • 全局变量的作用域是整个项目,而生命周期是整个项目
  • 局部变量的作用域是变量所在的局部范围。而生命周期可能大于作用域,即不是从作用域出来后就被销毁了(用static修饰的变量)。

4.6 常量

  • #define定义的标识符常量
#define max 10;
#define max “scaklhj”
5.字符串、转义字符和注释

5.1 字符串,自动以结尾,而这个是我们敲完字符串时,系统自动帮我们加的

char a='asdf';//系统自动输入
sizeof(a);   //我们会得到a所占空间大小是5个字节,因为算一个字节。
strlen(a);  //结果为4,strlen和printf都是遇到就停,只看表面,而sizeof是计算所占空间大小的

5.2

  • ddd 表示八进制的数字,d的个数不限,但不能超过8(8进制最大是7)
  • xdd表示十六进制的数字
  • 空格也算字符

5.3

  • %f float
  • %lf double
  • %zu 打印sizeof()返回的值,也可以用%d
6.数组

6.1 数组:一组相同类型元素的组合

int    arr1[]={0}    // []没有数(不分配空间),当后面赋值后,会自动分配空间,这里就自动分配4个字节的空间
int    arr2[2]={0}   // [2]代表2个元素,但后面只有一个数,则系统会自动补充0到数组里面
char   arr3[]={'0'} 
char   arr4[2]={'0'} // 系统会自动补充 
double arr5[]={0}
10 操作符
  • 除号的两端都是整数时,执行的是整数除法,如果两端只要有一个浮点数就执行浮点数的除法
float a=10.876;
printf("%10.1f",a);
//"10.1f"是指宽度为10,且保留小数点后1位(四舍五入),如果变量宽度不够,则前面补空格
//如果给的宽度小于变量的宽度则会自动增加宽度,能够正好符合变量的宽度。
//".1f"会根据变量的宽度自动调整
  • 取模操作符两个操作符只能是整数

  • 初始化:创建变量的同时给变量一个值

    int a=10;//初始化
    a=20;    //赋值
    
  • 单目操作符:只有一个操作数的操作符

int a=10;
printf("%d",sizeof(a));     //sizeof是个单目操作符,后面可以跟变量也可以跟变量类型
printf("%d",sizeof(int));
printf("%d",sizeof a);      //因为sizeof是单目操作符,所以后面可以不加括号直接跟变
printf("%d",sizeof int);    //量名,但不可以直接跟数据类型
  • (数据类型):强制类型转换

    int a=3.14;         //3.14 这种字面浮点数,编译器默认理解为double类型
    int a=(int) 3.14;  //3.14强制转换成整形
    
  • 逗号表达式:逗号隔开的一串表达式

    • 特点:从左到右依次计算,整个表达式的结果是最后一个表达式的结果
int a=20;
int b=3;
int c=5;
inr d=(c=a-2,a=b+c,c-3);
  • 下标引用操作符

  • int arr[10]={3};
    arr[3];           //[]就是下标操作符,arr和3就是[]的操作符
                              
    int n=3;         
    arr[n]=10;       //[]是操作符,里面可以放变量,当定义arr时,[]是定义语法的一种
                     //形式,所以里面需要放常量
    
11 关键字
  • typedef

    类型定义。即类型重命名

    typedef unsigned int unite_32
    // 给unsigned int(无符号整形)重新起了个名字,叫做unite_32
    
  • static

    修饰局部变量。该变量被修饰后,叫做静态局部变量。

    • 改变变量的生命周期,让静态局部变量除了作用域依然存在,直到程序结束,生命周期才结束
    • 将原本存在栈区的局部变量,存到静态区。(静态区一般存储全局变量和静态变量)

    修饰全局变量

    • 被修饰后,使得这个全局变量只能在本源文件被使用
    • 全局变量具有外部链接属性和内部链接,一旦被static是修饰后,外部链接属性就被消除了,只剩下内部链接属性

    修饰函数

    • 被修饰后,使得这个函数只能在本源文件使用,不能在其他源文件内使用
    • 函数具有外部链接属性和内部链接,一旦被static是修饰后,外部链接属性就被消除了,只剩下内部链接属性
  • const:常属性

    一个变量一旦被const修饰后,后面就不能该变,但可以在初始化的时候改变.使得这个变量具有了常属性,本质还是变量

    const int a=1;        //如果想改变,可以从在初始化的地方改变 
    a=2;                 // a的值不会被改变
    
  • extern:声明外部符号的.即在其他源文件定义的

    如果一个在其他源文件定义的函数,或者全局变量,如果想被目标源文件使用,必须先声明

    test1.c
    int add(int x,int y)
    int a;//a是全局变量
    test2.c
    extern int a;
    extern int add(int x,inty);
    
12 #define定义常量和宏
#define max 100
//定义常量
#define add(x,y) ((x)+(y))
//定义宏。add:宏名;x,y:参数;((x)+(y)):宏体
//参数可以是任意类型
13 指针
// 用指针和不用指针加一的区别(针对数组)
    int arr[2] = {0};
    int* p1 = arr;
    int* p2 = &arr;
    printf("%pn", p1;      //指针的类型决定了指针向前或向后走一步有多大(字节)
    printf("%pn", p1+1);   //int型指针,+1就是向前走四个字节,所以第二个和第四
    printf("%pn", p2);     //个输出相等 
    printf("%pn", p2+1);


    printf("%pn", arr);      //这里没有把运用指针就直接打印,而且加1,这里向前或向后加
    printf("%pn", arr+1);    //加一,取决于数组名前面是否有&,有&代表&arr是整个数组的
    printf("%pn", &arr);     //地址,加一,要前进整个数组大小的字节;没有&则是数组首元 
    printf("%pn", &arr+1);   //素的地址,加一,取决于这个数组的类型,整型数组则前进4

控制语句
  • C语言的三种基本结构

顺序结构

选择结构

循环结构

  • if 后面如果想跟多条语句,后面必须加{}。;代表一条语句语句的结束。{}里面也会有许多以;结尾的语句,但对于整个程序来说,{}是if的一条语句,if{}else{}又是整个程序的一条语句

  • 1010&&age<20 这是如果age=5因为先判断5>10为逻辑假0,0<20,为逻辑真,所以10

  • 控制语句整体,算一条语句 if {}else{} 是一条语句

  • else与离它最近的if匹配

  • 程序到return后,就代表结束该部分程序,不是结束整个程序,有返回值,这块程序就结束了

  • 当拿一个变量(单纯的变量)判断是否等于一个常量,可以让常量放在前面,3==a

  • 表达式不能赋值 变量就只是个变量 不要变形

    num%2==2   //num%2是个表达式,不能被赋值,不用写成2=num%2
    
  • code

//判断一个数是否为奇数	
	int num= 0;
	scanf("%d",&num);
	if ( num % 2==1) {
		printf("奇数");

	}
	else {
		printf("不是奇数");
	}
//输出1—100之间的奇数
int i = 0;
for (i = 0; i <= 100;i++) {
	if (i % 2 == 1) {
	printf("%d",i) }
}
// switch语句
//switch (整型表达式){
//语句项;        
//}
//语句项:是一些case语句
//case 整型常量表达式(字符也可以,字符也属于整型)
//语句;
//这个语句有两种形式
//1:表达式;
//2:控制语句(控制语句整体算是一个语句相对于整个程序)。控制语句有两种形式,有时用{},有时不
//用,7但要当成一个整体 !    
  • 在循环中,continue会跳过本次循环,也会跳过continue后面的语句
int ch=getchar(); //获取字符
putchar(ch)       //打印字符
  • 敲入回车键就是输入n 敲入回车键 才把字符输入缓存区 而scanf是只要缓存区有字符,就会读取

  • 输入n(就是回车键) 默认输入完毕

  • 内存缓存区,在程序执行完后,即出int main{}后就被清空,在程序没结束之前内存区有多少字符,scanf函数和getchar函数就得按顺序读取字符

  • 当用scanf和getchar函数获得输入时,最后需要敲一下回车键,这是回车键有三个作用

    • 1 换行输出

    • 2 将键盘输入的字符传到内存缓存区

    • 3 将换行字符一同传到缓存区。scanf会把换行符当成空白字符,而getchar会把换行符存到变量

    • 一旦敲回车键,scanf会立马读取

    • scanf函数遇到空白字符,就会停止读取(读取数字时,读取字符不会)

      scanf("%4d %d %d",&a,&b,&c); // scanf会忽略空白字符
      //输入:123 空格 12 回车 123
      //当敲回车时,就把123 空格输入进了缓冲区,这时scanf就开始读取了,当读到3时,虽然还没读满4个数,但还是会停止,(scanf遇到空白字符就停止),然后接着从非空白字符读取下一个数字,赋值给b,而不是把空白字符拿走。对于字符串,拿走后,如果还有空间,自动补  
      

  • getchar和scanf读到非打印字符时,会把相应的效果输入在窗口,比如ASCILL值 9 用putchar和printf显示时,会空4个格;ASCILL值 32

4.15
  • if 后面默认跟一条语句,如果想跟多条语句,可以加{}

  • for(i=0;i<10;i++)可以表示循环10次,如果i从0开始,建议i<10这样写

  • for(; ;)判断部分省略,判断部分恒为真

  • 初始化部分最好不要省略

  • =是赋值,==是判断

  • if 中的continue满足条件 会跳过的代码

    do
    {
    if (i==5)               
    continue;                  // 当i=5时,continue会跳过后面的代码
    i++;                       // 所以,到4之后就会死循环
    }while(i<10);
    
    • 在定义浮点数时,float通不过,可以尝试double
    • int a=5/4 a会取整数部分,不是先得出小数部分,在取余,这是整数的除法,浮点数的除法是要先求出小数的 (这里将被除数或者除数变成浮点数,执行的就是浮点数的除法,即将5或者4变成5.0 4.0)
4.17
  • for循环 里面只要有一个判断条件不满足,就结束循环
for (;L<=mid+3,R>=mid;L++,R--)
  • 写程序最好写一部分,测一部分
  • scanf(”%dn“)scanf在读取时会读完所有对应字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-33iWmHrr-1652186920778)(C:Users20961AppDataRoamingTyporatypora-user-imagesimage-20220417220403133.png)]

4.19
  • 当不调用函数的时候,形参就不开辟空间

  • int arr[10]={0};
    int p=arr;
    arr[2]=*(arr+2);
    *P=arr[0]=*(arr+0)// p代表的就是首元素的地址,不要把他看成变量名
    // 一个变量名只有在定义的时候(即int p),表示是个名字,但在后面使用时,要把他看成p所代表的数据
    
    
  • void func(int* arr)
    {
        int b=sizeof(arr)/sizeof(arr[0]); 
        // 在这里sizeof(arr)是首元素的地址,因为传进来的就是首元素的地址,则算的的首元素地址所占内存的大小
        
    }
    
    int main()
    { 
    
    int arr[10]={12};
    int a=sizeof(arr)/sizeof(arr[0]);
    // 这里sizeof(arr),arr代表的是整个数组,计算的是数组所占空间空间的大小
    }
    
  • 思考问题时,想的应该是内存里的数据,而不是谁代表数据,写的时候要把代表数据的变量名写出来,因为你不可能

​ 把数据直接写出来,就像不可能把地址写出来,找个东西代表他,但简单的数据10,直接写出来就行,没必要

​ 在找个变量来代表他

  • 链式访问:把一个函数的返回值方程另一个函数的参数
  • printf返回的是在屏幕打印字符的个数。23这是两个字符(’2‘和‘3’)
4.22
  • 自己定义的函数文件使用时,就是用双引号,标准库文件就是尖括号

    #include// 标准
    #include"add.c"  // 自定义
    
  • 模块化的意思就是把源文件分开写

    包含头文件,相当于把头文件的内容拷贝过来

  • %d:打印有符号整数(会有正负数)
    %u:打印无符号整数

4.23 函数栈帧的创建与销毁
  • 每一个函数的调用,都要在栈区创建一个空间

  • 压栈(push):给栈顶放一个元素

    出栈(pop):从栈顶删除一个元素

    栈顶指针:esp用来记录栈底的地址

    栈底指针:edp

    call:调用

    寄存器是独立于内存的,集成到cpu的

    十六进制后面要加h,在反汇编时

  • 在调用函数之前先将实参压栈(临时拷贝,在main创建的栈帧外 ),再调用函数。在调用函数会马上创建栈帧而且不会再为形参申请空间是main函数增加栈帧

  • 返回值时,是将值放在eax寄存器中 返回值时通过寄存器带回来的,没有在在栈区开辟空间

  • 在变量创建创建空间,两个变量的空间位置一定紧紧挨着

扫雷游戏+操作符
  1. 正数的原码、反码和补码一样

    负数的反码是符号位不变,其他位加取反,而反码加一就是补码

  2. 画红框中的意思如下,对a进行左移,并不会改变a的值

    • 移位操作符只针对整数,不支持浮点数
    • 无符号整数,可以看成正数
  3. 正数的原码、反码和补码是相同的,所以看到补码的符号位,可直接写出它的原码

操作符(2)
  1. int a=10;
    printf("%d",a--);
    // 打印10
    int a=10;
    test(a--);
    //传进去也还是10
    
  2. sizeof 是操作符,不是函数。如果是函数,sizeof a后面应该是(a)

  3. "abc"=="abcsf";//这是在比较地址
    //应该用strcmp();比较字符串
    
  4. b=(a>b?a:b);将条件表达式用括号标起来

  5. []

    // []是个双目操作符,左值和右值在某些情况下可以交换
    // arr[7]和7[arr]是等同的,sizeof也是个操作符,可以看作和+ -一样的乘除,满足交换律
    // 在定义数组时即,int arr[10]不能写成int 10[arr]
    //arr[7]-->*(arr+7)--->*(7+arr)--->7[arr]
    // arr就是首元素的地址
    // arr+7就是跳过7个元素,指向第八个元素
    // *(arr+7)就是8个元素
    
  6. 结构体传参,传值和传址

    struct stu
    {
      char name[20];
      int age;
      double score;
    };
    void set_stu(struct stu ss)  // 传值进去,编译器会在程序运行时,建立一个新的
    {                            // struct stu ss 最后改变的是ss不是s   
      // ss.name="sgj"; // ss.name是地址,不能以这样给数组赋值
       //ss.name[20]="sgj";// 正确赋值,按照正常的赋值方法赋值就行 
      strcopy(ss.name,"sgj");// 正确赋值
      ss.age=20;
      ss.score=100.0;
    }
    int main()
    {
        struct stu ={0};
        set_stu(s); // 传值
        print_stu(s); //传值
        return 0;
    }
    
    // 传址
    struct stu
    {
      char name[20];
      int age;
      double score;
    };
    void set_stu(struct stu* ss)  // 传址进去,编译器会在程序运行时,改变的是s
    {                               
      // ss.name="sgj"; // ss.name是地址,不能以这样给数组赋值
      strcopy(ss->name,"sgj");// 正确赋值
      ss->age=20; // 传址进去,用->形式调用参数
      ss->score=100.0;
    }
    void printf_stu(struct stu* ps)
    {
        printf("%s %d %lfn",ps->name,ps->age,ps->score);
    }
    int main()
    {
        struct stu s={0};
        set_stu(&s); // 传值
        print_stu(&s); //传值
        return 0;
    }
    
    
  7. 位操作符(只适用于整数)

    • &(按位与):只要有一个为零,对应位就为0

    • 正数和负数的按位与,运算出来的数,在不溢出的情况下,结果是正数

    • |(按位或):只要有一个为1,对应位就为1

    • 正数和负数的按位与,运算出来的数,在不溢出的情况下,结果是负数

    • ^(按位异或):相同为0,相异为1

    • 正数和负数的按位与,运算出来的数,在不溢出的情况下,结果是负数

    • (ab)a=b (ab)b=a 0^a=a a^a=0

      异或支持交换律即353=335

  8. sizeof :操作符

    • 计算的是变量所占内存空间的大小
    • 计算的是类型所创建的变量占据内存空间的大小,单位是字节
    sizeof(int);
    sizeof(a);
    sizeof a;// 没有sizeof int
    
  9. 0可以看成正数,其反码为0000000000000000000(原反补一致)。~0为-1

  10. ~的应用:将二进制位的某一位进行修改

    int a=13;
    // 补码:00000000 00000000 00000000 00001101
    // 将1101前面的一位变成1
    // 00000000 00000000 00000000 00001101
    //               |(按位或)
    // 00000000 00000000 00000000 00010000  1<<4
    //               =
    // 00000000 00000000 00000000 00011101
    // 即a|=(1<<4)
    // 上面是将某一位变成1
    // -----------------------------------------------------
    // 将上面变成的位变回0
    // 00000000 00000000 00000000 00011101
    //               &(按位与)
    // 11111111 11111111 11111111 11101111
    //               =
    // 00000000 00000000 00000000 00001101
    
    // 11111111 11111111 11111111 11101111
    //                ^
    //                | 
    //~(00000000 00000000 00000000 00010000)
    //                ^
    //                | 
    //         1<<4
    // 即 a&=~(1<<4)
    // 这是将某位变成0
    
操作符(3)
  • 无符号整型提升,提升了精度,一般不会改变大小

  • char 类型所存储的数的范围:-128~127

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UiL5MDGD-1652186920780)(C:/Users/20961/AppData/Roaming/Typora/typora-user-images/image-20220510193303416.png)]

  • 截断是从低位到高位截,即从右到左截

  • 优先级是指相邻操作符

  • 尽量写出唯一路径,或者加括号

    • 算术运算符 + - * / %

      赋值运算符 =

      long a=4可能会整型提升,因为4是int型,存到long中,整型提升。但算术运算(上面的算术运算符),是以缺省值运行的

  • 整型提升是按照变量的数据类型的符号位来进行提升的

  • 操作数都要转成排名最高的数据类型

  • 这告诉我们以后,尽量不去碰复杂表达式,宁愿多写点步骤,也不可为了方便写在一起

    对于表达式,先从整体上来看,找出优先级最大的操作符,如果有若干个相同的操作符,系统并不能指定将这几个优先级相同的操作符,全部计算完,再计算次一级的操作符

    不同的编译器有不同的规定,有的是全部算完,有的是先算一部分

    // 例:
    // Vs2019
    int a=1;
    int b=(++a)+(++a)+(++a);
    // 结果就是b=12
    // 这里就是先将括号先计算完。值得注意的是,+操作符的的左操作数的获取 // 是在获取右操作数之后求值的
    // Linux
    // 结果b=10
    // 那这里就是先将前两个括号计算出来。值得注意的是,和Vs一样,+操作符的的左操作数的获取是在获取右操作数之后求值的
    

    • 0xb6的二进制数是10110110,如果是写成32位就是00000000000000000000000010110110,因为a是char类型只能放八位,所以从左到右截断就是11111111,放到char类型的空间(也即1个字节),又因为char是有符号,所以存进去的最高位成了符号位,下面进行==操作时,会进行整型提升,因为最高位时是1,所以提升后的结果是11111111111111111111111111111111,所以成了负数。

    • 启发:内存空间存的只是一串二进制序列,当程序有不同的要求,会将这些二进制序列转换成对应的符号,例如,printf(“%c”,a),系统就会把存在a中的二进制序列先进行整型提升,然后找对应的字符

    • short是2个字节

    • 整型提升就是将存储的二进制序列进行精度提升

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873394.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号