一. 前言
大家都知道,sizeof和strlen可以用来获取大小,但是有着不同的用法,这里首先总结区别,最后根据sizeof 和 strlen 的具体事例来分析特别需要注意的事项。
二. sizeof 和 strlen 的特点、区别
二者的区别是老生常谈的话题,也不是本文的重点。这里直接放上总结:
1.sizeofsizeof是操作符,strlen是函数。 操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。 该类型保证能容纳实现所建立的最大对象的字节大小。
2.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以’’\0’'结尾的。
sizeof还可以用函数做参数,比如:
short f();
printf("%d\n", sizeof(f())); //输出的结果是sizeof(short),即2。
3.数组做sizeof的参数不退化,传递给strlen就退化为指针了。
4.大部分编译程序 在编译的时候就把sizeof计算过了,是类型或是变量的长度。这就是sizeof(x)可以用来定义数组维数的原因。 当用于一个结构类型时或变量, sizeof 返回实际的大小, 当用于静态地空间数组, sizeof 归还全部数组的尺寸。 sizeof 操作符不能返回动态地被分派了的数组或外部的数组的尺寸
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //而b=20;
而strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度,不是类型占内存的大小。
5.sizeof后如果是类型必须加括号,如果是变量名可以不加括号。这是因为sizeof是个操作符不是个函数。
三. 特别注意事项
在使用的时候,其实把握一个原则就可以正确使用sizeof和strlen:对于数组、字符串的实际长度用strlen,而对于结构体等的实际大小用sizeof。但是,其实还有些需要注意的地方,先看看下面的测试代码:
#include <iostream>
#define PROTOCOL_STRING "BitTorrent protocol"
void test1()
{
const int string_len = sizeof(PROTOCOL_STRING) - 1;
char handshake[1 + string_len + 8 + 20 + 20];
char *ptr = handshake;
std::cout << "sizeof handshake is " << sizeof(handshake) << std::endl;
std::cout << "strlen handshake is " << strlen(handshake) << std::endl;
// length of version string
memcpy(ptr, &string_len, 1);
ptr += 1;
std::cout << "sizeof handshake is " << sizeof(handshake) << std::endl;
std::cout << "strlen handshake is " << strlen(handshake) << std::endl;
// protocol identifier
memcpy(ptr, &PROTOCOL_STRING, string_len);
ptr += string_len;
std::cout << "sizeof handshake is " << sizeof(handshake) << std::endl;
std::cout << "strlen handshake is " << strlen(handshake) << std::endl;
// 8 zeroes, reserved bits
memset(ptr, 0, 8);
ptr += 8;
std::cout << "sizeof handshake is " << sizeof(handshake) << std::endl;
std::cout << "strlen handshake is " << strlen(handshake) << std::endl;
return;
}
void test2()
{
char hello[6] = "hello";
char *msg = (char *)malloc(10);
std::cout << "sizeof(msg) = " << sizeof(msg) << " strlen(msg) = " << strlen(msg) << std::endl;
std::string str = msg;
std::cout << "str.length() = " << str.length() << std::endl;
memcpy(msg, hello, sizeof(hello));
std::cout << "sizeof(msg) = " << sizeof(msg) << " strlen(msg) = " << strlen(msg) << std::endl;
str = msg;
std::cout << "str.length() = " << str.length() << std::endl;
return;
}
void test3()
{
char msg[] = { 0, 0, 0, 0, 1, 0, 0, 0 };
std::cout << "sizeof(msg) = " << sizeof(msg) << " strlen(msg) = " << strlen(msg) << std::endl;
return;
}
int main()
{
test1();
test2();
test3();
getchar();
}
test1()展示给大家的是一个bt协议的握手报文,中间填充了8个0,导致strlen使用失败。test2()表达的是使用malloc申请的字符串空间用sizeof是无法正确识别的。test3()和test1()类似。
总结一下: