sizeof测类型(数组名除外) strlen测实际长度 strncpy返回指针类型

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char *p="wangddd";
  7. printf("%d\n",sizeof(p));//输出4,指针类型
  8.  
  9. char x[];
  10. printf("%d\n",sizeof(x));//输出8,所占内存数。注意此处是8*1得出的8,若是int型数组则为8*4得32
  11.  
  12. printf("%s\n",strncpy(x,"wangddddd",sizeof(x)));//返回x指针,只能正常显示前7位,给x赋值时没有自动加上\0,
  13. //strncpy返回值是一个指针x
  14. printf("%d\n",sizeof(strncpy(x,"wangddddd",sizeof(x))));//输出4
  15. printf("%d\n",strlen(strncpy(x,"jskjksjdf",sizeof(x))));//随机 取决于编译环境
  16. printf("%d\n",strlen(strncpy(x,"jskjkse",sizeof(x))));//输出7,第8位正好是\0
  17.  
  18. char y[]="w c";
  19. printf("%d\n",strlen(y));//输出3
  20. printf("%d\n",sizeof(y));//输出5
  21.  
  22. return ;
  23. }

特殊之处:1 数组名不是指针,但神似指针,因为sizeof(X)打印的是8。具体的解释转载自:http://blog.chinaunix.net/uid-21765995-id-1815661.html

      2 sizeof可以如下使用:    

  1. 第一种用法:
      #include <iostream>
  2.   using namespace std;
  3.  
  4.   int main(int argc, char* argv[])
  5.   {
  6.   int i=;
  7.   cout<<sizeof(i)<<<<sizeof()<<sizeof <<endl;// sizeof(变量名) sizeof(常量名) sizeof 常量 都是可以的,但为了保持规范一般不写第三种
  8.   return ;
  9.   }
  1. 第二种用法:
      #include <iostream>
  2.   using namespace std;
  3.  
  4.   int sum(int a,int b)
  5.   {
  6.    cout<<a+b<<endl;
  7.    return a+b;
  8.   }
  9.  
  10. int main(int argc, char* argv[])
  11. {
  12.   int i=;
  13.   cout<<sizeof(sum(,))<<endl;
  14. return ;
  15. }
  16.  
  17. 结果为:4
    说明:仅打印了sum函数返回值的类型的大小,并没有调用函数。若sum无返回值则编译提示错误。

函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的:

  1. sizeof( sun );// error
  2. void foo2() { }
  3. sizeof( foo2() );// error
  4. struct S
  5. {
  6. unsigned int f1 : ;
  7. unsigned int f2 : ;
  8. unsigned int f3 : ;
  9. };
  10. sizeof( S.f1 );// error

对于结构中变量不能被sizeof计算是由于

让我们交换一下S1中char与int的位置:

  1. struct S2
  2. {
  3. int i;
  4. char c;
  5. };

看看sizeof(S2)的结果为多少,怎么还是8再看看内存,原来成员c后面仍然有3个填充字节,这又是为什么啊别着急,下面总结规律。

字节对齐的细节和编译器实现相关,但一般而言,满足三个准则: 
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除; 
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding); 
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)
  1. struct S3
  2. {
  3. char c1;
  4. S1 s;
  5. char c2;
  6. };

  S1的最宽简单成员的类型为int,S3在考虑最宽简单类型成员时是将S1“打散”看的,所以S3的最宽简单类型为int,这样,通过S3定义的变量,其存储空间首地址需要被4整除,整个sizeof(S3)的值也应该被4整除。 c1的偏移量为0,s的偏移量呢这时s是一个整体,它作为结构体变量也满足前面三个准则,所以其大小为8,偏移量为4,c1与s之间便需要3个填充字节,而c2与s之间就不需要了,所以c2的偏移量为12,算上c2的大小为13,13是不能被4整除的,这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。

通过上面的叙述,我们可以得到一个公式: 
结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目,即:
sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding )

