C语言声明一览

来源:互联网 发布:奥数 高斯算法 教师版 编辑:程序博客网 时间:2024/05/23 15:16

C语言中有几个难点,声明、数组和指针等。本文先介绍一下声明问题。

1、几个关键字的用法。

static,const,extern,typedef。

static 在C语言中主要有两个意思,在函数体内,表示被修饰变量在调用期间保持值的延续性;在函数级别,表示该函数只对所在文件可见。

const 表示一个变量在所影响的作用域内不可变。如,函数的形参void foo(const char * s);表示s所指向的内存在foo函数体内不可被改变(在别处则没有这个限制);另外,const与指针同时使用时,有三种情况:

const char * s;//表示s所指向内存不可变char * const s;//表示指针s的值不可变,即s所指向的地址是固定的const char * const s;//表示s的值既不可变s所指内存也不可变。

extern 修饰函数时表示函数全局可见(实际上不加static修饰的函数都是全局可见的);作用于变量,表示该变量在其他地方定义;其实在C++中也有使用,extern “C”,使得C++的函数可以在C中调用。

typedef 为一个类型起一个新的名字(不是宏的文本替换),一旦确定之后,该类型不能有别的修饰:

typedef int myInt;unsigned myInt i;   //errortypedef char * string;string dog, cat;    //等效于:char * dog; char * cat;#define string char *string dog, cat;    //等效于:char * dog; char cat;

typedef 可以简洁表示指向其他东西的指针,有点绕:

typedef void (*func)(int);/* 表示func是一个函数指针,接收一个int型参数,返回值是void */

2、复杂声明

结构体、联合体和枚举类型。
结构体与联合体接近。
在不使用typedef时,结构体声明方式有:

struct { 内容...};    //这种声明无法再次使用struct { 内容...} ele, book;      //ele 和book表示的是变量struct tag { 内容...};    //struct tag 合起来当作一个类型  

结构体有一些高级用法,比如数组不能直接值传递,但结构体可以,所以如果存在频繁对某个数组进行值传递的话,可以这样声明

struct int_tag {int value[100];};

struct int_tag 所占的内存为100个int型大小,可以直接赋值。
另外结构体里可以包含指向自身类型的指针。

如果只是声明了struct/union/enum,那在声明新的变量时需要将关键字带上,如:
struct int_tag a;

3、解释声明的优先级规则

一些复杂的声明:

char * const *(*next)();char *(* c[10])(int **p);void (*singal(int sig, void(*handle)(int)))(int);

如果下述的一套规则,那么上述几个声明分析起来就十分困难:

A. 声明从名字开始读取,然后按照优先级顺序依次读取
B. 优先级的顺序为:
B.1 声明中被括号括起来的部分
B.2 后缀操作符:
()表示这是一个函数;[]表示这是一个数组。
B.3 前缀操作符:
*表示“指向…的指针”
C. 如果const等关键字的后面紧跟类型说明符(int,long)那么它作用于类型说明符,其他情况下,作用于它左边紧邻的指针*符号

分析:

上述代码第一行

  1. 首先找到名字next,注意其被括号包围(A)
  2. 分析括号里的部分,*next,所以next是指向…的指针(B.1 B.3)
  3. 括号外有*前缀和()后缀(B)
  4. 取()后缀,所以next是一个指针函数,传入参数为空,并返回… (B.2)
  5. 取*前缀,表示返回的是一个指针 (B.3)
  6. 取出剩余前缀,char * const 解释为指向字符的常量指针(C)

所以,代码第一行的解释为:next是一个指针,该指针指向一个函数,该函数返回一个指针,该指针指向一个类型为char 的常量指针。(非常不标准的英语是:next is a pointer to a function which return a pointer to a const char type pointer)。

同理,第二行的声明:

  1. 找到c
  2. c是一个数组,大小为10
  3. 数组元素是指向…的指针
  4. 参数为int **的函数
  5. 函数返回值为char *

所以c是一个元素类型为 参数为int**且返回值为指向char的指针的函数指针,且大小为10的数组。

第三行的声明:

  1. 找到signal
  2. 是一个函数(参数先不管)
  3. 返回一个函数指针
  4. 返回的函数指针的参数是int,函数指针的返回值是void
  5. signal所传入的参数有两个,一个是整型,一个是void(*func)(int)
  6. func 也是一个指针,指向一个接收int参数并返回void的函数

发现signal返回值与所传递参数的一致性,

typedef void(*ptr_func)(int);ptr_func singal(int, ptr_func);

这样就能简化signal的定义了。

以上内容总结《C专家编程》。

4、typedef的困惑

自己在学习C语言的时候,不知道typedef的语法究竟是什么样的,在总结C语言的声明之后,便豁然开朗。

C语言声明一个变量的语句为statements V; 即V是某个类型的一个变量。如果在这个语句前加上typedef,即typedef statements V; 那么V就是这个类型的“别名”。

例:

unsigned int uintA;         //uintA 是一个变量typedef unsigned int uintA; //uintA 是一个unsigned int的类型unsigned char name[20];         //name 是一个长度为20的字符数组(不能简单当作指针)typedef unsigned char name[20]; //name 是一个类型,可以声明一个长度为20的字符数组的变量void(*ptr_func)(int);           //ptr_func 是一个函数指针,参数为int,返回空typedef void(*ptr_func)(int);   //ptr_func 是一个函数指针类型,可以声明一个接收int型参数返回值为void的函数指针变量。

以上为个人理解。

0 0