sizeof(string)为何返回4?

作者&投稿:穆果 (若有异议请与网页底部的电邮联系)
C语言sizeof('a')的返回值为什么是4,而不等于sizeof(char)~

C语言里就是把字符常量当做了整型处理的.
在c中'a'这类的是代表着'a'这类的ACSII的值..
而在c++中'a'这类就代表一个字符常量
sizeof 'a'
所以在VC++里,为 4 不为2 的原因.
你注意看我第一句话..在c中这个字符常量是被当做一个整形来处理的

string str;
str放的是地址,sizeof(str)相当于sizeof(int);

结构体的sizeof
这是初学者问得最多的一个问题,所以这里有必要多费点笔墨。让我们先看一个结构体:
struct S1
{
char c;
int i;
};
问sizeof(s1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。是这样吗你在你机器上试过了吗也许你是对的,但很可能你是错的!VC6中按默认设置得到的结果为8。

Why为什么受伤的总是我
请不要沮丧,我们来好好琢磨一下sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那就让我们来看看S1的内存分配情况:
S1 s1 = { 'a', 0xFFFFFFFF };
定义上面的变量后,加上断点,运行程序,观察s1所在的内存,你发现了什么
以我的VC6.0为例,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值就增长了。
让我们交换一下S1中char与int的位置:
struct S2
{
int i;
char c;
};
看看sizeof(S2)的结果为多少,怎么还是8再看看内存,原来成员c后面仍然有3个填充字节,这又是为什么啊别着急,下面总结规律。

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

对于上面的准则,有几点需要说明:
1) 前面不是说结构体成员的地址是其大小的整数倍,怎么又说到偏移量了呢因为有了第1点存在,所以我们就可以只考虑成员的偏移量,这样思考起来简单。想想为什么。

结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
例如,想要获得S2中c的偏移量,方法为
size_t pos = offsetof(S2, c);// pos等于4

2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型,这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。
这里叙述起来有点拗口,思考起来也有点挠头,还是让我们看看例子吧(具体数值仍以VC6为例,以后不再说明):
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 )

到这里,朋友们应该对结构体的sizeof有了一个全新的认识,但不要高兴得太早,有一个影响sizeof的重要参量还未被提及,那便是编译器的pack指令。它是用来调整结构体对齐方式的,不同编译器名称和用法略有不同,VC6中通过#pragma pack实现,也可以直接修改/Zp编译开关。#pragma pack的基本用法为:#pragma pack( n ),n为字节对齐数,其取值为1、2、4、8、16,默认是8,如果这个值比结构体成员的sizeof值小,那么
该成员的偏移量应该以此值为准,即是说,结构体成员的偏移量应该取二者的最小值,
公式如下:
offsetof( item ) = min( n, sizeof( item ) )
再看示例:
#pragma pack(push) // 将当前pack设置压栈保存
#pragma pack(2) // 必须在结构体定义之前使用
struct S1
{
char c;
int i;
};
struct S3
{
char c1;
S1 s;
char c2;
};
#pragma pack(pop) // 恢复先前的pack设置
计算sizeof(S1)时,min(2, sizeof(i))的值为2,所以i的偏移量为2,加上sizeof(i)等于6,能够被2整除,所以整个S1的大小为6。
同样,对于sizeof(S3),s的偏移量为2,c2的偏移量为8,加上sizeof(c2)等于9,不能被2整除,添加一个填充字节,所以sizeof(S3)等于10。

现在,朋友们可以轻松的出一口气了,:)
还有一点要注意,“空结构体”(不含数据成员)的大小不为0,而是1。试想一个“不占空间”的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。如下:
struct S5 { };

第一个例子:

char* ss = "0123456789";
sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针/////////////////////////////////你要的答案
sizeof(*ss) 结果 1 ===》*ss是第一个字符

char ss[] = "0123456789";
sizeof(ss) 结果 11 ===》ss是数组,计算到\0位置,因此是10+1
sizeof(*ss) 结果 1 ===》*ss是第一个字符

char ss[100] = "0123456789";
sizeof(ss) 结果是100 ===》ss表示在内存中的大小 100×1
strlen(ss) 结果是10 ===》strlen是个函数内部实现是用一个循环计算到\0为止之前

int ss[100] = "0123456789";
sizeof(ss) 结果 400 ===》ss表示再内存中的大小 100×4
strlen(ss) 错误 ===》strlen的参数只能是char* 且必须是以''\0''结尾的

char q[]="abc";
char p[]="a\n";
sizeof(q),sizeof(p),strlen(q),strlen(p);
结果是 4 3 3 2

第二个例子:

class X
{
int i;
int j;
char k;
};
X x;
cout<<sizeof(X)<<endl; 结果 12 ===》内存补齐
cout<<sizeof(x)<<endl; 结果 12 同上

第三个例子:

char szPath[MAX_PATH]

如果在函数内这样定义,那么sizeof(szPath)将会是MAX_PATH,但是将szPath作为虚参声明时(void fun(char szPath[MAX_PATH])),sizeof(szPath)却会是4(指针大小)

三、sizeof深入理解。

* 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)可以用来定义数组维数的原因

char str[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);
}

有关内容见: C++ PRIMER?
* 10.计算结构变量的大小就必须讨论数据对齐问题。为了CPU存取的速度最快(这同CPU取数操作有关,详细的介绍可以参考一些计算机原理方面的书),C++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐(data alignment)。这样做可能会浪费一些内存,但理论上速度快了。当然这样的设置会在读写一些别的应用程序生成的数据文件或交换数据时带来不便。MS VC++中的对齐设定,有时候sizeof得到的与实际不等。一般在VC++中加上#pragma pack(n)的设定即可.或者如果要按字节存储,而不进行数据对齐,可以在Options对话框中修改Advanced compiler页中的Data alignment为按字节对齐。
* 11.sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。如sizeof(max)若此时变量max定义为int max(),sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式

四、结束语

sizeof使用场合。

* 1.sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如:

void *malloc(size_t size),
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。

* 2.用它可以看看一类型的对象在内存中所占的单元字节。

void * memset(void * s,int c,sizeof(s))

* 3.在动态分配一对象时,可以让系统知道要分配多少内存。
* 4.便于一些类型的扩充,在windows中就有很多结构内型就有一个专用的字段是用来放该类型的字节大小。
* 5.由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。
* 6.如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。

string的实现在各库中可能有所不同,但是在同一库中相同一点是,无论你的string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。
sizeof(string)=4可能是最典型的实现之一,不过也有sizeof()为12、32字节的库实现。

String是一个对象,返回的是引用,或者说指针,当然是4(一般的)

1、sizeof()返回的是string对象所占用的空间,而不是string所存储的字符串的大小。
2、string的实现在各库中可能有所不同,但是在同一库中相同的一点是,无论string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。
3、sizeof(string)=4可能是最典型的实现之一,不过也有sizeof()为12、32字节的库实现,VC6.0测试后sizeof(string)=16,说明还是跟编译器有关。


C语言 fgets(text,sizeof(str1),stdin) stdin是什么?
stdin指的是标准输入,大多数情况下就是键盘 fgets(text,sizeof(str1),stdin) 就是从键盘输入sizeof(str1)这个长度的字符串(包括'\\0'),并保存到text这个地址空间

C语言中strlen()函数和sizof()函数分别怎么用?区别是什么
sizeof(arr)\/sizeof(a)\/sizeof(str)都是可以的,但是只能使用strlen(str),而不能strlen(arr);2、区别:2.1 sizeof()是C语言中判断数据类型或者表达式长度符;不是一个函数,字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来。2.2 strlen()求得方法是从开始到遇到第一个'\\...

请问strlen(name)和strlen(str)有什么区别啊?为什么strlen(str)等于...
你可以把字符串“name‘理解成地址变量,也就是int型,占四个字节,sizeof语句测量的是数据类型,所以sizeof(str)等于4,而strlen记录的是字符串长度,所以strlen(str)等于6。

sizeof和strlen区别
sizeof和strlen的区别是:含义不同、功能不同。1、含义不同 在定义时,要知道到strlen是一个函数,它用来计算指定字符串str的长度,但不包括结束字符(即null字符)。而sizeof是一个单目运算符,而不是一个函数,它的参数可以是数组、指针、类型、对象、函数等。这就是strlen和sizeof的最本质区别。2...

sizeof以数组名为参数
1L正确,2L错误。测试代码:include <stdio.h> int main(){ char str[] = "world", *pstr = "world";printf("%d %d",sizeof(str),sizeof(pstr));getchar();return 0;} Dev-C++下编译通过,运行结果6 4。--- 解释:char str[] = "world";这里初始化不限定长度,而"world"包含结束...

fgets(str,sizeof(str),stdin);这一句话什么意思?
从标准输入流获取最多40个字符;stdin 就是标准输入流,上面代码等同于 gets(str);

