面向过程

74 阅读11分钟

流程控制

Cpp/C

Java

它的if,else,else if while for 和C语言基本一样

break

break不仅可以退出最小循环,还可以退出任意循环

 public class q
 {
     public static  void main(String[] args)
     {
         flag_outer:
         for(int i=0;i<100;i++)
         {
 ​
             for(int j=0;j<10;j++)
             {
                 System.out.println(j);
                 if(j==5)
                     break flag_outer;//语句输出5后,他会退出那个名字叫 flag_outer:的循环
             }
         }
     }
 }
 ​

switch

switch后面是一个(),()中表达式返回的结果是一个等值,

这个等值的类型可以为:int,byte,short,char,String,枚举类型

 switch (表达式) 
 {
     case 值1:
          语句序列1;
          [break];
     case 值2:
          语句序列2;
          [break];
     [default:默认语句;]
 }

存储位置/作用域规则

全局

全局变量就是在main函数以外的地方

他是有一个默认值,0的

当局部变量与全局变量重名时,遵循就近原则,使用局部变量

局部

局部变量是子函数被调用时,才会分配空间

如果局部变量不初始化,可能是0xcccccccc

局部变量在栈里面,

ebp-4开始

Java

final

final修饰一个变量,变量的值不可以改变

final修饰指针,那么地址值就不可以改变,指针指向的数据可以改变

final修饰函数,那么这个函数不可以被该类的子类重写:

final修饰class,代表没有子类,该类不可以被继承:

Cpp/C

static

开始于全局变量

extern

main.c

 #include <stdio.h>
 ​
 int count;
 extern void output();
 ​
 int main()
 {
     count = 5;
     output();
 }

a.c

 #include <stdio.h>
 ​
 extern int count;
 ​
 void output(void)
 ​
 {
     count -= 1;
     printf("count is %d\n", count);
 }

现在main.c要用a.c的函数

于是main.c就

 extern void output();

然后就直接用函数 output();

在a.c的代码中,要用main.c的变量

于是在a.c中就

 extern int count;

然后就直接可以使用

const

运算符

Cpp/C

优先级

对于同级的运算符都采用

左-->右看齐

优先级别符号说明例子
1[] () . ->左-->右左-->右
1[]数组下标arr[index]
1()圆括号
1.成员选择(对象node.next
1->成员选择(指针)ptr->value
2sizeof ,(type) ,!, &, *, --, ++ ,~ ,-,左-->右左-->右
2sizeof长度运算符sizeof(arr)
2(type)强制类型转换(int)3.4
2!逻辑非运算符!1
2&取地址运算符&value
2*取值运算符*ptr
2--自减运算符--value--,value--
2++自增运算符++value,value++
2-负号-100
3/ ,*, %左-->右左-->右
4+, -左-->右左-->右
5<<,>>左-->右左-->右
6>, >=, <, <=左-->右左-->右
7==, !=左-->右左-->右
8&
9异或
10
11&&逻辑与
12逻辑或
13? :三目运算符左<--右
14=, ^=, &=, >>=, <<=, -=, +=, %= ,*=, /=, =左到右左到右
15逗号运算符左到右左到右
 #include <stdio.h>
 ​
 int main()
 {
     int x[10]={0,1,2,3,4,5,6,7,8,9}, *p1;
 ​
     x[3]; 
     
     p1=x+3, *p1++;
     //假设p1=0x00000000
     //*和++的优先级一样,采用从右到左的结合顺序,所以*p1++等价于*(p1++) 
     //对于p1=x+3, *p1++;的过程
     
     //先 p1+=3于是p1=0x00000003
     
     //对于*p1++
     //(1).先是p1++,但是p1还是0x00000003,因为是p1++,而不是++p1,
     //(2).*p1++=*(0x00000003)=3
     
     //如果你输出printf("%d",*p1),相当于对p1发生了一个引用,也就*(0x0000004) ,不要忘记了p1++ 
 }
  

Java

+

+ 可以实现字符串的拼接

+的作用: (1)表示正数 (2)表示相加操作 (3)进行字符串的拼接

--/++

Java的--和++是一样的

位运算

<< 左移

>> 有符号右移 : 如果是负数,右移动添加的是1

>>> 无符号右移:

优先级

数据类型

C

基本数据类型

C语言有无符号的 BYTE,WORD,DWORD,QWORD

对于Java语言,它的byte,word,dword,qword 是有符号数的范围,比如byte max=127

数组

typedef的进阶应用

 #include <stdio.h>
 typedef int Arr_six[6];
 int main()
 {
 ​
     Arr_six tmp =
     {
          5,4,3,2,1,0
     };
     printf("%d", tmp[5]);
     return 0;
 }

这里的话,达到了把a替换为A的快捷效果

Arr_six tmp –>int tmp[6]

自动初始化

(1)

int arr[]={0}

(2)

int a[5][5] = { {1, 2}, {3, 4, 5}, {6}, {7}, {0, 8} };

他的输出 可以看到 那些没有初始化的值,他把他作为0来初始话 对于一维的数组他也是一样的原理

二维数组如何遍历

设有数组arr [ 行 m ] [ 列 n ],现在要访问 arr [ y ] [ x ]

&arr [ y ] [ x ]]=&arr [ 0 ] [ 0 ] +y * sizeof(int)* n +x * sizeof(int); 地址 = y * n + x

