基于指针的数据类型与指针运算小结_C 语言

1.指针的数据类型小结

有关指针的数据类型

定义 含义
int i; 定义整形变量
int *p; 定义只想整型数据的指针变量p
int a[n]; 定义整形数组a,它有n个元素
int *p[n]; 定义指针数组p,它由n个指向整形数据类型的指针元素组成
int (*p)[n]; 定义指向n个元素的一位数组的指针变量
int f(); f为带回整形函数值的函数
int *p(); p为带回一个指针的函数,该指针指向整形数据。
int (*p)(); p为指向函数的指针,该函数返回一个整形数据
int * *p; p为一个指向指针的指针变量,它指向一个整形数据的指针变量

2.指针的运算小结
(1)指针变量的赋值

复制代码 代码如下:

int a;
int *p
p=&a;

将变量a的地址赋给p

复制代码 代码如下:

int a[3]={1,2,3};
int *p;
p=a;

将数组首元素的地址赋给指针p

复制代码 代码如下:

int a[3]={1,2,3};
int *p;
p=&a[2];

将数组中的元素的地址赋给指针p

复制代码 代码如下:

int main(){
    int  f(int z);
    int (*p)(int z);
    p=f;
    p(5);
}
int f(int z ){
cout<<z<<endl;
}

f为已经定义的函数,将f的入口地址赋给p

复制代码 代码如下:

int a=3;
int *p1=&a;
int *p2=p1;

p1和p2是同类型的指针,将p1的值赋给p2

(2)指针变量赋空值
指针变量可以有空值,即该指针变量不指向任何变量,可以这样表示:

复制代码 代码如下:

p=NULL;

实际上NULL代表整数0,也就是使p指向地址为0的单元。这样可以使指针不指向任何有效的单元。
实际上系统已经定义了NULL:

复制代码 代码如下:

#define NULL 0

C++中在iostream头文件中就包括了以上的NULL定义,NULL使一个符号常量。
在C-free编辑器中运行:

复制代码 代码如下:

#include<iostream>
using namespace std;
int main(){
 cout<<NULL;
 cout<<endl;
}

应注意,p的值等于NULL和p未被赋是两个概念。前者是有值得(值为0),不指向任何变量,后者虽未对p赋值但并不等于p无值,只是它的值是一个无法预料的值,也就是p可能指向某一个未指定的单元。这种情况是非常危险的。因此,在饮用变量之前一定要对其进行赋值。

任何指针变量或地址都可以与NULL做相等或者不等的比较:

复制代码 代码如下:

if(p==NULL)p=p1;

上面的语句还可以写成:

复制代码 代码如下:

if(!p)p=p1;

还应注意
int *p=NULL;和int *p;*p=NULL;的区别:
int *p=NULL是定义了一个指向整形变量的指针,并且对该指针进行了初始化操作,赋初始值为NULL;
而int *p;是定义了一个指向整形变量的指针,因为没有对该指针进行初始化,所以它可能指向任何一个值,因此可能指向一个非法的值,例如系统内存中的变量。

然后*p =NULL;是使p所指向的变量的值为0,因为p所指向的值是不确定的,所以该操作是十分危险的。

(3)指针变量的赋值应该注意的问题
我们知道基类型相同的不同的指针变量之间可以赋值。
不同的的基类型的变量之间是不可以进行赋值的。
运行代码:

复制代码 代码如下:

#include<iostream>
using namespace std;
int main(){
<span style="white-space:pre"> </span>int *p1,i=5;
<span style="white-space:pre"> </span>double *p2 ,j=2.5;
<span style="white-space:pre"> </span>p1=&i;
<span style="white-space:pre"> </span>p2=&j;
 p1=p2;
    cout<<*p1<<endl;
    return 0;
}

编辑器提示:

可以通过强制类型转化实现上述赋值:

复制代码 代码如下:

#include<iostream>
using namespace std;
int main(){
 int *p1,i=5;
 double *p2 ,j=2.5;
 p1=&i;
 cout<<*p1<<endl;
 p2=&j;
 cout<<*p2<<endl;
 p1=(int *)p2;
    cout<<*p1<<endl;
    return 0;
}

虽然,上述操作不再报错,但是指针的强制类型转发生了数据截断,所以仍然得不到理想的结果:

关于指针的强制类型转换

(4)指针变量加/减一个整数

例如:

复制代码 代码如下:

p++;
p--;
p+i;
p-1;
p+=i;
p-=i;

C++规定,一个指针变量加/减一个整数是将该指针变量的原值(原来指向的地址)和它指向的变量所占用的内存单元字节数相加或者相减。

如p+i;代表这样的地址计算:p+i*d,d是p所指向的变量单元所占用的字节数。这样才能保证p+i指向p下面的第i个元素。

(5)两个指针变量相减
如果两个指针指向的同一个数组中的元素,则两个指针变量之差是两个指针变来那个之间的元素的个数。

复制代码 代码如下:

#include<iostream>
using namespace std;
int main(){
 int a[10]={1,2,3,4,5,6,7,8,9,10};
 int *p1=&a[3];
 int *p2=&a[5];
 cout<<(p2-p1)<<endl;
 cout<<(p1-p2)<<endl;
 return 0;
}