“空结构体”(不含数据成员)的大小不为0,而是1。试想一个“不占空间”的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。如下:

  1. struct S5 { };
  2. sizeof( S5 ); // 结果为1
  1. #include <stdio.h>
  2. struct student
  3. {
  4. long id; //4字节
  5.  
  6. char name[]; //10字节
  7.  
  8. char sex; //1字节
  9.  
  10. int age; //4字节
  11.  
  12. float score; //4字节
  13.  
  14. };
  15. // 4+10+1+1+4+4
  16.  
  17. int main()
  18. {
  19. struct student one;
  20.  
  21. printf("%d", sizeof(struct student));
  22. }
  23. 这是我在QQ群里见到有人问的一道问题,结果为24,我说下自己的分析,若有不对还请高手指点,不胜感激。该结构体中最大的基本数据类型为4个字节(数组不是基本类型,被打散着看),所以该结构体的首地址为4的整数倍,id的偏移量为0,因为数组是一个整体,根据数组的sizeof可知其为10个字节,偏移量为sizeof(char)的整数倍,所以char[]的偏移量为4id决定),sex的偏移量也是sizeof(char)的整数倍,此时总共占了4++=15个字节,age的偏移量需要是sizeof(int)的整数倍,所以需要在sex后补上一个填充字节,所以age偏移量为16score的偏移量为16+=(可以被4整除),在算上score4个字节,为24,可以被结构体的最宽基本字节整除,所以整个结构体的sizeof(struct student)为24

对于参数中的数组类型,sizeof计算首地址时认为是指针:

  1. void foo3(char a3[])
  2. {
  3. int c3 = sizeof( a3 ); // c3 ==
  4. }
  5. void foo4(char a4[])
  6. {
  7. int c4 = sizeof( a4 ); // c4 ==
  8. }
  9. 也许当你试图回答c4的值时已经意识到c3答错了,是的,c3!=。这里函数参数a3已不再是数组类型,而是蜕变成指针,相当于char* a3,为什么仔细想想就不难明白,我们调用函数foo1时,程序会在栈上分配一个大小为3的数组吗不会!数组是“传址”的,调用者只需将实参的地址传递过去,所以a3自然为指针类型(char*),c3的值也就为4
memset
内存初始化函数memset()

