*C语言有关指针的变量声明中的几个易错点
转至:http://my.oschina.net/ypimgt/blog/108265
我们都知道,至少听说过指针对于C语言中的重要意义,但是在使用指针时却常常让我们痛不欲生,这里有几个在声明指针有关的变量时易错的地方。
1. int* 和 int * (注意空格的位置)
对于单变量声明,即一条语句中只声明一个指针变量的情况,没有区别;原因是C语言允许形式的自由性。即以下两种声明方式效果相同。
int *a;
int* a;
对于一条语句中声明多个指针变量的情况,有很大区别。
int* a, b,c;
对于这条语句,常会造成我们的误解:认为声明了三个整型指针。但是正解是:只有a是整型指针,b和c都是普通的整数。
这里的星号“*”号只是声明变量a的一部分,以上的变量声明相当于:
int *a;
int b;
int c;
如果希望在一条语句中声明多个整型指针,正确的方式应该是:
int *a, *b, *c;
2. typedef 和 #define 在创建类型别名时的区别
在C语言中实现创建类型别名的方法有两种:一种是使用typedef;一种是使用#define。使用方法也类似。
typedef int NEW_INT_TYPE1; /*int在前*/
NEW_INT_TYPE1 a1 = 1;
#define NEW_INT_TYPE2 int /*int在后*/
NEW_INT_TYPE2 a2 = 2;
printf("%d /n",a1);
printf("%d /n",a2);
但是如果需要创建新类型名时,我们只应该使用typedef,而不是#define。因为#define仅仅是在编译的时候做简单的替换工作,所以在处理一些问题上会有缺陷。
int m=2;
typedef int* NEW_INT_TYPE3; /*int在前*/
NEW_INT_TYPE3 a3, a4;
a3 = &m; /*指针赋值*/
a4 = &m; /*指针赋值*/
#define NEW_INT_TYPE4 int* /*int在后*/
NEW_INT_TYPE4 a5, a6=6;
a5 = &m; /*指针赋值*/
printf("%d /n",*a3);
printf("%d /n",*a4);
printf("%d /n",*a5);
printf("%d /n",a6);
/*运行结果:
2
2
2
6*/
分析:a3和a4是整型指针,a5是整型指针,但是a6只是整型(只要记住#define 仅仅是做替换操作,将NEW_INT_TYPE4替换为int*,而int* a5, a6; 的结果是“a5是整型指针,a6是整数”);
3. “常量指针”和”指向常量的指针”
对于常量变量:int const a 和const int a
效果相同;都是声明一个整型的变量a,且a是常量,其值不能改变(由于其值不能改变,其赋值方式只有两种:一种是声明时初始化,如int const
a=1; 一种是其作为函数的形式参数,函数被调用时用实参来初始化)。
对于含有指针时,根据声明时const和星号"*" 的位置,有三种形式:
|
形式 |
名称 |
说明 |
分析方法 |
| int const *p | 指向常量的指针 | 能修改指针本身的值,但是不能修改其指向的值 | 从变量标识符开始(即从右向左),①*p指向一个整数;②const修饰”*p”,表示*p是一个常量,即p指向的值是一个常量。所以,不可以修改”*p”,即不可修改p指向的值。 |
| const int *p | 指向常量的指针 | 同上 | 同上 |
| int * const p | 指针常量 | 能修改其指向的整型的值,但是不能修改指针本身的值 | 从变量标识符开始(即从右向左),const修饰p,表示p是常量,即不能修改p本身,但p指向的值可以修改。 |
总结,区分这两种类型的顺序是:从右向左看,一步一步的确定。
衍生的更为特殊的指针:指向常量的常量指针,声明方式是 int const * const p; 对于它,“指针本身的值”和“指向的值”都不能修改。
注意:有常量声明的变量只有两种赋值方式;一种是在声明时直接赋值,如int m; int * const p = &m;
另一种方法针对在函数中声明的形式参数,在函数被调用时被赋值,例如:当是不需要修改数组的元素时,形式参数使用int const
a[],即a指向的内容不能修改。
void firstTest(){
int m = 2;
int * const p = &m;/*指针p 是常量指针,要在声明时赋值*/
/*不能写为 int * const p; p = &m;*/
printf("%d /n",*p);
*p = 5; /*可以改变指针p 指向的值*/
printf("%d /n",*p);
getchar();
p=&m; /*编译报错,因为不能改变指针p本身 的值,*/
}
void secondTest(){
int m = 2;
int n = 3;
int const *p; /*指向常量的指针*/
p = &m;
/*也可以写为 int const *p = &m; */
printf("%d /n",*p);
p = &n; /*可以改变指针p本身的值*/
printf("%d /n", *p);
*p = 3;/* 编译报错,不能修改它指向的值。虽然这里*p的值本来就是2*/
}
*C语言有关指针的变量声明中的几个易错点的更多相关文章
- Go语言规格说明书 之 变量声明(Variable/Short variable declarations)
go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,完整的介绍Go语 ...
- scala学习笔记:变量声明中的模式
先看个正常的写法: scala> val x = 1 x: Int = 1 体会一下元组的写法: scala> val (x,y,z)=(1,2,3) x: Int = 1 y: Int ...
- go语言入门教程:基本语法之变量声明及注意事项
一.变量的使用 1.1 什么是变量 变量是为存储特定类型的值而提供给内存位置的名称.在go中声明变量有多种语法. 所以变量的本质就是一小块内存,用于存储数据,在程序运行过程中数值可以改变 1.2 声明 ...
- C语言讲义——指针(pointer)
指针是C语言最重要的特性之一, 也是最容易被误解的特性之一. 现代计算机把内存分割为字节(Byte), 每个字节都有唯一的地址(Address), 如果内存中有n个字节,可以把地址看做0~n-1的数. ...
- C语言全局变量的定义与声明
C语言中全局变量的定义与声明困扰着许多C语言初学者.本文讲述了全局变量定义与声明的用法,而且本为也将阐述这种用法的内在原理.我们先从两个错误例子引入,以下两个例程都在vc6.0平台上测试. 两种错误例 ...
- 浅谈C语言变量声明的解析
C语言本身提供了一种不甚明确的变量声明方式——基于使用的声明,如int *a,本质上是声明了*a的类型为int,所以得到了a的类型为指向int的指针.对于简单类型,这样声明并不会对代码产生多大的阅读障 ...
- C语言指针与数组的定义与声明易错分析
部分摘自<C语言深度解剖> 1.定义为数组,声明为指针 在文件1中定义: char a[100]; 在文件2中声明: extern char *a; //这样是错误的 这里的extern告 ...
- 【C语言探索之旅】 第一部分第四课第二章:变量的世界之变量声明
内容简介 1.课程大纲 2.第一部分第四课第二章:变量的世界之变量声明 3.第一部分第四课第三章预告:变量的世界之显示变量内容 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布 ...
- C语言变量声明内存分配
转载: C语言变量声明内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...
随机推荐
- FileSaver.js 介绍
这是著名开源项目 FileSaver.js 的 README.md,我把它翻译成中文.发出来,方便自己和他人阅读. 项目地址:https://github.com/eligrey/FileSaver. ...
- MongoDB的安装与配置
一.安装包安装: 1.安装 #1.安装路径为D:\MongoDB,将D:\MongoDB\bin目录加入环境变量 #2.新建目录与文件D:\MongoDB\data\dbD:\MongoDB\log\ ...
- CTF---密码学入门第三题 奇怪的短信
奇怪的短信分值:10 来源: Ayn 难度:易 参与人数:5117人 Get Flag:2623人 答题人数:2858人 解题通过率:92% 收到一条奇怪的短信: 335321414374744361 ...
- BZOJ 1001: [BeiJing2006]狼抓兔子【最大流/SPFA+最小割,多解】
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 23822 Solved: 6012[Submit][ ...
- 2017"百度之星"程序设计大赛 - 初赛(A)-1001.小C的倍数问题(HDU6108) 1005.今夕何夕-蔡勒公式 (HDU6112)
补完题?不存在的. 这么久了,还是一条咸鱼,看一堆乱七八糟的东西,写一堆没用的水题,一点进步都没有,还是那么菜,菜的掉渣. 这个百毒之星初赛A还会写两道最简单的水题,初赛B一点也不会,菜的难过... ...
- vue -- v-cloak解决刷新或者加载出现闪烁(显示变量)
在使用vue绑定数据的时候,渲染页面时会出现变量闪烁,例如 <div class="#app"> <p>{{value.name}}</p> & ...
- 1.移植3.4内核-分析内核启动过程,重新分区,烧写jffs2文件系统
1.在上章-移植uboot里.我们来分析下uboot是如何进入到内核的 首先,uboot启动内核是通过bootcmd命令行实现的,在我们之前移植的bootcmd命令行如下所示: bootcmd=nan ...
- Spark高可用集群搭建
Spark高可用集群搭建 node1 node2 node3 1.node1修改spark-env.sh,注释掉hadoop(就不用开启Hadoop集群了),添加如下语句 export ...
- CSS3 background-size 属性
定义和用法 background-size 属性规定背景图像的尺寸. 默认值: auto 继承性: no 版本: CSS3 JavaScript 语法: object.style.background ...
- 在MAC电脑上抓取iphone数据包的方法
一.说明: 1.整个抓包操作的过程中,手机必须一直通过USB链接MAC电脑 2.手机系统要求在IOS5以上,因为使用的RVI技术在IOS5以后的系统中才有 3.抓包过程中,手机可以使用任何网络2G.3 ...