我们的寻址时没有用到他的行数m,也就是他有几行,我们的编译器其实别不在乎...左边第一个参数

此刻如果你有这样的寻址方式

void show(int *arr, int n, int m){ 
    int i, j;
    for(i = 0; i < n; i++) {
        for(j = 0; j < m; j++) 
            printf("%d ", a[i][j]); 
        printf("\n"); 
    } 
}

就是错误的,因为编译器在不知道他的行数与列数的情况下,尤其是列数的情况下,他是无法当作二位的数组来识别的

应该这样

void show(int *a, int n, int m) { 
    int i, j; 
    for(i = 0; i < n; i++) { 
        for(j = 0; j < m; j++) 
            printf("%d ", *(a + i*m + j));
        printf("\n"); 
    } 
}

//注意上面那种表达方式

enum

和Python的字典类型有点相像

如何定义枚举类型

enum My_DAY  {  MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7  } ;
enum My_DAY day;
//或者
My_DAY day;

② 或者

enum  {  MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7 } day ;

③ 或者

enum DAY
{
      MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7
} day;

初始化的排序问题

1.默认的初始化方式如果你不去代入数字

MON, TUE, WED, THU, FRI, SAT, SUN 他就默认为 MON=0, TUE=1, WED=2, THU=3, FRI,=4 SAT=5, SUN=6 如果你加了数字,他就自然按照你给出的顺序来赋值 MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7

2.如果你给出一个数字,他就按照那个头数字,自动往下面排列

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};

那么上面就等效于

enum DAY
{
      MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6, SUN=7
} ;

当然你也可以这样


enum DAY
{
      MON=1, TUE, WED=100, THU, FRI, SAT, SUN
} day;

就等效于

enum DAY
{
      MON=1, TUE=2, WED=100, THU=102, FRI=103, SAT=104, SUN=105
} day;

一个简单的例子


#include <stdio.h>
#include <stdlib.h>
int main()
{

    enum dqx{ one = 10, two, three };

    dqx me = three;

    printf("%d", me);

    return 0;
}
//输出12

指针

数组指针

  1. 指针数组,本质是数组,装的指针

  2. 数组指针,本质是指针,指向一个一定长度的数组 ,

    变量存储的是数组的地址,虽然等价于数组第一个元素的地址,但是性质不一样,而数组的地址储存的是第一个元素的地址

    这就形成了一个二维的指针

#include <stdio.h>

int main() {


	int a[5] = { 1,2,3,4,5 };
	int b[5] = { 6,7,8,9,10 };
	int c[10] = { 11,12,13,14,15,16,17,18,19,20 };


	int* y[2] = { a,b };

	int(*x)[5] = (int(*)[5])c;

	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 5; j++)
			printf("%d ", y[i][j]);
		puts("");
	}

	for(int i=0;i<2;i++)
		for (int ii = 0; ii < 5; ii++)
		printf("%p : % d\n", x + i, x[i][ii]);
	puts("");
}


