博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C 指针
阅读量:5749 次
发布时间:2019-06-18

本文共 2769 字,大约阅读时间需要 9 分钟。

C 指针(完善中。。。)
 
一、认识存储单元
 
指针是C语言最显著的特色。要理解指针的概念,需要先理解计算机读写内存的的方式以及变量的概念。
 
计算机内存是以字节为单位划分内存单元的,每个内存单元占用一个字节,每个内存单元都有自己的地址编号,操作系统或软件根据这个地址来识别内存单元,在地址所标识的内存单元中存取数据。内存单元的地址是固定的,内存单元中的数据是可以修改的。
 
C语言中,变量名实质上是内存单元的地址符号,用户使用变量本质上是访问该变量所对应的内存单元。
 
二、C指针的概念
 
1、在C中,将内存单元的地址(编号)称为指针,可以通过一个变量来存放指针,这种变量称为指针变量。指针变量中存储的是内存单元的地址。
 
例如 int a = 10; 假设存放a的内存单元块为 101,102,103,104,占用四个字节。如果再执行一个 int *p=&a;那么p的值就成为101了,*p的值就是10,a的值也是10。
 
&是取地址运算符,获取变量的首地址。
 
2、创建指针的方法是:类型说明符 *变量名,这是C定义指针变量的方法。其中*表示这个变量是指针变量。
 
C要求,指针必须存放在指针变量中。
一个指针只能指向同一类型的变量。
 
3、指针的初始化
int *p=NULL;
int a=10;
int *p=&a;
 
注意:
a)未初始化的指针的系统会给一个随机的值,没有意义,操作可能引起系统崩溃。
b)未初始化的指针应该给一个NULL值,以表明它是个空指针,表示0值。
c)不允许把常量赋值给指针变量。
d)必须保持指针变量类型与所指数据的一致性,否则会发生不可预期的效果。(虽然C已允许将任何地址赋值给指针变量)。
 
4、取地址& 与 取内容*
 
取地址运算符是& ;
取内容运算符是*,注意:区别定义指针变量类型说明符*。
 
int a=10;
int *p=&a;    //定义指针变量p,并指向a;
*p=3;   //将3赋给指针p所指的内存单元,则a的值也变为了3
int b = *p;  //将指针p的所指内存单元值赋给变量b;
 
明白这个道理后,指针和一般变量一样可以操作了。
 
指针的直接操作内存,在Java中是没有的,Java没有指针。Java中的基本变量名实际上也是内存地址的别名。
 
三、指针操作数组
 
1、指向数组的指针
 
数组是保存在一片连续的内存单元中。数组名是这块连续内存单元的首地址,是不可改变的常量。因此数组名也是一个常量指针。
int a[3]={1,2,3};
int *p=a;  //指向数组的指针
 
当指针执行数组名或数组首元素地址时,指针就指向了数组。
 
2、指针运算
a)自增/自减:C规定,指针加1,表示指针后一个指针的类型的内存单元。
b)加减整数运算,只能加减整数,整数表示的基类型数据的宽度倍数。
c)指针相减,指针间的元素个数,不是存储单元数。
d)指针比较,判断指针在内存中的高低位置关系。
 
3、指针操作数组
 
下标发和指针法,分五种方式:
 
#include<stdio.h> 

int main() 


        
int i,a[5]={1,2,3,4}; 

        
int *p=a; 

        
for(i=0;i<4;i++) 

                printf(
"a[%d]=%d\n",i,a[i]); 

        printf(
"\n"); 

        
for(i=0;i<4;i++) 

                printf(
"p[%d]=%d\n",i,p[i]); 

        printf(
"\n"); 

        
for(i=0;i<4;i++) 

                printf(
"*(p+%d)=%d\n",i,*(p+i)); 

        printf(
"\n"); 

        
for(i=0;i<4;i++) 

                printf(
"*(a+%d)=%d\n",i,*(a+i)); 

        printf(
"\n"); 

        
for(i=0;i<4;i++) 

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

        getch(); 

        
