1、修饰基本类型变量,例如:
const int a = 100;
此时,在上面的初始化语句中,const对a进行限制,使得a在 程序中不能被赋值,成为只读数据,所以下面的操作是错误的
a = 200; //错误
#include <stdio.h>
int main(void)
{
const int a = 100; //a在程序中只读
//a = 200; //不能给a赋值
printf("a = %d\n", a);
int *pa = &a; //pa指向a
*pa = 300;
printf("a = %d\n", a);
return 0;
}
2、修饰指针
1》第一种情况:
int a = 100;
int *p = &a; 或者 int const *p = &a;
上面的初始化语句中,const对*p进行限制,使得*p在程序中不能被赋值,成为只读数据,所以下面的操作是错误的
*p = 200; //错误
int a = 100, b = 500;
//const int *p = &a; //等价于下面的语句
int const *p = &a;
//*p = 200; //*p为只读数据,不能被赋值
p = &b //正确
printf("*p = %d\n", *p);
int *pa = &a; //pa指向a
2》第二种情况:
int a = 100,b = 500;
int * const p = &a;
上面的初始化语句中,const对p进行限制,使得p在程序中不能被赋值,成为只读数据,所以下面的操作是错误的
p = &b; //错误
3》第三种情况:
int a = 100,b = 500;
const int * const p = &a; 或者 int const * const p = &a;
上面的初始化语句中,const对*p和p同时进行限制,使得*p和p在程序中都不能被赋值,成为只读数据,所以下面的操作是错误的
*p = 200; //错误
p = &b; //错误
二、数组与指针
1、数组名的深层含义:
如果有:int a[5] = {1,2,3,4,5};
第一个意思:
数组名a表示数组在内存空间中的名称,sizeof(a)=数组的占内存空间的字节数
第二个意思:
数组名取地(&a)址表示数组的起始地址,例如:
第三个意思:
数组名表示地址常量,即代表数组的第一个元素(首元素)的地址,例如:
2、数据元素的表示
int a[5] = {1,2,3,4,5};
数组元素:a[0],a[1],a[2],a[3],a[4]
也可以这样表示:*(a+0),*(a+1),*(a+2),*(a+3),*(a+4)
3、多维数组与指针
如果有二维数组:int a[2][3] = {{1,2,3},{4,5,6}};
三、指针与数组
1、数组指针和指针数组
1》数组指针:指向数组的指针或者存储数组地址的指针,
例如:int (*p)[10]; //p为指针,可以存储 有10个整型元素的数组地址
2》指针数组:包含指针的数组或者存储多个相同类型数据地址的数组,
例如:int *p[10]; //p为数组名,该数组中有10个元素,都是整型的指针
2、函数指针和指针函数
1》函数指针:指向函数的指针或者存储函数入口地址的指针,
例如:int (*p)(int); //定义p为函数指针,也就是p中可以存放一个函数的地址,但是该函数必须有一个int型参数和int型返回值
#include <stdio.h>
//函数的入口地址在C语言中可以表示为:fun或者&fun
int fun1(int x)
{
x *= 2;
return x;
}
void fun2(int x)
{
printf("%d\n",x);
}
void fun3(int x,float y)
{
printf("%d,%f\n",x,y);
}
int main(void)
{
int a = 100,b;
int (*p)(int); //定义函数指针p
p = fun1; //将函数fun1的入口地址赋给函数指针p
//p = &fun1; //将函数fun1的入口地址赋给函数指针p
//p = fun2;//错误
void (*p1)(int); //p1为函数指针
p1 = fun2;
void (*p2)(int,float); //p2为函数指针
p2 = fun3;
b = fun1(a);
printf("b = %d\n",b);
int a1 = 123,b1;
//b1 = (*p)(a1); //通过函数指针间接调用函数fun1
b1 = p(a1);//通过函数指针间接调用函数fun1
printf("b1 = %d\n",b1);
p1(b1);
return 0;
}
2》指针函数:返回指针的函数,或者说一个函数如果返回的是地址则该函数为指针函数
例如:int *p(int);
#include <stdio.h>
#include <string.h>
char *fun(char a[])//该函数为指针函数
{
int len;
char b[] = "farsight";
len = strlen(a);
//return b; //b作为地址不能返回
return a;
}
int main(void)
{
char array[] = "hello world";
char *str;
str = fun(array);
printf("%s\n",str);
return 0;
}
3、函数指针数组
由函数指针构成的数组,指的是一个可以存放多个函数入口地址的数组,
例如:int (*p[10])(int); //p为函数指针数组,该数组中有10个元素,这10个元素都是函数指针
#include <stdio.h>
int fun1(int x,int y)
{
return x + y;
}
int fun2(int x,int y)
{
return x - y;
}
int fun3(int x,int y)
{
return x * y;
}
int fun4(int x,int y)
{
return x / y;
}
int main(void)
{
int a = 6,b = 2;
/*
int(*p)(int,int);
p = fun4;
printf("%d\n",p(a,b));
*/
/*
int (*p[4])(int,int); //定义函数指针数组,p为函数指针数组的名称
p[0] = fun1;
p[1] = fun2;
p[2] = fun3;
p[3] = fun4;
printf("%d\n",p[0](a,b));
printf("%d\n",p[1](a,b));
printf("%d\n",p[2](a,b));
printf("%d\n",p[3](a,b));
*/
int (*p[4])(int,int) = {fun1,fun2,fun3,fun4}; //初始化函数指针数组,p为函数指针数组名称
char *str = "+-*/";
int i;
for(i = 0; i < 4; i++)
printf("%d %c %d = %d\n",a,str[i],b,p[i](a,b));
return 0;
}
四、字符数组传参
只需要传数组名即可,
计算字符串长度时,如果用sizeof,那么必须传数组名本身,如果用strlen,可以传数组名本身,也可以传指向该数组元素的指针,例如:
#include <stdio.h>
#include <string.h>
//函数的形参都是变量
//数组作为函数参数传递时,形参有两种定义形式,分别是数组形式和指针形式,该形参一定是指针
//void fun1(char p[])
void fun1(char *p)
{
int len;
len = strlen(p);
printf("len = %d\n",len);
len = sizeof(p)/sizeof(char);
printf("len = %d\n",len);
len = sizeof(p);
printf("len = %d\n",len);
printf("%s\n",p);
p[0] = 'H';
}
int main(void)
{
char str[] = "hello world"; //str为字符数组名
/*
char *p =str; //p为char型的指针,保存地址常量str
//计算字符串长度
printf("sizeof(str) = %d\n",sizeof(str));
printf("sizeof(p) = %d\n",sizeof(p));
//用strlen计算字符串长度时,只需要传该字符串第一个元素的地址即可
printf("strlen(str) = %d\n",strlen(str));
printf("strlen(p) = %d\n",strlen(p));
*/
fun1(str);
printf("%s\n",str);
return 0;
}