• C语言基础丨运算符之求字节数运算符和特殊运算符(十)


    求字节数运算符

    用于计算数据类型所占的字节数(sizeof)。

    一、sizeof的概念

    sizeof是c语言的一种单目操作符,如c语言的其他操作符++、--等。并且它并不是一个函数,sizeof的操作符以字节的形式给出了操作数的储存大小(操作数可以是一个表达式或括号里的类型名)并其储存的大小有操作数的类型决定,和本身无关系。

    二、sizeof的使用方法

    1.用于数据类型

     sizeof的使用形式:sizeof(char)注意数据类型必须用括号。

    2.用于变量

    sizeof使用形式:sizeof(a)或者 sizeof a都是正确的形式,但是大多的人都会带上括号。

    * sizeof的操作符不能用于函数类型,不完全类型。不完全类型是指具有未知储存大小的数据类型,如未知储存大小的数组类型、未知内容的结构或联合类void类型、、、、

    三、主要用途

    1.求基本类型和复合类型所占的内存字节数

    如:sizeof(int)、sizeof(int  *)

    2.求某个变量或者常量所占的内存字节数

    如:int i;

         sizeof(i)

         sizeof(5)

         sizeof(5L)

    3.求表达式所占的内存字节数,但是不执行括号里面的表达式

    如:size(i++), i的值不变

    4.求静态数组所占的内存字节数,这里的数组不能是指针,就是说所定义的数组和所用的sizeof的地方是同一个函数

    如:int a[10]

    5.求函数返回值类型所占字节数,但是不调用函数

    误区:

    1.sizeof是运算符不是函数

    2.用sizeof求到的是一个unsigned int 的值

    3.当数组是指针的时候求到的是指针所占的内存字节数

    4.不可以求void类型所占内存字节数,可以求void类型指针所占内存字节数

    sizeof(void)不可以

    sizeof(void *)可以

    四、特点

    1、sizeof是运算符,不是函数。sizeof以byte为单位返回操作数的大小。

    2、sizeof不能求得 void 类型的长度。

    3、sizeof能求得 void * 类型的长度。

    4、sizeof能求得静态分配内存的数组的长度。

    5、sizeof不能求得动态分配的内存的大小!

    6、sizeof不能对不完整的数组求长度!

    7、当表达式作为sizeof的操作数时,它返回表达式的计算结果的类型大小,但是它不对表达式求值!

    8、sizeof可以对函数调用求大小,并且求得的大小等于返回类型的大小,但是不执行函数体。

    9、sizeof求得的结构体(及其对象)的大小并不等于各个数据成员对象的大小之和! 

    10、sizeof不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小!

    关于运算符sizeof特点的详细解释,请参考https://blog.csdn.net/w57w57w57/article/details/6626840

    如果你正在学习编程遇到瓶颈,感到迷茫,困惑,值得加入我的【C语言C++学习企鹅圈子】
    学习交流,技术探讨,面试指导,简历修改...还有超多源码素材等学习资料,零基础的视频等着你!

    特殊运算符

    有括号(),下标[],成员(→,.)等几种。


     

    一、下标运算符 []

    借助于下标运算符 [](subscript operator),可以获取数组中单独的元素。下标运算符需要两个操作数。在最简单的情况下,一个操作数是一个数组名称,而另一个操作数是一个整数。

    在下面的示例中,假设 myarray 是一个数组的名称,并且 i 是一个整数类型的变量。表达式 myarray[i] 指定该数组内的第 i 号元素,数组中第 1 个元素的编号为 0,换句话说,第 i 号元素是数组中第 i+1 个元素。

    运算符 [] 的左操作数不一定需要是数组名称。一个操作数必须是一个指针类型表达式(例如,数组名称就是这类表达式的一种),同时,另一个操作数必须是整数。表达式 x[y] 等效于(*((x)+(y)))。下面的示例使用下标运算符初始化一个动态生成的数组。

    #include <stdlib.h>

    #define ARRAY_SIZE 100

    /* ... */

    double *pArray = NULL; int i = 0;

    pArray = malloc( ARRAY_SIZE * sizeof(double) );  // 生成这个数组

    if ( pArray != NULL ) {

      for ( i = 0; i < ARRAY_SIZE; ++i )                // 对数组进行初始化

        pArray[i] = (double)rand()/RAND_MAX;

    /* ... */

    }

    在该示例中,循环体内的表达式 pArray[i] 等效于 *(pArray+i)。i[pArray] 也是正确的,该表示方式也会生成相同的数组元素。

    二、成员(→,.)

    二元运算符 . 和 -> 常常被称为点运算符(dot operator)和箭头运算符(arrow operator),借助于这两个运算符,可以选择结构或联合中的成员。

    例 1 展示了点运算符的左操作数必须是一个结构或者一个联合,而右操作数必须是该类型(结构或联合)成员的名字。

    struct Article { long number; // 物品编号

                      char name[32];    // 物品名字

                      long price;      // 物品单价(精确到美分)

                      /* ... */

                    };

    struct Article sw = { 102030L, "Heroes", 5995L };

    sw.price = 4995L;                  // 将价格改为49.95

    点运算结果的类型,与所选择成员的类型是一样的。如果左操作数是一个左值,那么该运算也会产生左值。如果左操作数的类型有限定符(例如被声明为 const),那么结果类型也有该限定符。

    点运算符的左操作数并非一定是左值,如下例所示:

    struct Article getArticle();// 函数原型

    printf("name: %s ",getArticle().name);

    函数 getArticle()返回一个 struct Article 类型的对象。按此结果,getArticle().name 是一个有效的表达式,但不是一个左值,因为函数的返回值不是一个左值。

    运算符 -> 也可用于选择结构或联合的成员,但是箭头运算符的左操作数必须是一个指针,它指向一个结构或联合类型。右操作数是该结构或联合成员的名字。例 2 展示了运算符->的用法,同样使用例 1 所定义的结构 Article。

    【例2】

    struct Article *pArticle = &sw, // 一个指向struct Article的指针

          const *pcArticle = &sw;      // 一个指向struct Article的只读指针

    ++(pArticle->number);                    // 增加编号

    if ( pcArticle->number == 102031L ) // 正确:获取只读指针

      pcArticle->price += 50;        // 错误:不能使用限定符const的指针来修改对象

    箭头运算符的结果总是一个左值。它具有被选取成员的类型,也同样包括了其指针操作数的任何类型限定符。在例 2 中,pcArticle 是一个指向 const struct Article 的指针。其结果是,表达式 pcArticle->price 是一个常量。

    包含箭头运算符的任何表达式,都可以利用点运算符进行重写,做法是先将指针解参考,然后使用点运算符:表达式 p->m 等效于(*p).m;相反地,如果 x 是左值的话,表达式 x.m 等效于(&x)->m。

    和运算符 [] 一样,点运算符 . 和箭头运算符 -> 都具有最高的优先级,并且组合方式都是从左到右。因此,表达式 ++p->m 等同于 ++(p->m),表达式 p->m++ 等同于(p->m)++。

    然而,表达式(*p).m 中的括号是有必要的,因为复引用运算符 * 的优先级比较低。表达式 *p.m 等效于 *(p.m),这种等效仅当在成员 m 是指针时才有意义。

    我们通过结合下标运算符、点运算符和箭头运算符,对一个元素为结构的数组进行操作,来总结本文讲述的问题:

    struct Article arrArticle[10]; // 一个具有10个元素的数组

                                                    // 每个元素为结构类型

    arrArticle[2].price = 990L;            // 设置数组元素arrArticle[2]的成员price

    arrArticle->number = 10100L;        // 设置数组元素arrArticle[0]的成员number

    一个数组名称,例如本例中的 arrArticle,是一个指向第一个数组元素的常量指针。所以 arrArticle->number 指向第一个数组元素的成员 number。简单地说,对于任一的索引值 i,下面 3 个表达式是等价的:

    arrArticle[i].number

    (arrArticle+i)->number

    (*(arrArticle+i)).number

    它们都指向数组中索引值为 i 的元素的成员 number。

    今天就分享到这里啦,希望对大家学习有所帮助!


     
  • 相关阅读:
    隔离级别 && SNAPSHOT
    多态性&& 虚函数 && 抽象类
    socket编程
    [APIO2015]巴邻旁之桥
    LuoguP3701 「伪模板」主席树
    线段树标记永久化
    [HNOI2015]开店
    NOIP2017划水记
    FFTNTT总结
    [THUWC 2017]在美妙的数学王国中畅游
  • 原文地址:https://www.cnblogs.com/mu-ge/p/14379416.html
Copyright © 2020-2023  润新知