return 0; 

}
 
a[0]=1 

a[1]=2 

a[2]=3 

a[3]=4 


p[0]=1 

p[1]=2 

p[2]=3 

p[3]=4 


*(p+0)=1 

*(p+1)=2 

*(p+2)=3 

*(p+3)=4 


*(a+0)=1 

*(a+1)=2 

*(a+2)=3 

*(a+3)=4 


*p++=1 

*p++=2 

*p++=3 

*p++=4
 
注意,数组名虽然是指针,但是数组名是常量,不可改变,因此不可以a++;
 
4、指针操作二维数组
 
二维数组是多个一维数组组成的数组,或者说是一维数组的数组,或者说是一维数组,但是各个元素还是一维数组。
 
这个概念和java中是一致的。
 
假设有二维数组
int a[x][y];
那么
a)a表示数组首地址的指针。
b)a[i]表示第i+1个一维数组,其地址为a[i],指向的是一个一维数组。
c)a[i][j] 与*(a[i]+j)、*(*(a+i)+j)是相同的,表示同一个元素。
 
#include<stdio.h> 

int main() 


        
int a[4][5], i,j; 

        
for(i=0;i<4;i++) 

                
for(j=0;j<5;j++) 

                        a[i][j]=i*5+j; 

        printf(
"二维数组的值为:\n"); 

        
for(i=0;i<4;i++) 

        { 

                
for(j=0;j<5;j++) 

                        printf(
"%4d ",a[i][j]); 

                printf(
"\n"); 

        }                


        getch(); 

        
return 0; 

}
 
二维数组的值为: 

     0        1        2        3        4 

     5        6        7        8        9 

    10     11     12     13     14 

    15     16     17     18     19
 
 
5、数组指针
 
数组指针:变量是指针,指向了一个数组。
例如:
int *p[3];定义了一个指针p指向了一个长度为3的int数组。
 
#include<stdio.h> 

int main() 


        
int a[4][5],i,j; 

        
int (*p)[5]; 

        p=a; 

        
for(i=0;i<4;i++) 

        { 

                
for(j=0;j<5;j++) 

                        *(*p+j)=i*5+j; 

                p++; 

        } 

        printf(
"二维数组的值为:\n"); 

        p=a; 

        
for(i=0;i<4;i++) 

        { 

                
for(j=0;j<5;j++) 

                        printf(
"%4d    ",*(*p+j)); 

                printf(
"\n"); 

                p++; 

        }                


        getch(); 

        
return 0; 

}
 
二维数组的值为: 

     0        1        2        3        4 

     5        6        7        8        9 

    10     11     12     13     14 

    15     16     17     18     19
 
6、数组名参数
 
四、指针和字符串
 
本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/187730,如需转载请自行联系原作者
你可能感兴趣的文章
红外遥控资料
查看>>
luasocks的安装以及注意事项
查看>>
nginx: client intended to send too large body
查看>>
【VMCloud云平台】SCAP(四)租户(一)
查看>>
python---练习---即时标记
查看>>
linux释放内存的方法
查看>>
基于 Android NDK 的学习之旅----- C调用Java
查看>>
开始第一个Python程序!
查看>>
Google 或强制 OEM 预装 20 款应用,给你一个不Root的理由
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
双边过滤器(Bilateral filter)
查看>>
Android图形显示系统——下层显示4:图层合成上(合成原理与3D合成)
查看>>
Windows 10 技术预览
查看>>
centos卸载openjdk,安装sun的jdk
查看>>
Tomcat http跳转https
查看>>
Linux安装MySQL后找不到my.cnf原因以及从sql语句文件恢复数据库
查看>>
一个自动布署.net网站的bat批处理实例
查看>>
tomcat 安装
查看>>
AIX:物理卷及有关概念
查看>>