前段时间和同事讨论这个sizeof(),今天跑了一下记录下来;
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char str1[] = "Hello";
str1[2] = 'a';
printf("%s\n", str1);
char str2[100]="Hello";
char * p1 = "Hello";
const char *p2 = p1;
printf("%d, %d, %d, %d, %d\n", sizeof("Hello"), sizeof(str1), sizeof(str2), sizeof(p1), sizeof(p2)) ;
int a1[100] ={};
printf("lee a[100]:%d,strlen():%d\n",sizeof(a1),sizeof(*a1));
int a, b, c, d;
a = sizeof("123456789"); //a为10
b = sizeof("123456789"+1); //在 qt creator 和 VS 2015 结果不一致
c = strlen("123456789"); //c为9
d = strlen((const char *)("123456789"+1));
printf("%d, %d, %d, %d, %d, %d\n", a, b, c, d, sizeof(unsigned int), sizeof(int));
return 0;
}
结果:
Healo
6, 6, 100, 8, 8
lee a[100]:400,strlen():4
10, 8, 9, 8, 4, 4
解析:
1、sizeof("Hello")
的值是 6, 等价于 "hello\0"
应在内存中占 6 个字节,且 "hello"
是 char [6]
类型(由截图可知),但为什么不是 char *
或 const char *
呢?那就不知道了,反正编译器的规则 就是这么定的;
2、
sizeof(str1)
的值是 6, 等价于 sizeof(char [6])
,在内存中一共分配 1*6 个字节;下标里面的[]
中的 6 是根据赋值语句,编译器自己推算出来的;
3、sizeof(str2)
的值是 100, 等价于 sizeof(char [100])
,在内存中一共分配 1*100 个字节;
4、sizeof(p1)
的值是 4,等价于 sizeof(char *)
,等价于 sizeof(指针)
5、sizeof(p2)
的值是 4,等价于 sizeof(const char *)
,等价于 sizeof(指针)
下一组的结果运行和分析如下:
-
a
的值是 10, 等价于sizeof(char [10])
,在内存中一共分配 1*10 个字节; -
b
的值在不同系统,不同编译器上,结果是不一样的(eg: mac10.14.6 + qtCretor5.12.8 && win10 + vs2015); 结果不一直的原因是 无法判定"123456789"+1
到底应该是char [10] + int
之后,应该是什么类型?只能够根据自己的编译器实际决定;且还有一中观点: 此行是在编译时刻就已经被替换为具体的数值了,然后这一行的代码也会被删除掉,更加不会被执行,所以其 sizeof 的副作用是不会实现的(如sizeof(++i)
其实只能够等价于sizeof(对象(变量 i )的类型)
,其运行时刻在计算其值是不存在的)注意一点即可,有一个误区,以前的 类似于
int x1 = 3 + 'b'
能够顺利进行隐式转换,是因为知道最后应该转换为 等式 的左侧 的 int 类型;而我们这里系统没有 左值,故无法知道转换为什么类型,所以出现如下截图,此上下文不支持; -
c
的值是 9,没有什么好讲的,该函数的实现,是遇到第一个'\0'
就停止; -
d
的值是 8 ?(两个不同环境都是 8,有点费解),这个不明所以;查看源码 strlen() 的实现如下size_t strlen(const char *__s);
,按照我的理解,应该是等价于d = strlen((const char *)("123456789"+1))
的,显示结果依旧为 8;这个结果为啥是 8, 有点费解,不过觉得没有探究的必要,也不是本文谈论的重点;此行多探究无意义,且这样写,有点 “无中生有”,“惹是生非”,“搞事情” 的感觉 -
sizeof(unsigned int)
的值是 4,不用解释 -
sizeof(int)
的值是 4,不用解释
思考:
sizeof()
是 返回一个类型的在内存中说占的字节数。 是属于 运算符 , 同为 运算符 的还有 +
、-
、*
、/
、%
等。而这个是在编译时候就被执行,而非运行时候执行,一开始就已经是计算机被知道的。
C 标准和实际上的 编译器 一开始就定义好了,在 32 位电脑中,int
占据 4 字节, char
占据 1 字节;
对于内置的基本数据类型 来说,下面是很容易理解,觉得一开始就被编译机在内存里面分配了这么多的变量:
sizeof(int) --> 显示 4 字节
sizeof(char) --> 显示 1 字节
而 对于 复合数据类型 来求字节大小,其是需要根据 组合的基本数据类型 来给出实际的内存中所占的字节大小,比如自定义 类:
sizeof(自定类) --> 显示 字节对齐后的 字节
sizeof(数组) --> 显示 符合类型的数组 字节
sizeof(int [4]) --> 显示 4 * 4 字节 // 这样就容易理解了
所以就有了lee a[100]:400,strlen():4。