学习C指针之揭秘C的语法

10 篇文章 0 订阅

解读C的声明

解读步骤:

1,首先着眼于标识符(变量名或者函数名);

2,从距离标识符最近的地方开始,依照优先顺序解释派生类型(指针,数组,函数);优先顺序:1:用于整理声明内容的括弧;2:用于表示数组的[ ],用于表示函数的();3:用于表示指针的*;

3,解释完成派生类型,使用“of”, "to", "returning"将他们连接起来。

4,最后,追加数据类型修饰符(在左边,int, double等);

5,英语不好的人, 可以倒序用中文解释。

例子:

int (*func_p)(double);

1,先看标识符func_p;

读为:func_p。

2,然后看到附近的指针;

读为:func_p是一个指针。

3,解释用于函数的(),参数为double;

读为:func_p是一个指向函数(参数为double)的指针。

4,最后解释数据类型修饰符int;

读为:func_p是一个指向返回值为int的函数(参数为double)的指针。

指向数组的指针

数组和指针都是派生类型,他们都是由基本类型开始重复派生生成的。

也就是说,派生出数组之后,再派生出指针,就可以生成“指向数组的指针”。

指向数组的指针和指向数组初始元素的指针不是一回事。

int array[3];
int (*array_p)[3];

在数组前加上&可以取得指向数组的指针,因此这样是可以的:
array_p = &array;
这样是错误的:
array_p = array;

从地址的角度上说,array和&array也许就是指向的同一个地址,但是他们在运算的时候结果不同。

在上面的例子中,array+1,指针前进4个字节;array_p+1,指针前进12个字节。

函数类型的派生

数组类型就是将几个派生类型排列而成的类型。因此,数组类型的全体长度为:

派生源的类型的大小 x 数组的元素个数。

函数类型是无法得到特定长度的。

对指向函数类型的指针不能做指针运算,因为我们无法得到当前指针的类型的大小。

计算类型的大小

除了函数类型和不完全类型,其他类型都有大小。

通过sizeof(类型名),编译器可以帮我们计算当前类型的大小,无论是多么复杂的类型。

比如:sizeof(int (*[5](double0);

下面我们自己计算一下各种类型的大小:

在这里:

int   4个字节

double   8个字节

指针     4个字节

计算类型的顺序:

1,基本类型

2,指针

3,数组

4,函数(无法计算大小)

比如说int (*[5])(double); 

首先因为是返回int类型,计算结果为4个字节;指向返回int的函数的指针的数组,因为是函数,无法计算大小;指向返回int的的函数的指针,计算结果4个字节;返回int的函数的指针的数组(5个元素)结果为4X5=20;共20+4+4=28;

数组和指针相关的运算符

解引用:

单目运算符*被称为解引用;

地址运算符:

单目运算符&被称为地址运算符

下标运算符:

后置运算符[ ]被称为下标运算符;

—>运算符:

通过指针访问结构体的成员的时候会使用->运算符。

const修饰符

const将类型修饰为只读;

const主要用于修饰函数的参数;

/*const参数的实例*/
char *strcpy(char *dest, const char *src);

此时所谓的只读是如何表现的呢?做个实验就知道,上面例子中的src这个变量没有定义为只读。

char *strcpy(char *dest, const char *src);
{
    src = NULL:   //即使对src赋值,编译器也没有报错;
}

此时成为只读的不是src,而是src指向的对象;

char *strcpy(char *dest, const char *src);
{
    src = 'a':   //报错;
}

如果对src所指向的对象进行赋值,就会报错;

如果将src自身定义为只读,需要写成下面这样。

char *strcpy(char *dest, char * const src);
{
    src = NULL:   //报错;
}

如果想要将src的指向以及自身都定义为只读,可以写成下面这样:

char *strcpy(char *dest, const char * const src);
{
    src = NULL:   //报错;
    *src = 'a';   //报错;
}

const修饰的是紧跟在它后面的单词;

此外容易造成混乱的是:

char const *src;

const char *src;

意思完全相同。

对于一个结构体:

typedef struct {
char *title;
int price;
char inbn[];
} Bookdata;

将上面这个结构体作为输入参数的函数原型,可以写成下面这样:

/*注册书的数据*/
void regist_book(BookData const *book_data);

因为使用了const,所以book_data所指向的对象是禁止改写的。

但是,书的标题(book_data->title)所指向的内容是可以改写的。这是因为,根据指定的const而成为只读的对象只是“book_data所指向的对象的本身”, 而不包括“book_data所指向的对象再往前追溯到的对象”。

typedef

typedef用于给某类型定义别名。

比如: typedef char *String;

通过以上声明,对于“指向char的指针”可以使用“string”这个别名:

String a[10];

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值