//x++实际上是5*4的字节宽度

x装的是数组的地址

*x装的是数组第一个元素的地址

所以**x才可以获取成员

下面这个例题很本质

#include <stdio.h>

int main() {


	char c[] = {
				  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
				 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
				 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
				 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
				 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
				 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
				 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
				 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
				 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
				 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
				100,101,102,103,104,105,106,107,108,109,
				110,111,112,113,114,115,116,117,118,119,
				120,121,122,123,124,125,126,127,128,129,
				130,131,132,133,134,135,136,137,138,139,
				140,141,142,143,144,145,146,147,148,149,
				150,151,152,153,154,155,156,157,158,159,
				160,161,162,163,164,165,166,167,168,169,
				170,171,172,173,174,175,176,177,178,179,
				180,181,182,183,184,185,186,187,188,189,
				190,191,192,193,194,195,196,197,198,199,
	};
	int (*p1)[5] = (int(*)[5])c;
	char (*p2)[2][3] = (char(*)[2][3])c;
	char (*p3)[2][3][4] = (char(*)[2][3][4])c;

	printf("%08X\n", p1[2][2]);//2*5*sizeof(int)+2*sizeof(int)=2*20+2*4=48
	printf("%d\n", p2[3][2][5]);//3*2*3*sizeof(char)+5*sizeof(char)=3*6+2*3+5=29
	printf("%d\n", p3[3][2][5][7]);//3*2*3*4+2*3*4+5*4+7=123
	return 0;
}


//x++实际上是5*4的字节宽度

函数指针

不可以参与运算

可以大小比较

针对下面那种语法格式

声明 int ( * pfun ) (int, int); 定义 pfun = fun; 使用 int a = (*pfun)(5, 7);

代码示意

#include <stdio.h>

int fun(int, int);

int main() 
{
    int (*pfun)(int, int);
    pfun = &fun;
    int a = (*pfun)(5, 7); //通过函数指针调用函数,注意它的语法格式
    printf("%d\n", a);
    return 0;
}

int fun(int a, int b)
{
    return a + b;
}

回调函数

不知道怎么解释,反正例子能看动

#include <stdio.h>

int arr[] = { 99, 88, 77, 66, 55, 44, 33, 22, 11,00 };
void copy(int* array, int len, int (*ptr_func)(void))//这里有个函数指针类型   
{
    for (int i = 0; i < len; i++)
        array[i] = ptr_func();
}
int get_value(void)
{
    static int ecx = 0;
    return arr[ecx++];
}
int main(void)
{
    int myarr[10];
    copy(myarr, 10, get_value);
    for (int i = 0; i < 10; i++) 
        printf("%d ", myarr[i]);
    printf("\n");
    return 0;
}

多级指针的共性

加上*

砍掉*

共用体

优点

节约内存,共用体的大小以其中元素的最大值为代表

共用体应用场景

通信中的数据包会用到共用体:因为不知道对方会发一个什么包过来,用共用体的话就很简单了,定义几种格式的包,收到包之后就可以直接根据包的格式取出数据。

#include<stdio.h>
union Data
{
	int   i;//4
	float f;//4
	char  str[20];
};
int main()
{
	printf("%d", sizeof(Data));
}

这个共用体的大小是20字节,而不是28

数据的初始化与访问

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   double f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   data.i = 10;
   printf( "data.i : %d\n", data.i);
   
   data.f = 3.1415926;
   printf( "data.f : %f\n", data.f);
   
   strcpy( data.str, "dqx");
   printf( "data.str : %s\n", data.str);
   
 
   printf( "data.i : %d\n", data.i);
   printf( "data.f : %f\n", data.f);
   printf( "data.str : %s\n", data.str);
   
   
 
   return 0;
}

编程时经常会需要判断机器是大端机还是小端机,此时使用union就非常方便:

union var
{
    char str;
    int data;
};
var.data=0x01020304;

大端机高位存在低位.低位存高位

如果str=0x01,就是大段…

如果str=0x04,就是小端

