目录
1.5 sizeof可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用
2.2 ‘sizeof’ on array function parameter ‘str’ will return size of ‘char*’
0.阅读引用
1.sizeof
1.1 sizeof是运算符
sizeof的操作数可以是数据类型、函数、变量.
1.2 数据类型
例如我们要计算一个int型数据的存储空间可以用:sizeof(int),需要注意的是sizeof的操作数是数据类型
时要加括号,其数值大小为该数据类型所占的存储空间的字节数.
1.3 变量
sizeof(变量名)
如果定义 int a ,可以使用sizeof(a)计算a变量占据的存储空间,具体大小与a的类型有关.
注意:由于sizeof是操作符sizeof a(注意:sizeof和a之间有一个空格)或sizeof(a)都可以,可以不使用括
号),如果操作数是数组名则给出数组所占用内存的字节数. 如果数组名做函数的参数传递时退化为指针.
1.4 表达式
sizeof(表达式)
sizeof可以对一个表达式求值,编译器根据表达式的最终结果类型来确定大小,一般不会对表达式进行计
算.例如:sizeof(1+1.5).
#include <stdio.h>
int main(){
int a;
printf("sizeof a is %d .\n",sizeof a);
printf("sizeof(1+1.5) is %d\n",sizeof(1+1.5)); // 64位上是8
}
1.5 sizeof可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用
#include <stdio.h>
int myprint()
{
printf("hello world\n");
return 0;
}
int main()
{
printf("sizeof(myprint())is %d \n",sizeof(myprint()));
printf("sizeof(myprint)is %d \n",sizeof(myprint));
return 0;
}
结果只打印函数返回类型的sizeof值,并没有打印hello world说明函数myprint并没有调用.
C99标准规定,函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的,
如:
(1)sizeof(myprint)---这个现在好像是可以的了.
(2)sizeof一个void返回类型的函数如:
void foo () { }
sizeof(foo());---这个现在好像也是可以的了.
(3)位域,这个还是不能通过的;
struct S
{
unsigned int f1:1;
unsigned int f2:5;
unsigned int f3:12;
};
sizeof( S.f1 );
测试代码:
#include <stdio.h>
struct S
{
unsigned int f1:1;
unsigned int f2:5;
unsigned int f3:12;
};
int myprint()
{
printf("hello world\n");
return 0;
}
void foo(){}
int main()
{
printf("sizeof(myprint())is %d \n",sizeof(myprint()));
printf("sizeof(foo())is %d \n",sizeof(foo()));
printf("sizeof(myprint)is %d \n",sizeof(myprint));
//printf("sizeof(S.f1)is %d \n",sizeof(S.f1));
return 0;
}
注意:
我这里有些C99禁止的规则可以在我的gcc编译器下编译通过且可以执行,为了保证移植可靠性,我们
要注意各个编译器和平台下的移植性,这里还需要多多测试.
2.strlen
2.1 strlen测量的是字符的实际长度,不包含'\0'
strlen的结果运行的时候才出来(不是编译期求值),是计算字符串长度的,其参数必须是字符型指针
(char*),头文件为#include<string.h>.
strlen 测量的是字符的实际长度,以'\0' 结束( 不包含'\0' ). 而sizeof 测量的是字符的分配大小,
如果未分配大小,则遇到'\0' 结束(包含'\0' ,也就是strlen测量的长度加1),如果已经分配内存大
小,返回的就是分配的内存大小.
测试代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main(){
char str[] = "Hello World";
char str1[100] = "Hello World";
const char *str2 = "Hello World";
cout << strlen(str) << endl; // 11
cout << strlen(str1) << endl; // 11
cout << strlen(str2) << endl; // 11
cout << sizeof(str) << endl; // 12
cout << sizeof(str1) << endl; // 100
cout << sizeof(str2) << endl; // 32位的机器上是4,64位的机器上是8
return 0;
}
2.2 ‘sizeof’ on array function parameter ‘str’ will return size of ‘char*’
/*
在子函数中,sizeof会把从主函数中传进来的字符数组当作是指针来处理,指针的大小由机器来决定.
这种情况下在编译的时候会有警告,编程的时候要注意这一点,不要犯错.
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
void RightUpperCase( char str[] )
{
cout << "strlen(str) is " << strlen(str) << endl;
for( size_t i=0; i<strlen(str); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
void WrongUpperCase( char str[] )
{
cout << "被调用函数中sizeof(str)/sizeof(str[0]) is " << sizeof(str)/sizeof(str[0]) << endl;/*这句话编译的时候会有警告*/
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
int main(){
char str[] = "aBcDeyyyyyyy";
char str1[] = "aBcDeyyyyyyy";
cout << "调用函数中sizeof(str)/sizeof(str[0]) " << sizeof(str)/sizeof(str[0]) << endl;
RightUpperCase( str );
cout << str << endl;
WrongUpperCase( str1 );
cout << str1 << endl;
}
2.3 字符数组的初始化注意点
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = "hello";// 不定长的时候编译器会自动优化长度
char str2[] = {'h', 'e', 'l', 'l', 'o', '\0'};// OK
char str3[5] = {'h', 'e', 'l', 'l', 'o'}; // NOT OK,打印出的字符串与上下文有关,要注意用'\0'来标志字符串的结束,这里会产生内存溢出,如果这里写str3[6]暂时没有发现问题,但是是不严谨的,
char str4[6] = "hello\0"; // OK,初始化字定长符数组的情况下要将'\0'考虑进去
printf("str1:%s\n",str1);
printf("str2:%s\n",str2);
printf("str3:%s\n",str3);
printf("str4:%s\n",str4);
printf("sizeof(str1):%d\n", sizeof(str1));
printf("sizeof(str2):%d\n", sizeof(str2));
printf("sizeof(str3):%d\n", sizeof(str3));
printf("sizeof(str4):%d\n", sizeof(str4));
printf("strlen(str1):%d\n", strlen(str1));
printf("strlen(str2):%d\n", strlen(str2));
printf("strlen(str3):%d\n", strlen(str3));
printf("sizeof(str4):%d\n", strlen(str4));
return 0;
}
/*
运行结果如下图:
我们知道字符串是以 '\0' 为结束标志的,所以char str1[ ] = "hello" 等效于char str2[ ] =
{'h' , 'e' , 'l' , 'l' , 'o' , '\0'} 。strlen函数求的是字符串的实际长度,它求得方法是从
开始到遇到第一个'\0',如果你只定义没有给它赋初值,这个结果是不定的,它会从首地址一直找下
去,直到遇到'\0'停止。而如果不在字符数组初始化的时候加上\0,那么strlen 得到的值就不是正确
的数值,打印出来的结果也不是想要的结果。因此我们要避免这种情况,在初始化的时候要记得加上
\0,或者一次性赋初值。
*/
3.sizeof与strlen的比较
(1)strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小,
而大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度.
(2)sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以'\0'结尾的.