再谈C指针


1.指针是一个保存对象地址的变量。这里要注意的是,指针跟地址概念的不同,
指针是一种地址变量,通常也叫指针变量,统称指针。而地址则是地址变量的值。

2.对一个一般类型的地址进行sizeof运算,结果是4个字节,而a[0]由于代表了一个数组,
sizeof(a[0])的结果是整个数组的长度8x9xsizeof(int),并非4个字节。
具有数组类型的地址跟数组名一样都是一个符号地址常量,因此它必定是一个右值。

3(*p)[9]就是这种直接声明符加[]的形式。

p左边的*在这里不是取值运算符,而是一个声明符,它指出p是一个指针。
而()括号是不能去掉的,如果去掉了,由于[]运算符优先级比*高,p就会先跟[]结合,
这样p就变成了一个指针数组,而不是指向数组的指针。


4.为什么除了第一维之外其他维数的都要写明大小
int p[][6];
定义一个指针的时候,首先必须定出指针的类型,由于这(第一维的值)是一个指向数组的指针,
如果数组的元素的类型定下来了,那么这个指针的类型也就定下来了。前面说过,
C语言的多维数组实质上是数组的嵌套,那么所指向数组的元素必定具有“”数组类型“”,
也就是说,这个数组的元素是一个具有6个int元素的数组,
因此,p定义的时候,必须指定第二维的上界,这样才能把p的类型定下来。

5.字符串常量与一般数组的主要区别,是字符串常量存放在静态存储区,而一般数组
(非static)则是在栈中静态分配的。

6.声明修饰符的先后问题
对于存储类说明符、类型说明符和类型限定符的排列顺序,C标准并没有规定其顺序,
谁嵌套谁都可以。换言之,上面的声明可以写成:
int static const i=10, j=20, k=30;或者const int static i=10, j=20, k=30;
这无所谓,跟原声明是一样的。再举一个有趣的例子:

上面举的例子是变量的声明,函数的声明也同样道理,例如:
static const int func(void);


7.
typedef int a[10];
typedef void (*p)(void);
他们会以为a[10]是int的别名,(*p)(void)是void的别名,但这样的别名看起来又似乎不是合法的名字,
于是陷入困惑之中。
实际上,上面的语句把a声明为具有10个int元素的数组的类型别名,p是一种函数指针的类型别名。
虽然在功能上,typedef可以看作一个跟int PARA分离的动作,但语法上typedef属于存储类声明说明符,
因此严格来说,typedef int PARA整个是一个完整的声明。
例子:
typedef int a[2];
void main()
{
 a b;
 b[0] = 1;
 b[1] = 2;
 printf("%d/n", b[0]);
}

8.
const int *p;与int * const p的区别,这两个声明的中文名称常常搞得混乱不堪。
第一个声明的const是声明说明符,它修饰p所指向的对象,但p仍然是可变的,
这意味着p是一个指向常量的指针,简称常量指针。第二个声明的const是声明符的一部分,
它修饰的对象是p,这意味着p是一个常量,而且是一个指针类型的常量,简称指针常量。


//例子:
int a = 2;
int b = 3;
const int *p = &a;
//p的值可以改变 改变后*p值改变 但是不能直接给*p赋值
//比如 *p = 3;是错的 但是可以p = &b;则*p 的值变为3
int * const p2 = &a;

//p2是常量 既不能改变p2的值 p2 = &b是错的 但是可以改变*p2的值
//比如*p2 = 10; 则此时 a = 10;

*p2 = 10;
p = &b;
printf("*p  %d /n",*p);
printf("*p2  %d /n",*p2); 

 

 

“野指针”产生的3种原因:
指针变量没有被初始化。指针变量刚被创建时不会自动成为NULL指针,它的默认值是随机的,它会乱指一气;
指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针;
指针操作超越了变量的作用范围;


防止野指针的发生

用malloc或new申请内存之后,应该立即检查指针值是否为NULL。
不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作。
动态内存的申请与释放必须配对,防止内存泄漏。
用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。


大存储类型的指针向小存储类型的指针转换,会带来错误风险
  如  int a =0x12345678;
        int *pa = &a;
        char *pc = (char*)pa;
   (*pa)的数值为0x12345678; (*pc)的数值为0x12;

 


小存储类型的指针向大存储类型的指针转换,会带来极大的错误风险
  如  char b = 0x12;
        char *pb = &b;
        int *pd = (int*)pb;
    *pb的数值为0x12,*pd 的数值未知;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值