浅析C语言中的sizeof

这是一个依赖于编译系统的值,一
般定义为typedef unsigned int size_t;编译器林林总总,但作为一个规范,都会保证char、signed
char和unsigned char的sizeof值为1,毕竟char是编程能用的最小数据类型。
MSDN上的解释为:
The sizeof keyword gives the amount of storage, in bytes, associated with avariable or a
type (including aggregate types). This keyword returns a value of type
size_t.

2. 语法:
sizeof有三种语法形式,如下:
1) sizeof( object ); // sizeof( 对象 );
2) sizeof( type_name ); // sizeof( 类型 );
3) sizeof object; // sizeof 对象;
所以一下三种sizeof的使用都是对的


代码如下:

#include <stdio.h>
main()
{
int b;
printf("%d\n",sizeof b);
printf("%d\n",sizeof(b));
printf("%d\n",sizeof(int));
}

4. 基本数据类型的sizeof
这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型,由于它们都是和系
统相关的,所以在不同的系统下取值可能不同,这务必引起我们的注意,尽量不要在
这方面给自己程序的移植造成麻烦。一般的,在32位编译环境中,sizeof(int)的取值为4。

5. 指针变量的sizeof
等于计算机内部地址总线的宽度。所以在32位计算机中,一个指针变量的返回值必定是4(注意结果是以
字节为单位),可以预计,在将来的64位系统中指针变量的sizeof结果为8。
指针变量的sizeof值与指针所指的对象没有任何关系,正是由于所有的指针变量所占内存大小相等,所以
MFC消息处理函数使用两个参数WPARAM、LPARAM就能传递各种复杂的消息结构(使用
指向结构体的指针)。

6. 数组的sizeof
数组的sizeof值等于数组所占用的内存字节数,如:
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int)
sizeof当作了求数组元素的个数是不对的,求数组元素的个数有下面两种写法:int c1 = sizeof( a1 )
/ sizeof( char ); // 总长度/单个元素的长度
int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 总长度/第一个元素的长度.注意数组名做函数参数传递
时退化为指针。

7. 结构体的sizeof
struct S1
{
char c;
int i;
};
sizeof的结果等于对象或者类型所占的内存字节数,好吧,那就让我们来看看S1的内存分配情况:S1 s1
= { 'a', 0xFFFFFFFF };s1的地址为0x0012FF78,其数据内容如下:

0012FF78: 61 CC CC CC FF FF FF FF中间夹杂了3个字节的CC看看MSDN上的说明:When applied to a
structure type or variable, sizeof returns the actual size, which may
include padding bytes inserted for alignment.

这就是字节对齐!为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机的取数速度,否则
就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数
据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本
数据类型(int等)都位于能被4整除的地址上,以此类推。这样,两个数中间就可能
需要加入填充字节,所以整个结构体的sizeof值就增长了。

1.sizeof是运算符,跟加减乘除的性质其实是一样的,在编译的时候进行执行,而不是在运行时才执行。
那么如果编程中验证这一点呢?


代码如下:

<SPAN style="FONT-SIZE: 18px">#include<iostream></SPAN><SPAN style="FONT-SIZE: 14px">

using namespace std;

int main()
{
    int i=1;
    cout<<i<<endl;
    sizeof(++i);
    cout<<i<<endl;
    return 1;
}</SPAN>

输入结果为 1  
               1
sizeof中的++i 的副作用并没有显示出来,原因只可能有一个,在编译的时候sizeof执行以后将++i 处理了,++i 的副作用因此被消除了。如果sizeof 是在运行时进行的话,则肯定要注意++i 。实际上sizeof的实现应该是用宏来做的,宏在编译时进行执行。具体实现可以参考下面。
2.sizeof('a')在C语言中的结果是4,在C++中结果是1,看过某篇文章说C中sizeof侧重于“数”,而C++中sizeof更侧重于“字符”。

3.文章中讲了两个用宏实现sizeof的经典应用


代码如下:

//适用于非数组
#define _sizeof(T) ((size_t)((T*)0 + 1))
//适用于数组
#define array_sizeof(T) ((size_t)(&T+1)-(size_t)(&T))

先举两个小例子说明两个宏的应用,对于第一个如 _sizeof(int); 的结果就是4;对于第二个先声明一个大小为4的数组int a[4];那么array_sizeof(a)结果为16.

对于非数组的宏定义,先是将0转换为T*类型的指针所指向的地址(此时地址为0)。然后对T类型的地址加1,相当于加上了T类型的大小(即得到了非数组T的大小)。前面的size_t只是将地址转化为int型的整数返回。
一个简单的例子:int* p; p=p+1; --------p是一个int*类型的指针, p+1在地址空间上相当于加上了4个字节。

对于数组的宏定义,类似于非数组的宏定义,为了方便理解,这里可以把数组T看成一个用户自定义的类型,&T表示数组类型的指针,对于数组类型指针加1相当于在地址上加上了该数组大小。由于是用户自定义的类型所以不能强制将0转化为数组类型的地址,只能用加1后的地址减去之前的地址,得到的差值就是数组本身所占的字节大小。

