C语言指针基础
1.定义
指针:一个变量的地址称为该变量的指针。
指针变量:如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”
指针变量的值(即指针变量中存放的值)是地址(即指针)
定义指针变量的一般形式为
基类型 *指针变量名;
int *ptr;
说明:
指针变量的类型:指明了该指针指向的内存空间所存储的数据类型。
定义中的“*”表示所定义的变量是指针变量。变量名是ptr,而非*ptr
2.赋值
(1)通过 & 运算符为指针赋值,
例如:
ptr_var = &var;
(2)通过另一个指向相同类型数据项的指针变量对指针进行赋值,
例如:
ptr_var2 = ptr_var;
(3)给指针变量赋值为符号常量NULL(避免野指针)
例如:
float *ptr_var3=NULL;
说明:
NULL是一个空指针,表示该指针变量的值没有意义。
作用是为了避免对没有被初始化的指针变量的非法引用。NULL 的定义在“stdio.h”中。
(4)通过指针为变量赋值
例如:
int *ptr_var = NULL;
int var = 100;
ptr_var = &var;
*ptr_var = 10; /*等价于var = 10;*/ /*如果ptr_var指向var,则把10赋给var*/
3.指针运算符
只能进行加法和减法运算:+ - ++ -- += -=
两种形式:指针±整数 或者 指针 - 指针
(1)pointer_2 =&* pointer_1
先进行* pointer_1的运算,它就是变量a,再执行&运算。&* pointer_1与&a相同,即变量a的地址,就是将&a(a的地址)赋给pointer_2
(2) *&a==a? &*a? *右侧只能是地址
先进行&a运算,得a的地址,再进行*运算。即&a所指向的变量,也就是变量a。*&a和*pointer_1的作用是一样的,它们都等价于变量a。即*&a与a等价。
(3) (*pointer_1)++ 和 *pointer_1++
*pointer_1++:++和*为同一优先级别,而结合方向为自右而左,因此它相当于*(pointer_1++)。由于++在pointer_1的右侧,是“后加”,因此先对pointer_1的原值进行*运算,得到a的值,然后使pointer_1的值改变,这样pointer_1不再指向a了。
(*pointer_1)++: *pointer_1相当a,所以整个表达式相当于a++
4.比较
两个指针都指向相同类型的变量时,可以进行大小的比较!
5.按地址传递
指针可以作为参数
把实参的地址传给形参
允许函数访问内存位置
被调函数能够修改主调程序的参数的值
例:
6.指针与数组
一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组和数组元素。
所谓数组的指针(数组的名称)是指数组的起始地址,也就是第一个元素的地址。数组的指针是个常量指针。
常量就是不可变的。
例:
#include <stdio.h>
int main(){static int ary[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int I,*p=NULL;for (i = 0; i < 10; i ++){printf("\ni=%d,ary[i]=%d,*(ary+i)=%d",i,ary[i],*(ary + i));printf("&ary[i]= %X,ary+i=%X",&ary[i],ary+i);}for (p = ary; p < ary+10 ; p++){ /*能否使用ary++?*/printf(“\naddress:%x,value:%d”,p,*p);}return 0;
}
数组作为参数传递
一维数组元素作参数传递时,按值传递
整个数组(数组名)当参数传递时,按地址传递,有以下三种等价的写法:
void TestArray(char ary[ ]);
void TestArray(char ary[ LEN]);
void TestArray(char *ary);
整形数组作为返回值
四种情况:
7.字符串与指针
(1)指向字符串常量的字符指针
可以声明字符指针直接指向字符串常量
例如char* pStr=“Welcome”; 字符指针pStr将指向字符常量“Welcome”
“Welcome”为字符串常量,因此其值不能修改
例如代码 pStr[0]=‘h’; 将引发一个错误
(2)指向字符串变量的字符指针
可以使用字符指针来存储和访问字符串
声明字符指针语法:char* pStr;
声明字符串:char str[10]=“hello”;
使用字符指针指向字符串:pStr=str;
可以使用字符指针访问字符串,例如pStr[0]=‘a’; 该代码将第一个字符修改为’a’
例:
#include <stdio.h>
#include <string.h>
void main ()
{ char a, str[81], *ptr;printf("请输入一个字符串\n ");gets(str);printf("\n请输入一个字符");a = getchar();ptr = strchr(str,a);if(ptr != NULL) printf(“\nPosition of first occurrence is: %d”,ptr-str);else printf(“not found!”);
}
(3)字符数组与字符指针的区别
8.代码笔记
#include<stdio.h>
#include<string.h>
#include<windows.h>//指针的基本概念
//所谓指针就是你定义这变量存放的不是具体的值而是存放另外一个变量的地址
/*
void test(char *str)
{int i;for(i=0;i<strlen(str);i++){printf("%c",str[i]);}
printf("\n");
}
*/
/*
void* test(char *str)
{int i;//char array[10]={0};char *array=(char *)malloc(sizeof(char)*20);//自己开辟空间memset(array,0,20);//每次malloc后都要清空一次内存for(i=0;i<strlen(str);i++){printf("%c",str[i]);}strcpy(array,str);printf("\n");printf("array=%s\n",array);return array; //可以把指针作为参数返回值,但是绝对不能把函数里面的聚币变量的地址返回给外面,那是没意义的//因为当函数执行完成之后函数内部的局部变量都会被释放回收//如果你一定要返回指针地址就要自己开辟内存空间malloc函数
}int main()
{char message[20]="hello word";char *p_str=NULL;char arry[5]={1,2,3,4,5};char *strP=NULL;//如果一个指针变量定义后不赋值那么系统是给予无意义的值这是很危险的,赋值为空表示不只想任何地址int number=10;int i;int temp=20;int *p=&number; //定义了一个整形指针,这个p里面的数据是number内存中的地址int *p1=&temp;//这个时候就可以通过指针p来获取这内存中的具体指printf("p所指向的内存地址里面的值是=%d\n",*p); //*P拿去p地址里的数据*p=200; //直接赋值会改变printf("number=%d\n",number);p1=p;//指针变量也可以想普通变量一样正常赋值,但是只有相同类型的指针变量才能进*p1=999;printf("number=%d\n",number);*p1=*&number;printf("number=%d\n",number);//指针也可以参与算术运算++ --//但是有可能指向没有开辟的内存空间中//p1++;//printf("%d\n",*p1);p1=arry;p1+=2;printf("%d\n",*p1);//字符串strP=&message;//messge=strP 这种写法是错误的因为message是数组名,定义的时候地址是固定的,不能改变for(i=0;i<strlen(message);i++){printf("%c",strP[i]);}printf("\n");//test(message);p_str=test(message);printf("p_str=%s\n ",p_str);
}*/typedef struct
{int age;char name[10];
}PACK_T;PACK_T* structTest(PACK_T *pack_t)
{PACK_T *temp=(PACK_T *)malloc(sizeof(PACK_T));memset(temp,0,sizeof(PACK_T));pack_t->age=29;strcpy(pack_t->name,"ssss");memcpy(temp,pack_t,sizeof(PACK_T)); //整体拷贝return temp;
}void strcutArrTest(PACK_T packArr[],int len)
{int i=0;printf("packArr的大小%d\n",sizeof(packArr));//4 因为传过来的是指针,所有指针都只4字节for(i=0;i<len;i++){packArr[i].age=i;}
}int main()
{PACK_T pack_t={0};PACK_T *p_pack_t=NULL;PACK_T packArr[10]={0};p_pack_t = structTest(&pack_t);printf("name=%s age=%d\n",p_pack_t->name,p_pack_t->age);printf("packArr数组在内存中占用%d字节,其中一个PACK_T结构占用%d字节,这数组总共存放%d个结构体",sizeof(packArr),sizeof(PACK_T),sizeof(packArr)/sizeof(PACK_T));strcutArrTest(packArr,sizeof(packArr)/sizeof(PACK_T));printf("packArr[2].age=%d\n",packArr[2].age);free(p_pack_t); //销毁自己开辟的空间
}