数组和函数类型 + const修饰问题 + typedef 总结

typedef int ( myArrayType )[10];  // 数组类型
typedef int (* mypArrayType )[10]; // 数组指针类型
int (* mypValArrayType )[10];    // 数组指针类型的变量

typedef int c1 [10];  // 数组类型
typedef int * c2 [10];  // 指针数组类型
int * c3 [10];       // 指针数组

typedef char vertexNameArr [20];
vertexNameArr vertexArr [ 30 ];   相当于 vertexArr[30][20];
vertexNameArr* aaa[30];       相当于vertexArr* [30][20];

typedef int ( MyFuncType )( int , int );    // 函数类型
typedef int (* MyPFuncType )( int , int );  // 函数指针类型
int (* MyPFuncTypeVal )( int , int );     // 函数指针类型变量
typedef  int (* My[10] )( int , int );     //函数指针数组类型
int (* My[10] )( int , int );           // 函数指针数组
void (*b[10]) (void (*)());                                    //函数指针数组
void (*const Fun_ScanLine[KEY_LINE_SUM])(void)   // 函数指针数组

typedef int MyFuncType ( int , int );     // 函数类型
typedef int * MyPFuncType ( int , int );  //返回值是 指针的函数类型   下面有解释  这个还是函数类型
int * MyPFuncTypeVal ( int , int );      // 返回值是指针的函声明     

4. const修饰数组:
    第一组:2个
    const      int       arr[10];        这两个一样 都是不能修改数组里面的值  arr [0] = 100;不可以
    int        const     arr[10];        这两个一样 都是不能修改数组里面的值  arr [0] = 100;不可以
                  报的错误是 左值指定const对象,表达式必须是可以修改的左值;
  第二组:3个
    const      int      *arr[10];        这两个一样  但是const修饰的是什么呢   arr [0] = &a; 是可以的
    int        const     *arr[10];      这两个一样  但是const修饰的是什么呢   arr [0] = &a; 是可以的
   答:const修饰的是指针数组里存的指针所指向的内容是不可以被修改的, 想通过 * arr [0] = 1000; 
    把a改成1000是不可以的, 报的错误是左值指定const对象,表达式必须是可以修改的左值;
     int*       const     arr[10];      这个和前两个不同,const修饰的是什么呢  arr [0] = &a;不可以的 
    答:const修饰的是指针数组里存的指针是不能被修改的, arr [0] = &a;不可以的 ,
    报的错误是 左值指定const对象,表达式必须是可以修改的左值;
  第三组:3个
   void   (const  *pFuncArray[10] )  (void) ;
   const   void   (*pFuncArray[10] )  (void) ;
     答 程序没有验证,不知道怎么验证,因为函数地址所指向的内容不知道怎么修改,根据上面的指针数组推测:
        这两个也是一样的,const修饰的是函数指针数组里存的函数指针所指向的内容,它是不能被修改的;
         *Fun_ScanLine[0] = 11111; 不可以    这两种情况应该是不怎么用的;
   void   (* const pFuncArray[10] )  (void) ;
     答:const修饰的是函数指针数组里存的函数指针,它是不能被修改的, Fun_ScanLine [0] = print04 ;不可以;
        这种情况应该是常用的;

从这里以下是我从百度找到,节选的部分,解决了我函数和数组类型等问题,谢谢下面这个人的分享。

typedef :也许新手用这个关键字不多,但它却是一个很有用的关键字,可以使代码模块化程度更好(即与其它代码的关联较少),
        在C++中还是实现Traits技术的基础,也是模板编程的基本语法之一。
注意一
    同样,可以象下面这样隐藏指针语法:
    1 typedef char * pstr;  
    2 int mystrcmp(pstr, pstr);  
    这里将带我们到达第一个 typedef 陷阱。标准函数 strcmp()有两个‘ const char *'类型的参数。因此,它可能会误导人们象下面这样声明 mystrcmp():
    1 int mystrcmp(const pstr, const pstr);   
        用GNU的gcc和g++编译器,是会出现警告的,按照顺序,‘const pstr'被解释为‘char* const‘(一个指向 char 的指针常量),
        两者表达的并非同一意思。为了得到正确的类型,应当如下声明: 
        1 typedef const char* pstr;
注意二
    void (*b[10]) (void (*)());                                     // 函数指针数组   变量 b
typedef void (*pFunParam)();            //函数指针类型
typedef void (*pFunx)(pFunParam); //函数指针类型
   原声明的最简化版: pFunx b[10];或者pFunx a[10]; 这里的a或者b是变量的名字; //定义的是 函数指针数组 变量b a
    
    doube(*)() (*e)[ 9 ]; //函数的数组指针 有这么一个指针e 它是指向 函数的返回值是double类型参数是void类型的函数数组,数组的元素个数是9个 ;