(0)

相关推荐

  • C语言中的sizeof操作符用法及和strlen的区别

    一. 定义: sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数.其返回值类型为size_t,在头文件stddef.h中定义.在32位系统中: char的sizeof值为1,char是我们编程能用的最小数据类型. short的sizeof值为2: int.float.long为4: double为8: 所有的指针的sizeof值都为4. 二.语法: sizeof有三种语法形式,如下: 1) sizeof( object ); //

  • C语言中关于sizeof 和 strlen的区别分析

    1.编译时计算运算符sizeof,可用类型或变量做参数,计算占用内存的大小.sizeof后若是类型必须加括弧,若是变量名可不加括弧.sizeof(x)可用来定义数组维数如: 复制代码 代码如下: printf("%d\n", sizeof(short)); 输出的结果为短整型的长度2.用结构类型或变量做参数时,sizeof 返回实际的大小,当用于静态数组时,sizeof 返回全部数组的尺寸.sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸 2.运行时计算strlen,

  • C语言位运算和sizeof运算符详解

    位运算和sizeof运算符 C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的.位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果.位运算主要有6种:与(&),或(|),取反(~),异或(^),左移(<<),右移(>>). 1.位运算中的类型转换 位运算都必须进行Integer Promotion.在进行运算之前,都必须将char型.short型的数据转换为int或者unsigned int型再参与运算. 如下面这段程

  • C++无法重载点符号、::、sizeof等的原因

    大多数的运算符能够被程序员重载.例外的是:     . (点符号) :: ?: sizeof 并没有什么根本的原因要禁止重载?:.仅仅是因为,我没有发现有哪种特殊的情况需要重载一个三元运算符.注意一个重载了 表达式1?表达式2:表达式3 的函数,不能够保证表达式2:表达式3 中只有一个会被执行. Sizeof 不能够被重载是因为内建的操作(built-in operations),诸如对一个指向数组的指针进行增量操作,必须依靠它.考虑一下: X a[10]; X* p = &a[3]; X* q

  • C#中sizeof的用法实例分析

    sizeof是C#中非常重要的方法,本文就以实例形式分析C#中sizeof的用法.分享给大家供大家参考.具体分析如下: 在C#中,sizeof用来计算类型的大小,单位是字节.有这样的一个类: public class MyUglyClass { public char myChar1; public int myInt; public char myChar2; } 在客户端,试图使用sizeof计算该类型的大小. class Program { static void Main(string[

  • 深入sizeof的使用详解

    经常在C下编程,不了解精通sizeof就有点说不过去了,本文可没有sizeof与strlen的区别哦,尽管这个对比很经典,不过,将就点吧. 一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等.它并不是函数.sizeof操作符以字节形式给出了其操作数的存储大小.    操作数可以是一个表达式或括在括号内的类型名.操作数的存储大小由操作数的类型决定. 二.sizeof的使用方法1.用于数据类型 sizeof使用形式:sizeof(type) 数据类型必须用

  • sizeof()的简单介绍

    (一)基本概念 sizeof操作符以字节形式给出了其操作数的存储大小.操作数可以是一个表达式或括在括号内的类型名.操作数的存储大小由操作数的类型决定. (二)使用方法 1.用于数据类型 sizeof使用形式:sizeof(type) ,如sizeof(int) 2.用于变量 sizeof使用形式:sizeof(var_name)或sizeof var_name 变量名可以不用括号括住.如sizeof (var_name),sizeof var_name等都是正确形式.带括号的用法更普遍,大多数程

  • php检测数组长度函数sizeof与count用法

    本文实例讲述了php检测数组长度函数sizeof与count用法.分享给大家供大家参考.具体如下: 在php检测数组长度的函数有sizeof count 下面看个简单实例: 复制代码 代码如下: $colorlist = array("apple"=>"red", "grass"=>"green","sky"=>"blue","night"=>

  • C语言中sizeof()与strlen()函数的使用入门及对比

    sizeof()函数 1,是什么?     sizeof其实就是一个运算符,和那些+,-一样的东西,在程序编译的时候进行解析转换.虽然我们经常见到sizeof后面跟着个小括号,长得和函数差不多,但它和函数完全是两码事. 2,有什么用?     sizeof其实就是用于告诉我们编译器在为某一特定数据或者某种数据类型的数据在存储空间中开辟空间时,开辟的空间大小,以字节为单位. 3,怎么用?     sizeof(类型),或者sizeof(变量)都可以,得到的就是类型或者变量的存储空间.当对变量用的时

  • 解析一个有关sizeof用法的题目--sizeof(i++)

    复制代码 代码如下: #include <stdio.h>  int main()  {  int i;  i = 10;  printf("%d\n", i);  printf("%d\n", sizeof(i++));  printf("%d\n", i);  return 0;  } 这三行输出应该是什么?答案是:10410第三个为什么不是11? i为什么没有自增?请看C++标准;5.3.3 sizeofThe sizeof o

随机推荐