原来 sizeof
是一个特殊的,运算优先级很高的一种运算符?之前一直都不知道。
参考博客:
优先级
作为一个运算符,sizeof
自然也是有优先级的,它在 C++ 中优先级为 \(3\),也就是除了作用域解析运算符和诸如括号的操作符,它优先级基本上是最高的,和一般的运算符不同,它的运算是从右向左进行结合的。
运算逻辑
看一下 sizeof
在 msdn 上的定义:
The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types). This keyword returns a value of type size_t.
其作用就是返回一个对象或者类型所占的内存字节数,注意,sizeof
返回值是 unsigned long long int
。
然而一定记住 sizeof
不是一个函数,可以不加括号,比起操作运算符更像是一个特殊的宏,在编译阶段进行求值,为什么这么说?看下文吧。
运算
函数
我们都不知道,sizeof
其实是可以对一个函数调用求值的。其结果是函数返回值类型的大小,函数并不会被调用。
对函数求值的形式:`sizeof(函数名(实参表))``
注意:
1)不可以对返回值类型为空的函数求值。
2)不可以对函数名求值。
3)对有参数的函数,在用 sizeof
时,须写上实参表。
exp.
#include<bits/stdc++.h>
using namespace std;
unsigned long long int zyx(){
return 0;
}
int cnt;
void sbzyx(){
return;
}
int nbest(){
cnt++;
return 1;
}
int main(){
printf("%lld\n",sizeof zyx());
//输出 8,等价于 sizeof unsigned long long int
//printf("%lld\n",sizeof sbzyx()); 我这里好像不会报错,输出了个 1,但是会 warning
//printf("%lld\n",sizeof zyx);报错
printf("%lld\n",sizeof nbest());
//输出 4,等价于 sizeof int
printf("%d\n",cnt);
//输出 0,证明并没有调用函数
return 0;
}
基本类型
直接返回类型所占字节,输出对应类型的变量的 sizeof
也一样。
结构体
我也不知道结构体会有字节对齐的问题。
可供参考博客:C/C++ struct字节对齐那些事儿
具体原因上网查吧,我这里展示个代码你们就懂了。
#include<bits/stdc++.h>
using namespace std;
struct node{
int p;
long long k;
bool w;
};
struct node1{
int p[53];
long long k;
bool w;
};
struct node2{
int p[54];
long long k;
bool w;
};
struct zyx{
int p;
};
struct nb{
};
int main(){
printf("%lld %lld %lld\n",sizeof(zyx),sizeof(node),sizeof(nb));
//第一个不出意料的输出 4
//第二个输出24
//第三个输出 1
printf("%lld %lld",sizeof(node1),sizeof(node2));
//没想到吧,两个都是输出 232,因为两个 int 直接对齐了,但是最后单独的一个 int 为了和 long long 对齐,也会被改成 8。
return 0;
}
有趣的小知识:
C/C++不允许对struct成员进行重排序,即成员的内存排列顺序一定是定义顺序。
所以这会导致一个问题:
#include<bits/stdc++.h>
using namespace std;
struct node1{
int a;
bool b;
long long c;
};
struct node2{
int a;
long long c;
bool b;
};
int main(){
cout<<sizeof(node1)<<endl;
//输出16,因为int 和 bool 合并之后再对齐
cout<<sizeof(node2);
//输出24,int 和bool 分别对齐
return 0;
}
看似相同的代码内存占用却不一样(当然数据大的话其实看不出来)。
联合体union
结构体在内存组织上是顺序式的,联合体则是重叠式,各成员共享一段内存。所以整个联合体的 sizeof
也就是每个成员 sizeof
的最大值。
#include<bits/stdc++.h>
using namespace std;
union poper{
int k;
long long p;
bool x;
int w[6];
char ppp[8];
};
union po{
int k;
long long p;
bool x;
//int w[6];
//char ppp[8];
};
int main(){
printf("%lld %lld",sizeof(poper),sizeof(po));
//第一个最长的是 w[6] 为 4*6=24,输出24
//第二个最长的是 long long ,输出8
return 0;
}
数组
数组的 sizeof
值等于数组所占用的内存字节数。
- 当字符数组表示字符串时,其
sizeof
值将/0
计算进去。 - 当数组为形参时,其sizeof值相当于指针的sizeof值。
#include<bits/stdc++.h>
using namespace std;
int poper[82];
char po[18];
char zyx[]="sbzyx";
void yqt(char a[]){
cout<<sizeof(a)<<endl;
}
void yqtsb(char a[18]){
cout<<sizeof(a)<<endl;
}
int main(){
printf("%lld %lld %lld\n",sizeof(poper),sizeof(po),sizeof(zyx));
//输出 328 18 6
yqt(po);
//输出 8,即指针大小
yqtsb(po);
//输出 8,同上
return 0;
}
指针
指针是用来记录另一个对象的地址,所以指针的内存大小当然就等于计算机内部地址总线的宽度。
指针变量的 sizeof
值与指针所指的对象没有任何关系,同一台计算机输出的结果一定一样。
动态空间
比如 string,vector 等动态空间,对它们用 sizeof
的返回值通常是固定的,与长度无关。但是这并不意味着它们的空间就是这么大。
#include<bits/stdc++.h>
using namespace std;
string a="abcadfasfsddxgsdfgf";
basic_string<int>poww;
basic_string<pair<int,int> >fc;
basic_string<char>fwc="1";
vector<pair<int,int> >f(1965);
pair<int,long long> w;
int main(){
printf("%lld %lld %lld\n",sizeof a,sizeof f,sizeof w);
//32 24 16
printf("%lld %lld %lld %lld\n",sizeof(fc),sizeof(fwc),sizeof(poww),sizeof(string));
//32 32 32 32
return 0;
}
奇怪的运算符
所以我们可以回答上面的问题了,为什么说 sizeof
很奇怪呢?正常的运算符都是会运行内部的运算的,但是 sizeof
不会(不会运算函数,不会运行赋值操作等)。
#include<bits/stdc++.h>
using namespace std;
int a;
int main(){
cout<<sizeof(a=3)<<endl;
//4
cout<<a<<endl;
//0
cout<<sizeof(++a)<<endl;
//4
cout<<a<<endl;
//0
return 0;
}
小结
为了初赛,算是搞懂了这个奇怪的东西,去研究 union
了~