sizeof 

一、简单介绍

sizeof 是 C 语言的一种单目操作符,如 C 语言的其他操作符++、--等。它并不是函数。C 规定 sizeof 返回 sieze_t 类型的值。这是一个无符号整数类型。C99更进一步,把%zd 作为用来显示 size_t 类型值的 printf() 说明符。如果你的系统没有实现 %zd,你可以试着使用 %u 或者 %lu 代替它。

sizeof 操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。

二、使用方法

1、用于数据类型

sizeof 使用形式: sizeof (type)

数据类型必须用圆括号括住。如:sizeof (int)

2、用于变量

sizeof 使用形式:sizeof (var_name) 或 sizeof var_name

变量名可以不用圆括号括住。如:sizeof (6.08) 或 sizeof 6.08 等都是正确的形式。带括号的用法更普遍,大多数程序员采用这种形式。

注意:sizeof 操作符不能用于函数类型,不完全类型和位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型未知内容的结构或联合类型void类型等。如:

sizeof (max) 若此时变量 max 定义为 int max ( ),

sizeof (char_v) 若此时 char_v 定义为 char char_v [MAX] 且 MAX 未知

sizeof (void)

上述例子,都是不正确的形式。

3、sizeof 的结果

sizeof 操作符的结果类型是 size_t,它在头文件中 typedef 为 unsigned int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。

1)在windows,32位系统中
char         1个字节
short        2个字节
int            4个字节
long         4个字节
double    8个字节
float         4个字节

看看这三个分别是什么?
1,‘ 1‘,“ 1”。

第一个是整形常数, 32 位系统下占 4 个 byte;
第二个是字符常量,占 1 个 byte;
第三个是字符串常量,占 2 个 byte。

三者表示的意义完全不一样,所占的内存大小也不一样,初学者往往弄错。

2)当操作数为指针时,sizeof 依赖于编译器。一般unix的指针为 4个字节

#include <stdio.h>int main (void)
{char ptr[] = "hello";char *str = ptr;printf ("sizeof (str) = %d\n", sizeof (str));return 0;
}
输出结果:
sizeof (str) = 4

在 32 位系统下,不管什么样的指针类型,其大小都为 4 byte。可以测试一下 sizeof( void *)。

3)当操作数具有数组类型时,其结果是数组的总字节数

#include <stdio.h>int main (void)
{int ptr[20] = {1,2,3,4,5};printf ("sizeof (ptr) = %d\n", sizeof (ptr));return 0;
}
输出结果:
sizeof (ptr) = 80

4)联合类型操作数的 sizeof 是其最大字节成员的字节数,结构体类型操作数的sizeof,需要考虑内存对齐补齐。

参看:C语言再学习 -- 结构和其他数据形式

[cpp] view plaincopy
  1. #include <stdio.h>
  2. typedef union {
  3. char ch;
  4. int num;
  5. }UN;
  6. int main (void)
  7. {
  8. printf ("sizeof (UN) is %d\n", sizeof (UN));
  9. return 0;
  10. }
  11. 输出结果:
  12. sizeof (UN) is 4

结构体内存对齐与补齐

一个存储区的地址一定是它自身大小的整数倍(双精度浮点类型的地址只需要4的整数倍就行了),这个规则也叫数据对齐,结构体内部的每个存储区通常也需要遵守这个规则。数据对齐可能造成结构体内部存储区之间有浪费的字节。
结构体的大小一定是内部最大基本类型存储区大小的整数倍,这个规则叫数据补齐

[cpp] view plaincopy
  1. #include <stdio.h>
  2. typedef struct
  3. {
  4. char ch;
  5. int num;
  6. char ch1;
  7. }str;
  8. int main (void)
  9. {
  10. printf ("sizeof (str) is %d\n", sizeof (str));
  11. return 0;
  12. }
  13. 输出结果:
  14. sizeof (str) is 12

5)如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小

#include <stdio.h>char ca[10];void foo (char ca[100])
{printf ("sizeof (ca) = %d\n", sizeof (ca));
}
int main (void)
{char ca [25];foo (ca);return 0;
}
输出结果:
sizeof (ca) = 4

三、主要用途

1、sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:void *malloc(size_t size), size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 

2、sizeof的另一个的主要用途是计算数组中元素的个数。例如:void *memset(void *s,int c,sizeof(s))

3.在动态分配一对象时,可以让系统知道要分配多少内存。如:int *p=(int *)malloc(sizeof(int)*10);

4.由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。

5.如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。


四、注意的地方

