Skip to content

c overview

bin li edited this page Nov 1, 2018 · 1 revision

C

C语言声明

优先级规则

  • 理解C语言声明的优先级规则

  • A 声明从它的名字开始读取,然后按照优先级依次读取。

  • B 优先级从高到低依次是:

  • B.1 声明中被括号括起来的那部分

  • B.2 后缀操作符:

  •   括号()表示这是一个函数,而
    
  •   方括号[]表示这是一个数组。
    
  • B.3 前缀操作符:星号*表示“指向...的指针”。

  • C 如果const和(或)volatile关键字的后面紧跟类型说明符(如int,long等),那么

  • 它作用于类型说明符。在其他情况下,const和(或)volatile关键字作用于它左边

  • 紧邻的指针星号。

  • 用优先级规则分析C语言声明一例:char * const *(*next)();

  • 优先级规则解释一个声明:

  • A 首先,看变量名“next”,并注意到它直接被括号所括住

  • B.1 所以先把括号里的东西作为一个整体,得出“next是一个指向...的指针”

  • B 然后考虑括号外面的东西,在星号前缀和括号后缀之前作出选择

  • B.2 规则告诉我们优先级较高的是右边的函数括号,所以得出“next是一个函数指针,

  • 指向一个返回...的函数”
    
  • B.3 然后,处理“*”,得出指针所指的内容

  • C 最后,把“char * const”解释为指向字符的常量指针

  • 结果:next是一个指向函数的指针,该函数返回另一个指针,该指针指向一个只读的指向char的指针。

  • “char *(*c[10])(int **p)”

  • 使字符串的比较看上去更自然

  • #define STRCMP(a, R, b) (strcmp(a, b) R 0)

  • if (STRCMP(s, ==, "volatile"))

  • 操作typedef的提示

  • 不要为了方便起见对结构使用typedef。

  • 应该始终在结构的定义中使用结构标签,即使它并非必须,这种做法可以使代码更为清晰

  • typedef应该用在:

  • 数组,结构,指针以及函数的组合类型。

  • 可移植类型(typedef int uint32_t)

  • 提供一个简单的名字( typedef int (*ptr)(void) )

数组和指针并不相同

什么使声明,什么使定义

  • 定义:只能出现在一个地方,确定对象的类型并分配内存,用于创建新的对象。例如:int my_array[100];

  • 声明:可以多次出现,描述对象的类型,用于指代其他地方定义的对象(例如在其他文件里)。例如:extern int my_array[];

  • extern对象声明告诉编译器对象的类型和名字,对象的内存分配则在别处进行。由于并未在声明中

  • 为数组分配内存,所以并不需要提供关于数组长度的信息。对于多维数组,需要提供除最左边一维之外其他

  • 维的长度--这就给编译器足够的信息产生相应的代码。

  • 数组名是不可修改的左值,不能放在赋值符的左边

  • 字符串常量给指针赋值,例如:char *p="breadfruit", 初始化指针时所创建的字符串常量被定义为只读。

  • 由字符串常量初始化的数组是可以修改的。例如:char a[]="gooseberry"

  • 如果数组的长度比所提供的初始化的个数要多,剩余的几个元素会自动设置为0.如果元素的类型是指针,那么

  • 它们被初始化为NULL;如果元素类型是float,那么它们被初始化为0.0

  • 数组和指针参数是如何被编译器修改的:

  • “数组名被改写成一个指针参数”规则并不是递归定义的。数组的数组会被改写为“数组的指针”,而不是“指针的指针”。

  • ---------实参---------- -------所匹配的形式参数---------

  • 数组的数组 char c[8][10]; char (*)[10]; 数组指针

  • 指针数组 char *c[15]; char **c; 指针的指针

  • 数组指针(行指针) char (c)[64]; char ()[64]; 不改变

  • 指针的指针 char **c; char **c; 不改变

  • 使用指针向函数传递一个多维数组

  • 方法1,my_function(int my_array[10][20]);

  • 方法2,my_function(int my_array[][20]; Or my_function(int my_array(*)[20]);

  • 方法3,my_function(char **my_array);

  • ** 注意:只有把二维数组改为一个指向向量的指针数组的前提下才可以这样做!**

  • 使用指针从函数返回一个数组

  • int (*paf())[20]; //paf是一个函数,它返回一个指向包含20个Int元素的数组的指针。

  • 使用指针创建和使用动态数组

对链接的思考

  • interposition, 不要让程序中的任何符号成为全局的,除非有意把它们作为程序的接口之一。

对内存的思考

  • 通常导致段错误的几个直接原因:
  • 解除引用一个包含非法值的指针
  • 解除引用一个空指针(常常由于从系统程序中返回空指针,并未检查就使用)
  • 在未得到正确的权限时进行访问
  • 用完了堆栈或堆空间(虚拟内存虽然巨大但绝非无限)

其他

  • 调用库函数之后检查errno

Clone this wiki locally