C语言填坑之sizeof与strlen的比较

一、sizeof

1、本质
单目运算符,目的是获取变量或类型占用的存储空间(单位:字节)。

2、原型
入参:类型、变量名;
出参:size_t,即unsigned int

3、原理:指针偏移
非数组:#define _sizeof(T) ((size_t)((T*)0 + 1))
数组:#define array_sizeof(T) ( (size_t)(&T+1) - (size_t)(&T) )

4、作用阶段:
编译时(内部的赋值等语句的副作用不会发生,如sizeof(i++))

5、注意事项:
(1)不能计算动态分配空间的大小;
(2)作用于数组,编译时分配的数组空间大小;作用于类型,该类型所占空间大小;作用于指针,存储该指针所用空间的大小;作用于函数,决定于函数的返回值类型大小;(仅需要区分数组与类型,指针与函数是类型的特例)
(3)sizeof 作用于结构体,基本类型相加,注意字节对齐;
(4)各类型占用的空间大小与操作系统有关;
(5)C99特性,变长数组在运行时计算数组长度

二、strlen

1、本质:标准库函数,目的是获取字符串的字符个数(不包括结束符,单位:个)。

2、原型:
头文件:string.h
原型:size_t strlen(char const* str);

3、原理:
遍历计数,以结束符为截止条件:

size_t strlen(char const* str)
{
size_t ret = 0;
while(*str++) {
    ret++;
}
    return ret;
}

4、作用阶段:运行时

5、注意事项:
(1)函数仅统计从字符串起始位置到’\0’为止的字符个数,正确计算时要求字符串有结束符,并且如果字符串中有多个结束符,仅计算到第一个结束符。
(2)仅计算字符个数,与操作系统无关;

三、sizeof数组长度计算说明

(1)计算公式:#define array_sizeof(T) ((size_t)(&T+1) - (size_t)(&T))

假设数组a[100],a和 &a结果都是数组的首地址,但其类型不一样:
a表示&a[0],即对数组首元素取地址,a+1表示首地址+sizeof(元素类型);
&a尽管值为数组首元素地址,但类型为:类型 (*)[数组元素个数],&a+1大小为:首地址+sizeof(a)。

因此,&T+1指针将会指到数组的末尾,尾地址减去首地址,得出的正是数组的大小。

验证实例:

#include<stdio.h>
#include<string.h>

#define sizeof_type(T) ((size_t)((T*)0 + 1))

int main()
{
    char str[]="hello";
    char *p = str;

    printf("str_p=%p, &str_p=%p\n", str, &str);
    printf("str_p+1=%p, &str_p+1=%p\n", str + 1, &str + 1);
    printf("str_mem=%d, p_mem=%d\n", sizeof(str), sizeof(p));

    printf("str_len=%d, p_len=%d\n", strlen(str), strlen(p));

    printf("sizeof_int=%d, my_sizeof_len=%d\n", sizeof(int), sizeof_type(int));

    printf("sizeof_type=%d\n", ((size_t)((int*)0 + 1)));

    printf("sizeof_p=%p\n", (double*)0);
    printf("sizeof_p=%p\n", (double*)0 + 1);

	return 0;
} 
posted @ 2022-10-26 14:28  Pangolin2  阅读(141)  评论(0编辑  收藏  举报