C char str[50][50]; memset(str, 0, sizeof(str[0])); memset(str...
不一样,有差别。举个简单点的例子吧:include<stdio.h>#include<string.h>void main(){ int i = 0; char str[5][5] = {"abc", "def", "ghi", "jkl", "mno"}; memset(str, 0, sizeof(str)); for(i = 0; i < 5; ++i) { printf("%s\\n", str[i]...

C语言中strlen()函数和sizof()函数分别怎么用?区别是什么
1、用法:strlen(char* pstr);\/\/求的是字符串的实际长度 sizeof(类型说明符,数组名或表达式) 或sizeof ( 变量名)比如说有以下数据类型:int arr[10] ,a; char *str="hello world"; sizeof(arr)\/sizeof(a)\/sizeof(str)都是可以的,但是只能使用strlen(str),而不能strlen(arr);2、区...

void Func ( char str[100]) { 请计算 sizeof( str ) = 4 (2分) }...
.对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通 的指针类型,即char *str

...中末尾的\\0算在长度内吗,strlen算不算,还有sizeof算不算
strlen不算,sizeof算

锡山区13969031409: c语言的size of,strlen什么意思
却骅迈爽: 函数 sizeof(T) 返回指定参数 T 所占内存的字节数,象 x 这个数组,因为初始化的是一个字符串,除了把 string 的内容写入外,还要再加一个 \0 的结束符,所以长度一共是 7 个字节,与其中所存储的内容无关.strlen(x) 返回的是字符串从第一个字符到 \0 之前的字符个数,\0 等于 0,所以 x[0]=0 相当于 x[0]='\0'.所以输出为:7 0

锡山区13969031409: sizeof strlen strcpy函数什么含义 -
却骅迈爽: sizeof是一个关键字,用来判断一个数据类型的长度.可以用于变量,也可以用于对象. 例如 char a; sizeof(char); sizeof(a);两种写法都是可以的,值都是1. 如果是对变量的话,可以省去括号,例如写成: sizeof a;也是正确的,值还是1.strlen...

锡山区13969031409: char x[]="string"; x[0]=0;x[1]='\0';x[2]='0'; printf("%d%d\n",sizeof(x),strlen(x));输出为什么是70 -
却骅迈爽: sizeof(x), 是计算x占多少内存.char x[]="string" 有6个字符外加一个看不见的字符串结束符,共7个.x[0]=0; ASCII 码 0 就是null, 就是字符串结束符.strlen(x) 返回字符串长度,长度是不计入字符串结束符的,所以得0.printf("%d%d --- 是70. sizeof(x) 返回7,strlen(x) 返回0

锡山区13969031409: 求字符串长度的问题(sizeof) -
却骅迈爽: 说白了,sizeof是求类型的大小,不管是表达式还是后面直接加类型;换种说法是在其后表达式在内存中占用的字节. p是char *类型,当然是4字节.你改为char p[] = "hello"; 这就是后面字符串的长度. 或者 用strlen函数要是规定只能用sizeof,那就这样写. int size = 0; while(*p++)size += sizeof(*p); 没什么意义,这样的代码写出来让人笑话.

锡山区13969031409: c++中的strlen,sizeof,getline函数分别是什么意思,怎么用的 -
却骅迈爽: strlen是返回一个字符串的长度,到'\0'截止. 比如a[0]='0'; a[1]='1'; a[2]='\0'; 这时strlen(a)就会返回2 即使a[3]不为'\0'也会返回2sizeof是返回这类型的数据多占的空间.一般用memset给一个数组赋初值时和读取一行字符时用. 比如memset( data, 0, sizeof( data ) ); 这个意思就是给data数组全部元素赋值为0getline是读取一行 一般这么写 cin.getline( data, sizeof( data ) );

锡山区13969031409: c语言的sizeofstrlen什么意思
却骅迈爽: \"string\"为字符串但凡字符串都邑有一个停止符\'/0\'占一个所以此时输出的x的大年夜小就是7

锡山区13969031409: C++中getlen()、strlen()、sizeof()三个函数的区别是什么? -
却骅迈爽: strlen() 这个函数是返回一个字符串中的字符个数,不包括结束符 '\0'; sizeof()这个函数是返回一个对象或类型所占的内存字节数; getlen()这个函数查了很多资料都没找到,应该是自己写的一个函数吧.下面具体说一下strlen()和sizeof...

锡山区13969031409: c语言sizeof的一个小问题 -
却骅迈爽: 宏被替换为后面的 也就是说sizeof(STRING+1)被替换为sizeof("Hello,world!"+1),严格来说这个都算语法错误,因为sizeof后面应该跟一个类型.所以默认的求得是字符串的长度,后面的会被忽略.

锡山区13969031409: sizeof()运算的是什么?返回什么? -
却骅迈爽: float可以提供6位有效数字的精确性,超过后会自动转换为有效数字15位的double,而double是要占用8字节.

锡山区13969031409: 64位系统sizeof(string)的值是40,为什么? -
却骅迈爽: 32位和64位系统的一个存储单元的存储数据的大小不同,C中32位下的string是占16个字节的,64位应该是32个字节的,出现40可能是环境问题.sizeof(int),或者其他类型的大小不知是否正常?可以发下来看看啊

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网