C语言学习笔记

1.指针和数组的关系

▶指针指向第一个元素之前一个位置
for(vp = &values[5-1]; vp >= &values[0];vp--)
{
    *vp = 0;
}
//vp指针最后会停在&values[0]前面一个位置,即“&values[-1]”

以上代码实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。

标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

▶数组名与指针之间的等价关系
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int * p = arr;

//以下全部等价
printf("%d\n", arr[2]);
printf("%d\n", p[2]);
printf("%d\n", 2[arr]);

printf("%d\n", *(arr+2)); 
printf("%d\n", *(p+2));
printf("%d\n", *(2+arr));

2.一些调试实例

▶数组越界导致的死循环:
int i = 0;
int arr[10] = {0};
for(i=0; i<=12; i++)
{
    arr[i] = 0;
    printf("hehe\n");
}

内存分为栈区、堆区、静态区。在栈区中,变量创建从高地址向低地址依次创建,所以上述代码中,变量i处于高地址(在VS编译器中处于arr[12],即与数组间隔2),数组arr依次从低向高地址访问,越界到arr[12]会操作变量i,导致死循环。

3.关于const

const修饰变量,使其变为常变量,具有不可修改属性。下面探讨一下相关用法。

▶const修饰指针变量
int n = 10;
int m = 20;

//const放在*左边,修饰的是*p,表示指针指向的内容不能通过指针来改变,但是指针变量本身是可以修改的
const int *p = &n;
*p = 5;  //err,不可修改
p = &m;  //ok,可修改

//const放在*右边,修饰的是指针变量p,表示指针变量不能改变,但是指针指向的内容可以改变
int* const p = &n;
*p = 5;  //ok,可修改
p = &m;  //err,不可修改

当const放在*左边的时候,有没有可能“通过指针p”改变其指向的内容呢?

int n = 10;
int m = 20;

const int* p = &n;
int* p2 = p;
*p2 = 5;
printf("%d\n", n);  //5
int** p3 = &p;
**p3 = 6;
printf("%d\n", n);  //6

由上,在C中通过“中转指针”或二级指针,都是可以间接改变p指向的内容。

但是第5行代码会在编译时报出警告:warning C4090: “初始化”: 不同的“const”限定符

当const放在*右边的时候,同样可以间接改变p指向的内容。不同的是第8行代码会报出警告。

(题外,在C++中对const限制更为严格,无法从const变量进行取址中转)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值