数组
一、一维数组的创建与初始化
创建数组时数组空间为整体开辟整体释放,在内存中是连续存放,在定义时就已经确定数组大小(下标不可为0),且不可被整体赋值。在数组的创建过程中,如果进行了初始化则可不指定数组的大小,多维数组按照一维数组进行理解。
数组传参发生降维,降维成指向其(数组)内部元素类型的指针。
数组名一般情况下都指的是首元素的地址,但如果sizeof()单独出现以及&后跟数组名时表示的是整个数组
int s[5];
//表示数组首元素地址
printf("%d\n", sizeof(s+1));//结果为4/8,指针的具体大小根据编译器的不同大小不同
//表示整个数组
printf("%d\n", sizeof(s));//结果为20
二、数组传参(函数)
由于在传参过程中如果拷贝整个指针会导致效率大大降低甚至导致栈溢出,所以数组传参要发降维问题,函数内数组作为参数时,实参为首元素地址,形参为指针。
在访问结构体成员时也同样要发生类似的操作,用指向结构体的指针来指代结构体。
typedef struct node{
int a;
int b;
}point;
void pop(int* p){
}
int main(){
point a;
int* p=a;
pop(p);
return 0;
}
传参样例:
//用数组的形式传递参数,不需要指定参数的大小,传的只是数组首元素的地址。
void test(int arr[])
{}
//也可以传入数组大小
void test(int arr[10])
{}
//数组降维,用指针进行接收,传的是数组首元素的地址
void test(int *arr)
{}
//二维数组传参,第一个方括号可以空,但是第二个不可以空
void test(int arr[][5])
{}
void test(int arr[4][5])
{}
//传过去的是二维数组的数组名,即数组首元素的地址,也就是第一行的地址,第一行也是个数组,用一个数组指针接收(比较少用)
void test(int (*arr)[5])
{}
三、字符数组
char a[]={'a','x','d'};
//此处由于结尾没有'\0',strlen的机制是遇到'\0'即停止,所以在结尾没有'\0'时为随机数
//strlen(a)为随机数
//sizeof(a)为3
char a[]={'a','x','d','\0'};
//strlen(a)为3
//sizeof(a)为4
char* a="axd";//或char a[]="axd"
//直接通过""定义字符串时,会自动在结尾补'\0',不需要自行补充,但'\0'依旧会占据一个字节
//strlen(a)为3
//sizeof(a)为4
char c[5]={'a', 'b', '\0', 'c', '\0'};
printf("%s", c);//结果为ab,因为字符串结束标志位'\0'
操作符
一、运算优先级
注:①++/–高于解引用;
②解引用高于±*/
③±*/高于位运算;
④位运算高于+=、-=、/=、*=;
%操作两边必须是整数。
二、二进制中的操作符
1、位运算基本介绍
与运算:&
同1则1,否则为0;
或运算:|
同0为0,否则为1
非运算:~
1取0 0 取1
异或运算:^
两者相等为0,不等为1
移位运算操作符:<< 左移 ; >> 右移
①**<<左移:**左边抛弃末尾补0;负数对反码的补码进行移位操作;相当于乘2;
②**>> 右移:有符号的补符号位**,无符号的补0;相当于除以2。
2、反码与补码
**反码:**正数的反码为原码本身,负数反码符号位不变,剩余的数字位取反;
**补码:**正数的补码为原码本身,负数的补码为反码+1 。