作用:在一段内存中填充某个给定的值,注意填充时是按照字节顺序填充的,而不是按照元素填充。
此方法是对较大的结构体和数组进行清零操作的一种有效方法。
函数形式:memset(void *buffer,int c,size_t n)
buffer是需要设置的内存的开始地址;c是期望填充值;n是需要填充的字节数。
  1. 1:一个int
  2. a[]型变量,则memset(a,,sizeof(int))此操作后,元素a[]的每个字节的值都是100,即0x64,二进制表示:
  3. ,所以元素a[]为0x64646464,二进制表示:
  4. void main()
  5. { int i,a[];
  6. memset(a,,*sizeof(int));
  7. for(i=;i<;i++)
  8. cout< 此函数输出的10个元素并非10,而是每个字节都是00001010组成的int型数。
  9. 2:
  10. #include
  11. #include
  12. void main( void )
  13. {
  14. char buffer[] = "This is a test of the memset function";
  15. printf( "Before: %s\n", buffer );
  16. memset( buffer, '*', );
  17. printf( "After: %s\n", buffer );
  18. }
  19. Output
  20. Before: This is a test of the memset function
  21. After: **** is a test of the memset function
  22.  
  23. Memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为' ''\0'
  24. 例:char a[];
  25. memset(a, '\0', sizeof(a));
  26. memset可以方便地清空一个结构体类型的变量或数组。
  27. 如:
  28. struct sample_struct
  29. {
  30. char csName[];
  31. int iSeq;
  32. int iType;
  33. };
  34. 对于变量
  35. struct sample_strcut stTest;
  36. 一般情况下,清空stTest的方法:
  37. stTest.csName[]='\0';
  38. stTest.iSeq=;
  39. stTest.iType=;
  40. memset就非常方便:
  41. memset(&stTest,,sizeof(struct sample_struct));
  42. 如果是数组:
  43. struct sample_struct TEST[];

  44. memset(TEST,,sizeof(struct sample_struct)*);
memcpy 用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度。
例:char a[100],b[50]; memcpy(b, a, sizeof(b));
注意如果用memcpy(b,a,sizeof(a)),很可能会造成b的内存地址溢出。
Strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝。
例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘\0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。
str也可以用用个参数的strncpy(a,b,n)

        

sizeof strlen strncpy用法总结 结构体实际所占内存大小 以及memset用法的更多相关文章

  1. NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构

    本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存 ...

  2. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

  3. [C++关键字] alignof & alignas 内存对齐 sizeof 占内存大小

    直接上代码测试是入门神器,以结构体为例,解释“对齐”和“补齐”概念. #include <iostream> struct Empty {}; struct Foo { int f2; d ...

  4. .NET C#基础(5):结构体 - 高性能代码的基石

    0. 文章目的   本文面向有一定.NET C#基础知识的学习者,介绍C#中结构体定义.使用以及特点. 1. 阅读基础   了解C#基本语法   了解.NET中的栈与托管堆 2. 值类型 2.1 .N ...

  5. 【 转】 C/C++结构体和联合体的区别

    联合体用途:使几个不同类型的变量共占一段内存(相互覆盖) 结构体是一种构造数据类型用途:把不同类型的数据组合成一个整体-------自定义数据类型 总结: 声明一个联合体: union abc { i ...

  6. 结构体(struct)

    结构体 结构体是将不同类型的数据按照一定的功能需求进行整体封装,封装的数据类型与大小均可以由用户指定. 1 结构体的声明.定义及初始化 1.1 声明结构体类型 struct 结构体名 { 成员列表: ...

  7. 漫谈C语言结构体

    相信大家对于结构体都不陌生.在此,分享出本人对C语言结构体的学习心得.如果你发现这个总结中有你以前所未掌握的,那本文也算是有点价值了.当然,水平有限,若发现不足之处恳请指出.代码文件test.c我放在 ...

  8. 漫谈C语言结构体【转】

    相信大家对于结构体都不陌生.在此,分享出本人对C语言结构体的学习心得.如果你发现这个总结中有你以前所未掌握的,那本文也算是有点价值了.当然,水平有限,若发现不足之处恳请指出.代码文件test.c我放在 ...

  9. C语言 结构体作为函数的参数

    1)使用结构体变量作为函数的参数 使用结构体变量作为函数的实参时,采用的是值传递,会将结构体变量所占内存单元的内容全部顺序传递给形参,形参必须是同类型的结构体变量 demo: # include &l ...

随机推荐

  1. IPv6 tutorial 3 New features: IPsec and LAN features

    https://4sysops.com/archives/ipv6-tutorial-part-3-new-features-ipsec-and-lan-features/ In the last p ...

  2. 应付发票审批 Hold and Release Names

    (N) AP > Setup > Invoice > Hold and Release Names 这里一般默认就可以了.Use the Invoice Hold and Relea ...

  3. Hibernate一级缓存、二级缓存

    缓存就是把以前从数据库中查询出来和使用过的对象保存在内存中,准确说就是一个数据结构中,这个数据结构通常是或类似HashMap,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对 ...

  4. BZOJ2741: 【FOTILE模拟赛】L

    2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1170  Solved: 303[Submit][Status] ...

  5. ☀【css】透明

    让IE浏览器支持RGBA颜色http://www.hujuntao.com/web/css/ie-browser-support-for-rgba-color.html 透明纯色背景 backgrou ...

  6. iOS开发 .framework的Optional(弱引用)和Required(强引用)区别, 有错误 Library not found………………

    http://www.cnblogs.com/wanyakun/p/3494323.html 强引用(Required)的framework是一定会被加载到内存的,但是弱引用(Optional)的fr ...

  7. VS2010+WINDBG+VMWARE9.0和fatal error RC1106: invalid option: -ologo错误

    提供属性配置文件一份: http://pan.baidu.com/s/1iS1Ix <?xml version="1.0" encoding="utf-8" ...

  8. Asp.Net MVC4新特性指南(2):新特性介绍

       上一章讲解了最基本的MVC4说明.今天就介绍下几种新特性的使用例子:   就当大家有MVC3的基础了.在这个基础上在看下面的介绍就容易多了.1.Web API MVC4包括一个更好的解决方案:A ...

  9. S3C2440触摸屏驱动实例开发讲解

    出处:http://www.embeddedlinux.org.cn/html/yingjianqudong/ 一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--6 ...

  10. 使用Hadoop打造私有云盘之API操作

    项目介绍:使用hadoop实现云盘的增删读获取列表功能,hadoop不支持数据修改,特性是一次写入多次读取.主流的网盘也不支持该功能.今天我们用hdfs的FileSystem实现这些操作. 1.上传功 ...