1、在混合类型的算术运算的情况下,较小的类型被转换成较大的类型。反之,可能会丢失数据。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main (void)
{int a = 10;printf ("sizeof ((a > 5) ? 4 : 8.0) = %d\n", sizeof ((a > 5) ? 4 : 8.0));return 0;
}
输出结果:
sizeof ((a > 5) ? 4 : 8.0) = 8

2、判断表达式的长度并不需要对表达式进行求值

#include <stdio.h>
int main (void)
{int a = 10;int b = 0;int c = sizeof (b = a + 12);printf ("a = %d, b = %d, c = %d\n", a, b, c);return 0;
}
输出结果:
a = 10, b = 0, c = 4

所以sizeof (b = a + 12)并没有向 a 赋任何值。

strlen

strlen首先是一个函数,只能以char * 做参数返回的是字符的实际长度,不是类型占内存的大小。其结果是运行的时候才计算出来的。

#include <string.h>
size_t strlen(const char *s);

函数功能:用来统计字符串中有效字符的个数

功能实现函数:

[cpp] view plaincopy
  1. size_t strlen (const char *s)
  2. {
  3. const char *sc;
  4. for (sc = s; *sc != '\0'; ++sc)
  5. /"nothing"/
  6. return sc - s;
  7. }

strlen()函数被用作改变字符串长度,例如:

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <string.h>
  3. void fit (char *, unsigned int);
  4. int main (void)
  5. {
  6. char str[] = "hello world";
  7. fit (str, 7);
  8. puts (str);
  9. puts (str + 8);
  10. return 0;
  11. }
  12. void fit (char *string, unsigned int size)
  13. {
  14. if (strlen (string) > size)
  15. *(string + size) = '\0';
  16. }
  17. 输出结果:
  18. hello w
  19. rld

可以看出:fit()函数在数组的第8个元素中放置了一个'\0'字符来代替原有的o字符。puts()函数输出停在o字符处,忽略了数组的其他元素。然而,数组的其他元素仍然存在。

puts (str + 8);

表达式str + 8是str[8]即'r'字符的地址。因此puts()显示这个字符并且继续输出知道遇到原字符串中的空字符。

sizeof 与 strlen 的区别

参看:C语言再学习 -- 字符串和字符串函数

谈两者的区别之前,先要讲一下什么是字符串,字符串就是一串零个或多个字符,并且以一个位模式为全 0 的 '\0' 字节结尾。如在代码中写 "abc",那么编译器帮你存储的是 "abc\0"。

siezeof运算符提供给你的数目比strlen大1,这是因为它把用来标志字符串结束的不可见的空字符('\0')也计算在内。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>int main (void)
{char *str1 = "abcde";char str2[] = "abcde";char str3[8] = "abcde";char str4[] = {'a', 'b', 'c', 'd', 'e'};char *p1 = malloc (20);printf ("sizeof (str1) = %d, strlen (str1) = %d\n", sizeof (str1), strlen (str1));printf ("sizeof (*str1) = %d, strlen (str1) = %d\n", sizeof (*str1), strlen (str1));printf ("sizeof (str2) = %d, strlen (str2) = %d\n", sizeof (str2), strlen (str2));printf ("sizeof (str3) = %d, strlen (str3) = %d\n", sizeof (str3), strlen (str3));printf ("sizeof (str4) = %d, strlen (str4) = %d\n", sizeof (str4), strlen (str4));printf ("sizeof (p1) = %d, sizeof (*p1) = %d\n", sizeof (p1), sizeof (*p1));printf ("sizeof (malloc(20)) = %d\n", sizeof (malloc (20)));return 0;
}
输出结果:
sizeof (str1) = 4, strlen (str1) = 5
sizeof (*str1) = 1, strlen (str1) = 5
sizeof (str2) = 6, strlen (str2) = 5
sizeof (str3) = 8, strlen (str3) = 5
sizeof (str4) = 5, strlen (str4) = 5
sizeof (p1) = 4, sizeof (*p1) = 1
sizeof (malloc(20)) = 4

总结:

1. sizeof 操作符的结果类型是 size_t,它在头文件中typedef为 unsigned int 类型。该类型保证能容纳实现所建立的最大对象的字节大小。

2. sizeof 是算符,strlen 是函数

3. sizeof可以用类型做参数strlen只能用char*做参数且必须是以''\0''结尾的。sizeof 还可以用函数做参数,比如:

short f();
printf("%d\n",sizeof(f()));
输出的结果是sizeof(short),即2。

4.数组做 sizeof 的参数不退化,传递给 strlen 就退化为指针了。

5.大部分编译程序 在编译的时候就把 sizeof 计算过了 是类型或是变量的长度这就是 sizeof(x) 可以用来定义数组维数的原因
charstr[20]="0123456789";
int a=strlen(str);//a=10;
int b=sizeof(str);//而b=20;

6. strlen 的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小

7. sizeof 后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符不是个函数。

8. 当适用了于一个结构类型时或变量, sizeof 返回实际的大小,当适用一静态地空间数组, sizeof 归还全部数组的尺寸。sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸。

9. 数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:
fun(char [8])
fun(char [])
都等价于 fun(char *)
在C++里参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小如果想在函数内知道数组的大小, 需要这样做:进入函数后用memcpy拷贝出来,长度由另一个形参传进去
fun(unsiged char*p1, int len)
{
    unsigned char* buf= new unsigned char[len+1]
    memcpy(buf, p1,len);
}

我们能常在用到 sizeof 和 strlen 的时候,通常是计算字符串数组的长度看了上面的详细解释,发现两者的使用还是有区别的,从这个例子可以看得很清楚:

charstr[20]="0123456789";
int a=strlen(str);//a=10; >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。
int b=sizeof(str);//而b=20; >>>> sizeof 计算的则是分配的数组 str[20] 所占的内存空间的大小,不受里面存储的内容改变。
上面是对静态数组处理的结果,如果是对指针,结果就不一样了

char* ss ="0123456789";
sizeof(ss) 结果4 ===》ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间,应该是 长整型的,所以是4
sizeof(*ss) 结果1 ===》*ss是第一个字符 其实就是获得了字符串的第一位'0' 所占的内存空间,是char类 型的,占了 1 位
strlen(ss)= 10 >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。

面试题:

1、sizeof( int) *p 表示什么意思?

需要明白 sizeof 后跟数据类型,必须要用圆括号括住的,强制类型转换也应该是 (int*) p,所以这句话所表达的意思是 sizeof (int) 乘以 p

#include <stdio.h>int main (void)
{int p = 1;printf ("%d\n", sizeof (int)*p); return 0;
}
输出结果:
4
#include <stdio.h>int main (void)
{int p = 1;printf ("%d\n", sizeof ((int *)p));  //强制类型转换return 0;
}
输出结果:
4

2、在 32 位系统下:
int *p = NULL;
sizeof(p)的值是多少?
sizeof(*p)呢?

sizeof (p) = 4;  因为 p为指针,32位系统 指针所占字节为 4个字节

sizeof (*p) = 4;  因为 *p 为 指针所指向的变量为int类型,整型为 4个字节

#include <stdio.h>int main (void)
{short *p = NULL;int i = sizeof (p);int j = sizeof (*p);printf ("i = %d, j = %d\n", i, j);return 0;
}
输出结果:
i = 4, j = 2

3、int a[100];
sizeof (a) 的值是多少?
sizeof(a[100])呢? //请尤其注意本例。
sizeof(&a)呢?
sizeof(&a[0])呢?

sizeof (a) = 400;  因为 a是类型为整型、有100个元素的数组,所占内存为400个字节

sizeof (a[100]) = 4;  因为 a[100] 为数组的第100元素的值该值为 int 类型,所占内存为4个字节。

sizeof (&a) = 4;  因为 &a 为数组的地址即指针,32位系统 指针所占字节为 4个字节

sizeof (&a[0]) = 4; 因为&a[0] 为数组的首元素的地址即指针,32位系统 指针所占字节为 4个字节

