流程控制
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 | ||
| 2 | sizeof ,(type) ,!, &, *, --, ++ ,~ ,-, | 左-->右 | 左-->右 | ||
| 2 | sizeof | 长度运算符 | 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
指针
数组指针
-
指针数组,本质是数组,装的指针
-
数组指针,本质是指针,指向一个一定长度的数组 ,
变量存储的是数组的地址,虽然等价于数组第一个元素的地址,但是性质不一样,而数组的地址储存的是第一个元素的地址
这就形成了一个二维的指针
#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,得在数字末尾加上