1.在 C 语言中,可以使用 const 关键字来修饰指针,以限制指针所指向的内存空间的访问权限。
int *const ptr3 = arr;
*ptr3 = 998;
ptr3 指向数组 arr,可以修改ptr3指向的元素的值,但不能修改 ptr3 所指向的元素,例如:ptr = arr ;×
int const *ptr = &a; //常目标指针,只能换人不能修改值,
ptr =&b;
2.冒泡排序的便捷写法
for (i = 0; i < 3; ++i){ // 使用冒泡排序对数组进行排序
for (j = 0; j < 2 - i; ++j){
if (arr[j] > arr[j + 1])arr[j] ^= arr[j + 1] ^= arr[j] ^= arr[j + 1];
}
}
3.测量数组长度
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(arr) / sizeof(arr[0]);
4.位运算符
左边丢弃,右边补0 ;
int a = 2;
int b = a << 1; // 将a的二进制位向左移动1位;b is 4,
a : 00000000000000000000000000000010
b : 0|000000000000000000000000000010+0
右边丢弃,左边补0;
int a = 10;
int b = a >> 1;
a : 00000000000000000000000000001010
b : 0+0000000000000000000000000000101|0
5.负数存储
负数-1要存放在内存中,内存中存放的是二进制的补码 (255 - 1)
6.位运算符
7.结构体访问符区别:
定义:
struct student { char name[20]; int age; };
struct student stu = {"Alice", 18};
点操作:(通过结构体变量名访问结构体成员)
printf("Name: %s, Age: %d\n", stu.name, stu.age);
箭头操作:(通过结构体指针访问结构体成员)
struct student *pstu = &stu;
printf("Name: %s, Age: %d\n", pstu->name, pstu->age);
8.指针加减数
野指针避免,int* p = NULL; // 当你不知道给什么值的时候用,即使赋值NULL
9.指针相减的作用
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("%d\n", &arr[9] - &arr[0]); // 得到指针和指针之间元素的个数
10.判断系统的大小端
因为小端序的机器在存储多字节数据时,低字节在前,高字节在后,即 0x01020304 在小端序的机器中存储为 0x04030201。如果 a 的低字节不为 1,则说明当前机器的字节序为大端序。
int a = 1;
char* pa = (char*)&a; // 这里需要进行一下强制类型转换
if(*pa == 1)printf("小端");
else printf("大端");
11.无符号类型unsigned____
有符号 char 的范围是: -128 ~ 127
无符号 char 的范围是: 0 ~ 255
12.浮点数的储存
二进制浮点数V可以表示成以下形式: (-1)^S * M * 2^E
① (-1)^s 表示符号位,当 s = 0,V为正数;当s = 1, v为负数
② M表示有效数字,大于等于1,小于2
③ 2^E 表示指数位
例如: 二进制:101.1 → 1.011 * 2^2 → (-1) ^0 * 1.011 * 2^2
存为:s=0 M=1.011 E=2
13.数组指针的写法
for(i=0; i<10; i++)
{
//以下写法全部等价
printf("%d ", p[i]);
printf("%d ", *(p+i));
printf("%d ", *(arr+i));
printf("%d ", arr[i]); //arr[i] == *(arr+i) == *(p+i) == p[i]
}
指针数组:int* parr1[10];
数组指针:int (*parr2)[10];
存放数组指针的数组: int (*parr3[10])[5];
14.二维数组传参
15.函数指针
int Add(int x, int y)return x + y;
int (*pf)(int, int) = &Add; //函数指针
函数指针数组:
pfArr 就是函数指针数组,{}内部为函数名
int (*pfArr[5])(int, int) = {NULL, Add, Sub, Mul, Div};
使用:
int input =0;
for(input =1;input<5;input++) (pfArr[input])(x, y); //分别执行各个函数
16.C语言的回调函数
void Calc(int (*pf)(int, int))
{
int x = 0;
int y = 0;
printf("请输入2个操作数:>");
scanf("%d %d", &x, &y);
printf("%d\n", pf(x, y));
}
使用:在别的函数内:Calc(Add);//Add为一个新的函数
17.指针的使用注意
如果没有应初始化 :int* p = NULL; // 初始化为NULL
指针的解引用:在解引用之前,需要确保指针指向的内存块已经被分配。
if (p == NULL) {return 1;}
用完之后释放指针:
free(p); // 释放内存块
p = NULL; // 将指针赋值为NULL
需要确保指针的类型匹配:
int a = 10;
float b = 3.14;
int* p = &a; // int类型的指针指向int类型的变量
float* q = &b; // float类型的指针指向float类型的变量
18.C语言操作寄存器
对一个寄存器的位6进行赋值为1的操作:
寄存器:
19.带参数的宏定义
以避免受大括号、分号、运算符等优先级的影响。
20.指针的详细使用
1.
char ch = 'a';
char *p = &ch; ------->*p == p[0] ='a';
2.
char ch[] = {'a','\0'};-----------ch 等于 &ch[0] ------->*ch==ch[0]=='a'
3.
int a;
int *p = &a;
a = 10;
*p = 9;
printf("a = %d\n", a); // 输出结果为9
printf("&a = %d\n", &a); // 输出a的地址,即变量a在内存中的地址
printf("p = %d\n", p); // 输出p的值,即a的地址
printf("p = %d\n", &p); // 输出p的地址,在32位系统中输出结果为4,64位系统中输出结果为8
printf("*p = %d\n", *p); // 输出p所指向的值,即a的值,输出结果为9
4.
int b[5] = {1, 2, 3, 4, 5};
printf("b = %d ,*b = %d, *(b+1) = %d, *(b+2) = %d\n",b, *b, *(b+1), *(b+2));
//b = -13328 ,*b = 1, *(b+1) = 2, *(b+2) = 3
5.字符串数组输出模式
char *str = "I love U";
int i, length;
length = strlen(str);
for (i = 0; i < length; i++)
{
printf("%c", str[i]);
}
//I love U
6.
char arr[] = "abcdef";
char *p = arr;
printf("*p %c\n", *p); // a
printf("p %c\n", p[0]); // abcdef
printf("p %s\n", p); // abcdef
printf("arr %s\n", arr); // abcdef
printf("&p %d\n", &p); //-13312