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

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

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

      2 sizeof可以如下使用:    

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

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

sizeof( sun );// error
void foo2() { }
sizeof( foo2() );// error
struct S
{
unsigned int f1 : ;
unsigned int f2 : ;
unsigned int f3 : ;
};
sizeof( S.f1 );// error

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

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

struct S2
{
int i;
char c;
};

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

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

  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。试想一个“不占空间”的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。如下:

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

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

void foo3(char a3[])
{
int c3 = sizeof( a3 ); // c3 ==
}
void foo4(char a4[])
{
int c4 = sizeof( a4 ); // c4 ==
}
也许当你试图回答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:一个int
a[]型变量,则memset(a,,sizeof(int))此操作后,元素a[]的每个字节的值都是100,即0x64,二进制表示:
,所以元素a[]为0x64646464,二进制表示:
void main()
{ int i,a[];
memset(a,,*sizeof(int));
for(i=;i<;i++)
cout< 此函数输出的10个元素并非10,而是每个字节都是00001010组成的int型数。
例2:
#include
#include
void main( void )
{
char buffer[] = "This is a test of the memset function";
printf( "Before: %s\n", buffer );
memset( buffer, '*', );
printf( "After: %s\n", buffer );
}
Output
Before: This is a test of the memset function
After: **** is a test of the memset function Memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为' '或'\0';
例:char a[];
memset(a, '\0', sizeof(a));
memset可以方便地清空一个结构体类型的变量或数组。
如:
struct sample_struct
{
char csName[];
int iSeq;
int iType;
};
对于变量
struct sample_strcut stTest;
一般情况下,清空stTest的方法:
stTest.csName[]='\0';
stTest.iSeq=;
stTest.iType=;
用memset就非常方便:
memset(&stTest,,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[];

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. 【POJ】1692 Crossed Matchings

    经典DP,想了很久,开始想复杂了. #include <iostream> using namespace std; #define MAXNUM 100 int mymax(int a, ...

  2. centos中忘记root密码问题

    centos中root密码问题   几次在虚拟机中安装cenos,都没有提示输入root密码,具体操作如下: 1.在启动的时候,进入启动界面后,按除了Enter键之外的任意键,即可进入该界面.然后 按 ...

  3. dom操作之开关灯

    <!DOCTYPE html> <html> <meta http-equiv="Content-Type" content="text/h ...

  4. apache开源项目--hadoop

    Hadoop 是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系统(Had ...

  5. C#基础回顾:正则表达式

    C#基础回顾:正则表达式 写在前面:本文根据笔者的学习体会结合相关书籍资料对正则表达式的语法和使用(C#)进行基本的介绍.适用于初学者. 摘要:正则表达式(Regular Expressions),相 ...

  6. zookeeper 客户端编程

    zookeeper是一个分布式的开源的分布式协调服务,用它可以来现同步服务,配置维护.zookeeper的稳定性也是可以保证的,笔者曾参与过的使用zookeeper的两个应用,一个是用zookeepe ...

  7. lightoj 1002

    最短路的变形,使用spfa做. #include<set> #include<map> #include<list> #include<stack> # ...

  8. [POJ2484]A Funny Game

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4533   Accepted: 2780 Description Alice ...

  9. 股票中的数学:EMA的推导01

    说明:本人并不炒股,原因很简单:没钱.当然了,作为一名IT工作者,因为工作需要和个人兴趣,就有了本系列文章.阅读本系列文章不需要任何高深的知识,哪怕是一个像我这样从未真正炒过股的人也没关系.但本文还是 ...

  10. linux驱动程序之电源管理之标准linux休眠与唤醒机制分析(一)

    1. Based on linux2.6.32,  only for mem(SDR) 2. 有兴趣请先参考阅读: 电源管理方案APM和ACPI比较.doc Linux系统的休眠与唤醒简介.doc 3 ...