typedef double (*pFuny)(); //函数指针类型 pFuny
        typedef pFuny (*pFunParamy)[9];
      pFunParamy e;

    理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;
    括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。举例:
    1 int (*func)(int *p);
    首先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针;然后跳出这个圆括号,
    先看右边,又遇到圆括号,这说明(*func)是一个函数,所以func是一个指向这类函数的指针,即函数指针,
    这类函数具有int*类型的形参,返回值类型是int。
    1 int (*func[5])(int *);
    func右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明func的元素是指针
 (注意这里的*不是修饰func,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合)。跳出这个括号,
    看右边,又遇到圆括号,说明func数组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。
注意三
    用途七:typedef 和存储类关键字(storage class specifier) 
    这种说法是不是有点令人惊讶,typedef 就像 auto,extern, mutable ,static,和 register、volatile 一样,
    是一个存储类关键字。这并不是说 typedef 会真正影响对象的存储特性;它只是说在语句构成上,
    typedef 声明看起来象 static,extern 等类型的变量声明。下面将带到第二个陷阱: 
    1 typedef register int FAST_COUNTER; // 错误  
    编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef 已经占据了存储类关键字的位置,
    在 typedef 声明中不能用 register(或任何其它存储类关键字)。

也许新手用这个关键字不多,但它却是一个很有用的关键字,可以使代码模块化程度更好(即与其它代码的关联较少),在C++中还是实现 Traits技术 的基础,也是模板编程的基本语法之一。
若说变量定义是为变量命名,而typedef(或称为类型定义)就是为类型命名。既然都是命名,那就会有很多类似的地方。而变量定义我想大家都会使用,因此类型定义也必然会使用。
类型定义的语法可以归结为一句话:只要在变量定义前面加上typedef,就成了类型定义。这儿的原本应该是变量的东西,就成为了类型。
如,下面的变量定义:
int integer;     //整型变量
int *pointer;   //整型指针变量
int array [5]; //整型数组变量
int *p_array [5]; //整型指针的数组的变量
int (*array_pointer) [5];//整型数组的指针的变量
int function (int param);//函数定义,也可将函数名看作函数的变量
int *function (int param);//仍然是函数,但返回值是整型指针
int (*function) (int param);//现在就是指向函数的指针了
若要定义相应类型,即为类型来起名字,就是下面的形式:
typedef int integer_t;                      //整型类型
typedef int *pointer_t;     //整型指针类型
typedef int array_t [5]; //整型数组类型
typedef int *p_array_t [5];    //整型指针的数组的类型    //这个就是我要找的;
typedef int (*array_pointer_t) [5]; //整型数组的指针的类型
typedef int function_t (int param);     //函数类型
typedef int *function_t (int param);    //函数类型    //这个就是我要找的;
typedef int (*function_t) (int param); //指向函数的指针的类型
注意: 上面的函数类型在C中可能会出错,因为C中并没有函数类型,它的函数变量会自动退化成函数指针;
在C++中好像是可以的。在这里主要说明的是形式上的相似性.
 
typedef的一般形式为:
typedef   类型     定义名;
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
其实,在C语言中声明变量的时候,有个 存储类型指示符 storage-class-specifier ),它包括我们熟悉的 extern、static、auto、register 。在不指定存储类型指示符的时候,编译器会根据约定自动取缺省值。另外,存储类型指示符的位置也是任意的(但要求在 变量名和指针* 之前),也就是说以下几行代码是等价的:
static const int i;
const static int i;
int const static i;
const int static i;
根据C语言规范, 在进行句法分析的时候,typedef和存储类型指示符是等价的 所以,我们把上述使用static的地方替换为typedef:
typedef const int i;
const typedef int i;
int const typedef i;
const int typedef i;
上述代码的语义是:将i定义为一个类型名,其等价的类型为const int。以后如果我们有i   a代码,就等价于const int a。对于有指针的地方也是一样的,比如:
int const typedef *t;那么代码t   p。就相当于int const *p。
另外,typedef不能和static等存储类型指示符同时使用,因为每个变量只能有一种存储类型,所以代码:typedef static int i;是非法的。
使用typedef简化复杂的变量声明
1)、定义一个有10个指针的数组,该指针指向一个函数,该函数有一个整形参数,并返回一个整型?
第一种方法:int (*a[10])(int);
第二种方法:typedef int (*pfunc)(int);
             pfunc a[10];
2)、定义一个有10个指针的数组,该指针指向一个函数,该函数有一个函数指针(不带参数,返回值为空)参数,并返回空。
第一种方法:void (*a[10])(void (*)(void));
第二种方法:typedef void (*pfuncParam)(void);
               typedef void (*pfunc)(pfuncParam);
pfunc a[10];
3)、一个指向有10个函数指针(不带参数,返回值为double)数组的指针
第一种方法:double (*)(void) (*p)[10];
第二种方法:typedef double (*pfunc)(void);
             typedef pfunc (*pfuncParam)[10];
             pfuncParam p;
总结:
typedef有两种用法:
一、一般形式,定义已有类型的别名
  typedef   类型    定义名;
二、创建一个新的类型
     typedef   返回值类型   新类型名(参数列表);




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值