运行结果:

(6)两个指针变量比较
若两个指针指向同一个数组的元素,则可以进行比较大小。指向前面元素的指针变量小于指向后面元素的指针变量。

复制代码 代码如下:

#include<iostream>
using namespace std;
int main(){
 int a[10]={1,2,3,4,5,6,7,8,9,10};
 int *p1=&a[3];
 int *p2=&a[5];
 if(p1<p2){
  cout<<"p1<p2"<<endl;
 }else{
  cout<<"p1>=p2"<<endl;
 }
 return 0;
}

结果输出:

还可以利用这个性质,输出数组中的所有的元素:

复制代码 代码如下:

#include<iostream>
using namespace std;
int main(){
 int a[10]={1,2,3,4,5,6,7,8,9,10};
 int *p=a;
    while(p<a+10){
     cout<<*p<<endl;
     p++;
    }
 return 0;
}

输出结果:

时间: 2024-08-04 04:00:06

基于指针的数据类型与指针运算小结_C 语言的相关文章

C++中指针的数据类型和运算相关知识小结_C 语言

C++有关指针的数据类型和指针运算的小结 前面已用过一些指针运算(如p++,p+i等),现在把全部的指针运算列出如下. 1) 指针变量加/减 一个整数 例如:p++,p--,p+i,p-i,p+-i,p-=i等. C++规定,一个指针变量加/减一个整数是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数相加或相减.如p+i代表这样的地址计算:p+i*d,d为p所指向的变量单元所占用的字节数.这样才能保证p+i指向p下面的第i个元素. 2) 指针变量赋值 将一个变量地址赋给一个指

C/C++指针小结_C 语言

第一章.指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区.让我们分别说明. 先声明几个指针放着做例子: 例一: (1)int *ptr; (2)char *ptr; (3)int **ptr; (4)int (*ptr)[3]; (5)int *(*ptr)[4]; 如果看不懂后几个例子的话,请参阅我前段时间贴出的文章<<如何理解c和

关于c语言指针的两处小tip分享_C 语言

1:常量指针与指针常量 常量指针与指针常量名字很接近,但是两者区别很大. 常量指针是指指向常量的指针,例如:char const *st[4]="str";或者使用下面的方法,效果是一样的:const char *st[4]="str"; 它声明了一个指针变量,这个指针指向了一个常量字符串,但是由于指向的内存空间是常量,因此该地址的内容是不能修改的,例如:*st="no"; //这是不行的,因为内存空间的内容不能修改st="ok&quo

Linux环境下段错误的产生原因及调试方法小结_C 语言

最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的"段错误"(Segmentation Fault).借此机会系统学习了一下,这里对Linux环境下的段错误做个小结,方便以后同类问题的排查与解决. 1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况.这里贴一个

基于c++强制类型转换的(总结)详解_C 语言

什么是类型转换? 类型转换的含义是通过改变一个变量的类型为别的类型从而改变该变量的表示方式.为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符. C与C++的类型转换 C中: 复制代码 代码如下: (T)element 或者 T(element) c++中: 复制代码 代码如下: reinterpret_cast<T*> (expression)dynamic_cast<T*>     (expression)static_cast<T*>      (e

C语言 指针与二维数组详解_C 语言

二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有"缝隙".以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; 从概念上理解,a 的分布像一个矩阵: 0   1   2   3 4   5   6   7 8   9  10  11 但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存: C语言中的二维数组是按行排列的,也就是先存放 a[

深入分析C语言中结构体指针的定义与引用详解_C 语言

指向结构体类型变量的使用首先让我们定义结构体:struct stu{char name[20];long number;float score[4];} ;再定义指向结构体类型变量的指针变量:struct stu *p1, *p2 ;定义指针变量p 1.p 2,分别指向结构体类型变量.引用形式为:指针变量→成员:[例7-2] 对指向结构体类型变量的正确使用.输入一个结构体类型变量的成员,并输出. 复制代码 代码如下: #include <stdlib.h> /*使用m a l l o c (

C语言 指针数组详解及示例代码_C 语言

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组.指针数组的定义形式一般为: dataType *arrayName[length]; [ ]的优先级高于*,该定义形式应该理解为: dataType *(arrayName[length]); 括号里面说明arrayName是一个数组,包含了length个元素,括号外面说明每个元素的类型为dataType *. 除了每个元素的数据类型不同,指针数组和普通数组在其他方面都是一样的,下面是一个简单的例子: #include <stdi

c++函数中的指针参数与地址参数区别介绍_C 语言

比如 一个函数 chat(link &a): chat(ling *a): 前者引入一个地址做形参 是不是可以把一个指针变量p.. 这么用chat(p): 那跟第二个函数 有什么区别呢 都是传地址啊.. 小弟弄不明白~~ chat(int&a); chat(int *a); 这两个函数是完全不同意义的东西,你的理解主要是在int&a和int* a这个类型上面.要注意int&和int*是两个完全不同的类型.int&是引用类型,而int*是指向int类型变量的指针类型.