, sz);
C99标准规定,函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的:
sizeof(foo); //error
void foo2(){}
sizeof(foo2()); //error
struct S {
unsigned int f1:1;
unsigned int f2:5;
unsigned int f3:12;
sizeof(S.f1); //error
sizeof的常量性
sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用,如:
char ary[sizeof(int) * 10]; //ok
而C99标准规定sizeof也可以在运行时刻进行计算,如下面的程序在Dev-C++中可以正确执行:
int n;
n = 10; //n动态赋值
char ary[n]; //C99也支持数组的动态定义
printf("%d\n", sizeof(ary)); //ok.输出10
但在没有完全实现C99标准的编译器中就行不通了,上面的代码在VC6中就通不过编译。
所以我们最好还是认为sizeof是在编译期执行的,这样不会带来错误,让程序的可移植性强些。
sizeof之指针变量 vs. 数组变量
sizeof()的变量如果是指针char *,则返回指针本身的大小;如果是数组char [],返回的是数组空间的大小。
在32位计算机中,一个指针变量的返回值通常是4(以字节为单位),在64位系统中指针变量的sizeof通常为8。
char *pc = "abc";
int *pi;
string *ps;
char **ppc = &pc;
void(*pf)(); //函数指针
sizeof(pc); //结果为4
sizeof(pi); //结果为4
sizeof(ps); //结果为4
sizeof(ppc); //结果为4
sizeof(pf); //结果为4
指针变量的sizeof值与指针所指的对象没有任何关系,所有的指针变量所占内存大小相等。
数组的sizeof值等于数组所占用的内存字节数,如:
char a1[] = "abc";
int a2[3];
sizeof(a1); // 结果为4,字符末尾还存在一个'\0'结束符
sizeof(a2); // 结果为3 * 4 = 12(依赖于int的大小)
求数组长度(个数)
int c1 = sizeof(a1) / sizeof(char); //总长度/单个元素的长度 char型
int c2 = sizeof(a2) / sizeof(a2[0]); //总长度/第一个元素的长度 int型
函数形参列表里的数组本质是指针!!!
注意:在C++里,参数传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小。如果想在函数内知道数组的大小, 必须增加一个形参,将长度传进去。
void foo3(char a3[3]) {
int c3=sizeof(a3); //c3 = ?
void foo4(char a4[]) {
int c4=sizeof(a4); //c4 = ?
这里函数参数a3已不再是数组类型,而是蜕变成指针,相当于char* a3。试想:当我们调用函数foo3时,程序会在栈上分配一个大小为3的数组吗?不会!数组是“传址”的,调用者只需将实参的地址传递过去,所以a3自然为指针类型char*,c3的值也就为4。
结构体的sizeof
待补充。。。
从栈看sizeof
其实理解 sizeof 只需要抓住一个要点:栈。
程序存储分布有三个区域:栈、静态和动态。能够从代码直接操作的对象,包括任何类型的变量、指针,都是在栈上的;动态和静态存储区是靠栈上的所有指针间接操作的。
sizeof 操作符,计算的是对象在栈上的投影体积,记住这点很多东西都很清楚了。
char const *static_string = "Hello";
//sizeof(static_string)是sizeof一个指针,所以在32bit system是4
char stack_string[] = "Hello";
//sizeof(stack_string)是sizeof一个数组,所以是6*sizeof(char)
char*string = new char[6];
strncpy(string,"Hello",6");
//sizeof(string)是sizeof一个指针,所以还是4。
//和第一个不同的是,这个指针指向了动态存储区而不是静态存储区。
不管指针指向的内容在什么地方,sizeof 得到的都是指针的栈大小。
sizof与引用
C++ 中对引用的处理比较特殊。sizeof一个引用得到的结果是sizeof一个被引用的对象的大小。
struct test {
int a, b, c, d, e, f, g, h;
int main() {
test &r = new test;
cout << sizeof(test) << endl; //32
cout << sizeof r << endl; //也是32
system("PAUSE");
strlen()
返回的是一个字符串的实际长度(字符个数),即从字符串首地址开始,直到遇到第一个'\0'(字符串结束符)为止的这一段长度(不包括'\0')。
注意数组的初始化问题!!!
char aa[10];
cout << strlen(aa) << endl; //结果是不定的,因为未初始化,'\0'在内存中的位置不确定
char aa[10] = {'\0'};
cout << strlen(aa) << endl; //结果为0
char aa[10] = "jun";
cout<<strlen(aa)<<endl; //结果为3
sizeof vs. strlen()
(1)sizeof本质是运算符,strlen是函数。
sizeof可以用类型做参数,strlen只能用char *做参数,且必须是以'\0'结尾的。
sizeof还可以用函数做参数,比如:
short f();
printf("%d\n", sizeof(f()));
// 输出的结果是sizeof(short),即2。
(2)数组做sizeof的参数不退化,传递给strlen就退化为指针了。
char Array[3] = {'0'};
sizeof(Array); // 3
char *p = Array;
strlen(p) == 1; // sizeof(p)结果为4
(3)大部分编译程序在编译的时候就把sizeof计算过了,是类型或是变量的长度,这就是sizeof(x)可以用来定义数组维数的原因。而strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度的,不是类型占内存的大小。
(4)sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧。这是因为sizeof是个操作符,不是个函数。
(5)当适用于一个结构体类型或变量时, sizeof返回实际大小;当适用于静态的空间数组时, sizeof返回全部数组的尺寸(占用内存)。
(6)sizeof操作符不能返回动态分配的数组或外部的数组尺寸。
//sizeof与strlen的区别
char *sz = "abcde";
char sz1[20] = "abcde";
cout << sizeof(sz) << endl;
cout << strlen(sz) << endl;
cout << sizeof(sz1) << endl;
cout << strlen(sz1) << endl;
/*输出:
memset与memcpy函数中的使用
关于memset与memcpy函数更详细的信息请见memset,memcpy与strcpy一文。
参数中使用strlen(str)和sizeof(str)有什么区别?
sizeof(str)返回str这个指针变量所占的内存字节数目;
strlen(str) 返回str所指向的字符串的长度。
用sizeof的话,只给str所指向的内存块连续4个字节清0;
用strlen的话,是给str所指向的字符串全部清0;
sizeof()应该是编译时处理的,而strlen是函数,两者本质不同,使用时注意定义。
char * fun(char *str) {
memset(str, 0, sizeof(str));
//sizeof(str))求得是指针str的大小,指针占空间是一样的4个字节;
//str指向的是数组的首地址,这样相当于将数组前四个元素至为‘\0’,
//用printf("%s")的话,遇到第一个'\0',即退出。
//如果用memset(str, 0, strlen(str));就得看运气了。
//str指向数组b[400]首地址,b[400]没有显示初始化,
//strlen是遇到'\0'退出,有可能b[0]就是'\0',
//strlen(str)的结果就为0,用printf("%s")就打印不出来了;
//strlen(str)也有可能是其他值,得看'\0'在b[400]的哪个位置了
return str;
int main(int argc, char* argv[]) {
char *a, b[400];
a = fun(b);
strlen---------测“字符个数”(包括:不可见字符,如:空格等)
sizeof---------测“BYTE个数”
(整理自网络)
参考资料:
https://baike.baidu.com/item/sizeof/6349467
Min是清明的茗