位域

可能是为了节约内存

struct data
{
    int a:8;
    int b:2;
    int c:6;
}buff;

表示什么意思?

int 是4个字节,一个32位的长度

现在

a开了8bit位的长度,max=1111 1111 b

b开了2bit位的长度,max=0000 0011 b

c开了6bit位的长度,max=0011 1111 b

如果超出了范围,会取对应后n位的二进制位

Java

byte 数据类型,它的取值范围为 [-128 ,127]

Java 变量声明必须初始化

java中无论:字母,数字,符号,中文都是字符类型的常量,都占用2个字节。

字符串String

他这个字符串是多态的分配,也就是你也无法清楚的知道string会malloc出多少个字节

直接使用,无需导包

String类不可以被继承,不能有子类

String底层是一个char类型的数组

 //通过构造器来创建对象:
 
 String s1 = new String();
 String s2 = new String("abc");
 String s3 = new String(new char[]{'a','b','c'});
 String s4 = "abc";
char charAt(int index) 用于返回指定索引处的字符
int compareTo(Object o) | int compareTo(String anotherString) 返回 0,<0 ,>0
int compareToIgnoreCase(String str) 比较两个字符串,不考虑大小写。 返回 0,<0 ,>0

my_srting.length() 返回长度

my_srting.isEmpty() 是否为空

my_srting.charAt(1) 返回索引值的成员

str1.equals(str2) 2个字符串是否相等

s10.substring(3) //字符串的截取[3,..]

s10.substring(3, 6) // 字符串的截取[3,5]

s10.concat("pppp")//字符串的合并/拼接操作:

s11.replace('a', 'u') // 把a替换为u

s13.toUpperCase()// 大写

s13.toLowerCase() //小写

数组

他不可以写

 char x[]="123"; //这会报错

基本数组

int x[]={1,2,3}; //貌似不可以写长度 int x[3]={1,2,3};

new出来的数组

byte []x=new byte[128];
int[] arr = {12,23,45};
int[] arr = new int[]{12,23,45};

数组类

涉及的数组类函数

import java.util.Arrays;

String sz_arr=Arrays.toString(My_Arr); //参数是My_Arr,返回数组对应的字符串
Arrays.fill(My_Arr,0); // 参数是My_Arr,把My_Arr的每一位都初始化为0,类似于memset
Arrays.sort(My_Arr);//参数是My_Arr,My_Arr会被排序,按照升序
int index= Arrays.binarySearch(My_Arr,4)//返回My_Arr的中值为4的index
int[] NewArr=Arrays.copyOf(My_Arr,4);//把My_Arr的前4个成员复制给NewArr
int[] newArr = Arrays.copyOfRange(My_Arr,1,4);//把My_Arr 的1,2,3位置复制给newArr 
boolean flag =Arrays.equals(arr3,arr4)//比较arr3数组和arr4数组是否相等
System.arraycopy(SrcArr,1,DestArr,2,3);//从SrcArr[1]位置开始复制3个到DestArr[2]位置

二维数组

import java.util.Arrays;
public class q
{

    public static  void main(String[] args)
    {
        int[][] lp_tmp = new int[3][];
        int[] Arr_tmp = {1,2,3};
        
        lp_tmp[0] = Arr_tmp;
        lp_tmp[1] = new int[]{4,5,6,7};
        lp_tmp[2] = new int[]{9,10};
    }
}

布尔类型

布尔类型:

boolean类型有两个常量值,true和false,在内存中占一位(不是一个字节)

不可以使用 0 或非 0 的整数替代 true 和 false ,这点和C语言不同

枚举

java的枚举是用的字符串值?

C的枚举是用字符串替代数值

package tmp;
class EnumTest {
    enum emm{ dqx, vm4 , ok }//这里是一个声明罢了,和实现无关
    emm whoami;
}
public class q{
    public static void main(String[] args)
    {
        EnumTest etmp = new EnumTest();
        etmp.whoami = EnumTest.emm.dqx;
        System.out.println(etmp.whoami);
    }
}

浮点数

默认浮点数是doule

如果要是float,得在数字末尾加上