#include <stdio.h>int main (void)
{int a[100];printf ("sizeof (a) = %d\n", sizeof (a));printf ("sizeof (a[100] = %d\n", sizeof (a[100]));printf ("sizoef (&a) = %d\n", sizeof (&a));printf ("sizeof (&a[0] = %d\n)", sizeof (&a[0]));return 0;
}
输出结果:
sizeof (a) = 400
sizeof (a[100] = 4
sizoef (&a) = 4
sizeof (&a[0] = 4

4、int b[100];
void fun(int b[100])
{
sizeof(b);// sizeof (b) 的值是多少?
}

sizeof (b) = 4;  因为函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。参数传递数组永远都是传递指向数组首元素的指针。

#include <stdio.h>void fun (int b[100]) //指针做形参
{printf ("sizeof (b) = %d\n", sizeof (b));
}int main (void)
{int a[10];fun (a);return 0;
}
输出结果:
sizeof (b) = 4
#include <stdio.h>
void foo (void)
{printf ("111\n");
}void fun (foo) //函数做形参
{printf ("sizeof (foo) = %d\n", sizeof (foo));
}
int main (void)
{fun ();return 0;
}
输出结果:
sizeof (foo) = 4

C语言再学习 -- 关键字sizeof与strlen相关推荐

  1. C语言再学习--关键字

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/53021879 C语言一共有32个关键字,如下表所示: 关键字 说明 auto ...

  2. C语言再学习 -- 关键字const

    const 关键字其实我们并不陌生,之前有讲过const修饰数组和指针.现在来详细介绍这个关键字. 参看:[C/C++和指针]著名的<const的思考> 一.const 介绍 1.cons ...

  3. C语言再学习 -- 关键字typedef

    参看:C语言再学习 -- 结构和其他数据形式 参看:C语言再学习 -- 关键字struct(转) 参看:常见typedef 用法 参看:关于typedef的用法总结 一.typedef 介绍 type ...

  4. C语言再学习 -- 关键字struct(转)

    参看:C语言再学习 -- 结构和其他数据形式 参看:c语言中的关键字struct(结构体)的用法 整理总结: 结构体的一般定义形式为: 标签(tag)字段允许为成员列表提供一个名字,这样它就可以在后续 ...

  5. C语言再学习 -- 关键字volatile

    上周确实事情挺多的,年会.公司聚餐,一到过年就有忙不完的事分心.还好C语言再学习总结的已经差不多了,年前也不展开别的了,接下来这十几天.总结几篇典型的面试题吧. 言归正传,接下来看看关键字 volat ...

  6. C语言再学习 -- 关键字return和exit ()函数

    终于到了最后一个关键字 return 了.感觉时间过的飞快,转眼间又是一年,如果时间可以 return 就好了. 一.return 介绍 参看:C语言中return 用法 1.含义: return 表 ...

  7. C语言再学习 -- 关键字void

    参看:C语言关键字 void 用途: 1.对函数返回的限定,用于强调函数没有返回值.如,void func(int x); 2.对函数参数的限定,用于强调函数没有任何参数.如,int func(voi ...

  8. C语言再学习 -- 详解C++/C 面试题 1

    参看:<高质量C++ C编程指南>.林锐 对这篇文章记忆犹新,因为之前找工作面试的时候,遇到过一家公司就是用的这套面试题.现在就结合考查的知识点和我总结完 C 语言再学习后的深入理解,来详 ...

  9. C语言再学习 -- 再论数组和指针

    之前有总结指针数组,但是现在看来总结的太简单了.好多重要的知识点都是一带而过的.本想在后面添加后来想想算了,还是再写一篇文章来详细介绍数组和指针这对冤家吧. 之前总结的,参看:C语言再学习 -- 数组 ...

最新文章

  1. 浅谈Java中的final关键字
  2. java面试精典问答
  3. JVM 调优实战--VisualVM综合分析可视化工具的使用教程(含远程JMX连接)
  4. LCP 07. 传递信息
  5. 【华为敏捷/DevOps实践】3. 如何开好站立会议
  6. ttc文件linux安装,centos系统安装中文字体几种方法
  7. centos7.6(腾讯云)开放端口及配置腾讯云安全组
  8. cannot run program “google-chrome“: error=2, 没有那个文件或目录
  9. 项目视频讲解_基于SSH2+Maven+EasyUI+MySQL技术实战开发易买网电子商务交易平台
  10. Java入门 - 循环结构基础
  11. ubuntu设置maven环境变量
  12. STC8G1K08A之PWM占空比调整
  13. 投稿Springer旗下某中科院1区TOP期刊时间记载
  14. mysql 创建外部表_Greenplum
  15. 【PMP】PMBOK 笔记 第7章 项目成本管理
  16. 制作esp32-cam拍照上传,微信小程序照片显示的监控小车
  17. (CodeForces) D. Kilani and the Game (搜索)
  18. 修改苹果Mac终端前面的计算机名
  19. 《计算机网络》(第8版)第五章 运输层 知识点总结
  20. 面试被问死怎么办?学会这四招,通过的机率提升30%

热门文章

  1. linux 网络编程 2---(TCP编程)
  2. Play on Words UVA - 10129 (有向图欧拉路径)
  3. 【Mysql】MySQL event 计划任务
  4. 同域下跨文档通信iframe和window.open
  5. 第五节 面向对象相关特性
  6. 编译安装Apache2.4.10
  7. 做毕设时遇到的一些问题,以及一些小技巧
  8. 函数名称前面加引用“”或指针符号“*”的意思
  9. 交通银行软件中心编制_国家标准研究项目区块链服务技术安全要求编制启动会顺利召开...
  10. Ubuntu 16.04网速慢解决方法