1.const 修饰指针
1.1const修饰变量
变量是可以修改的,如果把一个变量的地址交给一个指针变量,通过指针变量的也可以修改这个变量,但是如果我们希望加上一些限制,不能被修改,,怎么做呢?这就是const的作用。
#include<stdio.h>
int main(void)
{
const int a = 10; //const前加,a具有了常属性(不能被修改了)
//a是不是常量呢?虽然a是不能被修改的,但是本质上还是变量,也称为常变量
//a = 20;a会报错
int arr[a];//在C++中没有报错,const修饰的变量就是常量,在C语言中会报错
printf("%d\n", a);
return 0;
}
1.2 const修饰指针变量
1.2.1 const修饰指针变量的时候,放在*的右边
#include<stdio.h>
int main(void)
{
int a = 10;
int b = 20;
int* const p = &a; //const修饰指针变量的时候,放在*的右边,
//p = &b;//这里会报错
*p = 100;//没有报错
printf("%d\n", a); //100
//const限制的是指针变量本身,指针变量不能再指向其他变量了
//但是可以通过指针变量,修改指针变量指向的内容
return 0;
}
1.2.2 const修饰指针变量的时候,放在*的左边
#include<stdio.h>
int main(void)
{
int a = 10;
int b = 20;
int const* p = &a; //const修饰指针变量时,放在*的左边,
p = &b;//没有报错
//*p = 100;//会报错
printf("%d\n", a);//10
//限制的是:指针指向的内容,不能通过指针来修改指向的内容
//但是可以修改指针变量本身的值(修改的指针变量的指向)
return 0;
}
总的来说,凡是const后面的内容均不可修改。如果*的右边跟左边都有const修饰,
int const * const p; ,那么*p=0和p=* n 都是会报错的,const在两边修饰任何一种都不可修改!
2.assert断言
assert.h头文件定义了宏assert(),用于在运行时确保程序符合指定条件,,如果不符合,就报错终止运行,这个宏被称为“断言”。
assert(p != NULL);
assert()宏接受一个表达式作为参数,如果该表达式为真(返回值不为0),assert()不会产生任何作用,程序继续运行,如果一个表达式为假(返回值为0),assert()就会报错。
作用:不仅可以自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制,如果已经确认程序没有任何问题,不需要再做断言,就在#include<assert.h>语句的前面,定义一个宏NDEBUG。
然后重新编译程序,编译器会禁用文件中所有的assert()语句,如果程序又出现问题,可以移除这条#define NDEBUG 指令,(或者把它注释掉),再次编译,这样就重新启用了assert()语句。
assert()语句的缺点是,因为引入了额外的检查,增加了程序运行的时间。
3.指针的使用和传址调用
3.1 strlen的模拟实现
参数 str 接收一个字符串的起始地址,然后开始统计字符串中\0之前的字符个数,最终返回长度。
止。如果要模拟实现只要从起始地址开始向后逐个字符的遍历,只要不是\字符,计数器就+1,这样直到\0就停。
这里为什么会这样,因为在主函数my_strlen后面的括号里面写了NULL(被挡住了),这个是有问题的,没有直接报错是因为加了宏#define NDEBUG,,如果没写,是直接在assert(str != NULL);这里断言出错,但是如果里面传的实参是arr,程序会正常运行,打印出数组长度6。
3.2 传值调用和传址调用
写一个函数,交换两个整型变量的值。
//写一个函数,交换两个整数的内容
#include<stdio.h>
void swap2(int *pa, int*pb)
{
int tmp = 0;
tmp = *pa; //tmp=a
*pa = *pb; //a=b
*pb = tmp; //b=tmp
}
int main(void)
{
int a = 10;
int b = 20;
printf("交换前:a=%d b=%d\n", a, b); //10 20
swap2(&a, &b);//传址调用
printf("交换后:a=%d b=%d\n", a, b); //20 10
return 0;
}
//当实参传递给形参的时候,形参是实参的一份临时拷贝
//对形参的修改不会影响实参的
4.数组名的理解
sizeof (数组名), sizeof 中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节.
&数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)
那么这三个地址表示是完全一样的吗?给每一个数组后面加1来看。