如何计算对象或者类型所占的内存字节数(各种总结)

本文深入讲解C/C++中sizeof运算符的用法及其在不同场景下的应用,包括基本数据类型、指针、数组及结构体等,并分析了结构体内部成员的对齐规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结一下将sizeof用于各种类型对象或类型时其结果的算法。

1、认识sizeof

sizeof是C/C++中的一个operator,其作用就是返回一个对象或者类型所占的内存字节数(byte)。返回值是size_t,在头文件stddef.h中定义。

2、用法

sizeof的用法有一下3种:

(1)sizeof(object);//即sizeof(对象)

(2)sizeof(type_name);//即sizeof(类型名,如int,char...etc)

(3)sizeof object;//即sizeof 对象

例如:

  1. int i;  
  2. sizeof(i);  
  3. sizeof(int);  
  4. sizeof i;  
  5. sizeof int//error!!!  
int i;
sizeof(i);
sizeof(int);
sizeof i;
sizeof int; //error!!!

【注】:

(1)实际上sizeof计算对象的大小也是转换成对象类型来计算的,that is to say:对同类型的不同对象使用sizeof操作,得到的值是一样的。

(2)关于上面第(1)个表达式中的object,其可以延伸至一个unary-expression(一元表达式),例如:

  1. sizeof(2); //相当于sizeof(int)  
  2. sizeof(2+4.55); //相当于sizeof(2.0+4.55),从而相当于sizeof(double)  
sizeof(2); //相当于sizeof(int)
sizeof(2+4.55); //相当于sizeof(2.0+4.55),从而相当于sizeof(double)

(3)sizeof可以对函数调用求值,就相当于对该函数的返回值类型求sizeof。

  1. char foo()  
  2. {  
  3.     cout<<"foo函数被调用!"<<endl;  
  4.     return 'a';  
  5. }//函数   
  6. int foo_size;  
  7. foo_size=sizeof(foo());//相当于求sizeof(char)  
char foo()
{
	cout<<"foo函数被调用!"<<endl;
	return 'a';
}//函数
int foo_size;
foo_size=sizeof(foo());//相当于求sizeof(char)

(4)sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用。

例如:

  1. char ary[ sizeofint ) * 10 ];  //ok~~~  
char ary[ sizeof( int ) * 10 ];  //ok~~~

3、各种sizeof计算

(1)基本数据类型的sizeof(C++primer中叫内置类型),如:int,char,double,float,short,long

在32位计算机中,各种内置类型所占的字节数如下:

char-------------1bytes;

short------------2bytes;

int----------------4bytes;

long--------------4bytes;

float--------------4bytes;

double-----------8bytes;

long double----8bytes;

(2)指针数据类型的sizeof

指针记录了另一个对象的地址,即指针变量是用来存放地址数据的,那么其当然等于计算机地址总线的宽度了。所以在32位计算机中,无论指针p指向何种类型的数据对象,其sizeof结果肯定为4bytes。

  1. char *pc="abcd";  
  2. int *pi;  
  3. string *ps;  
  4. char **ppc=&pc;  
  5. void (*ppf)();//函数指针  
  6. cout<<"sizeof(pc)="<<sizeof(pc)<<endl;  
  7. cout<<"sizeof(pi)="<<sizeof(pi)<<endl;  
  8. cout<<"sizeof(ps)="<<sizeof(ps)<<endl;  
  9. cout<<"sizeof(ppc)="<<sizeof(ppc)<<endl;  
  10. cout<<"sizeof(ppf)="<<sizeof(ppf)<<endl;//这5个结果均为4bytes  
char *pc="abcd";
int *pi;
string *ps;
char **ppc=&pc;
void (*ppf)();//函数指针
cout<<"sizeof(pc)="<<sizeof(pc)<<endl;
cout<<"sizeof(pi)="<<sizeof(pi)<<endl;
cout<<"sizeof(ps)="<<sizeof(ps)<<endl;
cout<<"sizeof(ppc)="<<sizeof(ppc)<<endl;
cout<<"sizeof(ppf)="<<sizeof(ppf)<<endl;//这5个结果均为4bytes

(3)数组类型的sizeof

数组的sizeof值等于数组所占用的内存字节数。

【切记】:有人以为sizeof(数组名)是求数组中元素的个数,这种认识是严重错误的。
例如:

  1. char a1[]="abcd";  
  2. int a2[3];  
  3. sizeof(a1)=5*1=5bytes;//一个char类型占1byte  
  4. sizeof(a2)=3*4=12bytes;  
char a1[]="abcd";
int a2[3];
sizeof(a1)=5*1=5bytes;//一个char类型占1byte
sizeof(a2)=3*4=12bytes;

【注】:

(1)求数组元素的两种方法

  1. int counts_a1=sizeof(a1)/sizeof(char);  
  2. int counts_a1=sizeof(a1)/sizeof(a1[0]);  
int counts_a1=sizeof(a1)/sizeof(char);
int counts_a1=sizeof(a1)/sizeof(a1[0]);

(2)当数组名被用作函数参数传递时,此时的数组名变蜕化成一个相应类型的指针了

  1. void foo3(char a3[3])   
  2. {     
  3. int c3 = sizeof( a3 ); // c3 =3  这里c3=sizeof(a3),想当于c3=sizeof(char*),故c3=4!!!   
  4. }  
  5.   
  6. void foo4(char a4[])  
  7. {     
  8. int c4 = sizeof( a4 ); // 同上,c4 =4!!!    
  9. }  
void foo3(char a3[3]) 
{   
int c3 = sizeof( a3 ); // c3 =3  这里c3=sizeof(a3),想当于c3=sizeof(char*),故c3=4!!! 
}

void foo4(char a4[])
{   
int c4 = sizeof( a4 ); // 同上,c4 =4!!!  
}

(4)结构体的sizeof

结构体在内存中时如何实际存储的呢?

结构体的大小不是所有成员大小的简单的相加,还需要考虑一个很重要的问题---------系统在存储结构体变量时存在一个“边界对齐”的问题。其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理。在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。编译器会按照成员列表的顺序一个接一个地给每个成员分配内存的,字节对齐的细节遵循以下3个原则:

1)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal padding);

2)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding);

下面用例子来说明VC是怎样存放结构体的。例如:

Eg1:

  1. //结构体1   
  2. struct Mystruct1  
  3. {  
  4. double data_db;  
  5. char data_ch;  
  6. int data_i;  
  7. };  
//结构体1
struct Mystruct1
{
double data_db;
char data_ch;
int data_i;
};

分析:

为上面的结构体分配内存的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员data_db分配内存,其起始地址跟结构的起始地址相同(即data_db的偏移量为0,刚好为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员data_ch分配内存,这时下一个可以分配的地址相对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把data_ch存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;接下来为第三个成员type分配空间,这时下一个可以分配的地址相对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址相对于结构的起始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。所以整个结构的大小为:sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。

Eg2:

  1. //结构体2   
  2. struct Mystruct2  
  3. {  
  4. char data_ch;  
  5. double data_db;  
  6. int data_i;  
  7. };  
//结构体2
struct Mystruct2
{
char data_ch;
double data_db;
int data_i;
};

分析:

为上面的结构体分配内存的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员data_ch分配内存,其起始地址跟结构的起始地址相同(即data_ch的偏移量为0,刚好为sizeof(char)的倍数),该成员变量占用sizeof(char)=1个字节;接下来为第二个成员data_db分配内存,这时下一个可以分配的地址相对于结构的起始地址的偏移量为1,不是sizeof(double)=8的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充7个字节(这7个字节没有放什么东西),这是下一个可以分配的地址相对于结构的起始地址的偏移量变为8,是sizeof(double)=8的倍数了,所以把data_db存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(double)=8个字节。接下来为第三个成员data_i分配空间,这时下一个可以分配的地址相对于结构的起始地址的偏移量为16,是sizeof(int)=4的倍数,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:1+7+8+4=20,不是结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以还得在第三个成员变量data_i的后面填充4个字节,使其达到24个字节,成为字节边界数的倍数。所以整个结构的大小为:sizeof(MyStruct)=1+7+8+4+4=24,其中有7+4个字节是VC自动填充的,没有放任何有意义的东西。

Eg3:

  1. #include <iostream>   
  2. using namespace std;  
  3.   
  4. char foo()  
  5. {  
  6.     cout<<"foo函数被调用!"<<endl;  
  7.     return 'a';  
  8. }  
  9.   
  10. int main()  
  11. {  
  12.     //内置数据类型   
  13.     int a=5;  
  14.     char b='c';  
  15.     cout<<"内置数据类型:"<<endl;  
  16.     cout<<sizeof(int)<<endl;  
  17.     cout<<sizeof(a)<<endl;  
  18.     cout<<sizeof(char)<<endl;  
  19.     cout<<sizeof(b)<<endl;  
  20.   
  21.     //对指针求其大小   
  22.     cout<<"指针数据类型:"<<endl;  
  23.     char *pc="abcd";  
  24.     int *pi;  
  25.     string *ps;  
  26.     char **ppc=&pc;  
  27.     void (*ppf)();//函数指针  
  28.     cout<<"sizeof(pc)="<<sizeof(pc)<<endl;  
  29.     cout<<"sizeof(pi)="<<sizeof(pi)<<endl;  
  30.     cout<<"sizeof(ps)="<<sizeof(ps)<<endl;  
  31.     cout<<"sizeof(ppc)="<<sizeof(ppc)<<endl;  
  32.     cout<<"sizeof(ppf)="<<sizeof(ppf)<<endl;  
  33.   
  34.   
  35.     //对函数调用求值   
  36.     cout<<"函数调用:"<<endl;  
  37.     int foo_size;  
  38.     foo_size=sizeof(foo());  
  39.     cout<<"sizeof(foo())="<<foo_size<<endl;//函数foo()并不会被调用,sizeof对一个函数调用求值,就相当于对该函数的返回类型求sizeof, 即sizeof(char)  
  40.   
  41.   
  42.     //对结构体求值   
  43.     cout<<"对结构体类型:"<<endl;  
  44.     struct ALIGN1  
  45.     {  
  46.         char a;  
  47.         int b;  
  48.         char c;  
  49.     };  
  50.       
  51.   
  52.     //调整ALIGN1中成员列表   
  53.     struct ALIGN3  
  54.     {  
  55.         int b;  
  56.         char a;  
  57.         char c;  
  58.     };  
  59.   
  60.     struct ALIGN2  
  61.     {  
  62.         double a;  
  63.         char b;  
  64.         int c;  
  65.     };  
  66.   
  67.     //再举一个例子   
  68.     //结构体1   
  69.     struct Mystruct1  
  70.     {  
  71.         double data_db;  
  72.         char data_ch;  
  73.         int data_i;  
  74.   
  75.     };  
  76.     //结构体2   
  77.     struct Mystruct2  
  78.     {  
  79.         char data_ch;  
  80.         double data_db;  
  81.         int data_i;  
  82.     };  
  83.   
  84.   
  85.   
  86.     cout<<"struct1的大小:"<<endl;  
  87.     cout<<sizeof(ALIGN1)<<endl;  
  88.     cout<<"a的偏移量:"<<offsetof(ALIGN1,a)<<endl;  
  89.     cout<<"b的偏移量:"<<offsetof(ALIGN1,b)<<endl;  
  90.     cout<<"c的偏移量:"<<offsetof(ALIGN1,c)<<endl;  
  91.   
  92.     cout<<"struct2的大小:"<<endl;  
  93.     cout<<sizeof(ALIGN2)<<endl;  
  94.   
  95.   
  96.     cout<<"struct3的大小:"<<endl;  
  97.     cout<<sizeof(ALIGN3)<<endl;  
  98.     cout<<"a的偏移量:"<<offsetof(ALIGN3,a)<<endl;  
  99.     cout<<"b的偏移量:"<<offsetof(ALIGN3,b)<<endl;  
  100.     cout<<"c的偏移量:"<<offsetof(ALIGN3,c)<<endl;  
  101.   
  102.     //输出Mystruct1和Mystruct2的大小   
  103.     cout<<"sizeof(Mystruct1)="<<sizeof(Mystruct1)<<endl;  
  104.     cout<<"sizeof(Mystruct2)="<<sizeof(Mystruct2)<<endl;  
  105.   
  106.     //查看Mystruct1和Mystruct2中变量的(相对于结构体的起始地址)偏移量  
  107.     cout<<"Mystruct1_data_db的偏移量="<<offsetof(Mystruct1,data_db)<<endl;  
  108.     cout<<"Mystruct1_data_ch的偏移量="<<offsetof(Mystruct1,data_ch)<<endl;  
  109.     cout<<"Mystruct1_data_i的偏移量="<<offsetof(Mystruct1,data_i)<<endl;  
  110.   
  111.     cout<<"Mystruct2_data_db的偏移量="<<offsetof(Mystruct2,data_db)<<endl;  
  112.     cout<<"Mystruct2_data_ch的偏移量="<<offsetof(Mystruct2,data_ch)<<endl;  
  113.     cout<<"Mystruct2_data_i的偏移量="<<offsetof(Mystruct2,data_i)<<endl;  
  114.   
  115.   
  116.   
  117.     return 0;  
  118. }  
#include <iostream>
using namespace std;

char foo()
{
	cout<<"foo函数被调用!"<<endl;
	return 'a';
}

int main()
{
	//内置数据类型
	int a=5;
	char b='c';
	cout<<"内置数据类型:"<<endl;
	cout<<sizeof(int)<<endl;
	cout<<sizeof(a)<<endl;
	cout<<sizeof(char)<<endl;
	cout<<sizeof(b)<<endl;

	//对指针求其大小
	cout<<"指针数据类型:"<<endl;
	char *pc="abcd";
	int *pi;
	string *ps;
	char **ppc=&pc;
	void (*ppf)();//函数指针
	cout<<"sizeof(pc)="<<sizeof(pc)<<endl;
	cout<<"sizeof(pi)="<<sizeof(pi)<<endl;
	cout<<"sizeof(ps)="<<sizeof(ps)<<endl;
	cout<<"sizeof(ppc)="<<sizeof(ppc)<<endl;
	cout<<"sizeof(ppf)="<<sizeof(ppf)<<endl;


	//对函数调用求值
	cout<<"函数调用:"<<endl;
	int foo_size;
	foo_size=sizeof(foo());
	cout<<"sizeof(foo())="<<foo_size<<endl;//函数foo()并不会被调用,sizeof对一个函数调用求值,就相当于对该函数的返回类型求sizeof, 即sizeof(char)


	//对结构体求值
	cout<<"对结构体类型:"<<endl;
	struct ALIGN1
	{
		char a;
		int b;
		char c;
	};
	

	//调整ALIGN1中成员列表
	struct ALIGN3
	{
		int b;
		char a;
		char c;
	};

	struct ALIGN2
	{
		double a;
		char b;
		int c;
	};

	//再举一个例子
	//结构体1
	struct Mystruct1
	{
		double data_db;
		char data_ch;
		int data_i;

	};
	//结构体2
	struct Mystruct2
	{
		char data_ch;
		double data_db;
		int data_i;
	};



	cout<<"struct1的大小:"<<endl;
	cout<<sizeof(ALIGN1)<<endl;
	cout<<"a的偏移量:"<<offsetof(ALIGN1,a)<<endl;
	cout<<"b的偏移量:"<<offsetof(ALIGN1,b)<<endl;
	cout<<"c的偏移量:"<<offsetof(ALIGN1,c)<<endl;

	cout<<"struct2的大小:"<<endl;
	cout<<sizeof(ALIGN2)<<endl;


	cout<<"struct3的大小:"<<endl;
	cout<<sizeof(ALIGN3)<<endl;
	cout<<"a的偏移量:"<<offsetof(ALIGN3,a)<<endl;
	cout<<"b的偏移量:"<<offsetof(ALIGN3,b)<<endl;
	cout<<"c的偏移量:"<<offsetof(ALIGN3,c)<<endl;

	//输出Mystruct1和Mystruct2的大小
	cout<<"sizeof(Mystruct1)="<<sizeof(Mystruct1)<<endl;
	cout<<"sizeof(Mystruct2)="<<sizeof(Mystruct2)<<endl;

	//查看Mystruct1和Mystruct2中变量的(相对于结构体的起始地址)偏移量
	cout<<"Mystruct1_data_db的偏移量="<<offsetof(Mystruct1,data_db)<<endl;
	cout<<"Mystruct1_data_ch的偏移量="<<offsetof(Mystruct1,data_ch)<<endl;
	cout<<"Mystruct1_data_i的偏移量="<<offsetof(Mystruct1,data_i)<<endl;

	cout<<"Mystruct2_data_db的偏移量="<<offsetof(Mystruct2,data_db)<<endl;
	cout<<"Mystruct2_data_ch的偏移量="<<offsetof(Mystruct2,data_ch)<<endl;
	cout<<"Mystruct2_data_i的偏移量="<<offsetof(Mystruct2,data_i)<<endl;



	return 0;
}


 

以上都是一些简单的东西,但是要是时间久了,这些细枝末节就很可能被大家遗忘了,而且这些东西也是笔试中经常光顾的问题。小弟暂且将小文作为乍到优快云的第一篇文章,花了2个多小时整理出来,愿与君共勉。

<think>好的,我现在需要回答用户的问题:如何在不使用sizeof关键字的情况下求C语言中数据类型字节数。首先,我得回忆一下sizeof的作用,它是用来获取类型或变量在内存中的大小。现在用户希望不用这个关键字,那有没有其他方法呢? 首先,我应该想到指针的算术运算。比如,对于数组来说,两个相邻元素的地址差就是该类型的大小。假设我们有一个数组,比如int arr[2],那么&arr[1]和&arr[0]之间的差就是int的大小。不过这个方法可能对某些类型比如char不太适用,但原理是对的。或者,可以使用结构体中的两个相同类型的成员,计算它们的地址差。但结构体可能会有填充,所以这可能不太可靠。 另一种方法是使用指针的差异。例如,将指向某类型的指针加1,然后转换成char指针,这样得到的差值就是该类型的大小。例如,对于int类型,可以这样做:(char *)(&ptr + 1) - (char *)&ptr,其中ptr是该类型的变量。但这里要注意,ptr必须是一个变量,而不是类型名,所以可能需要用类型名来声明一个变量,或者用0指针进行运算?或者使用结构体中的成员地址差? 或者,使用0指针的技巧。例如,假设有一个结构体,里面有两个相同类型的成员,比如struct { char a; type b; }; 然后计算&b - &a,不过这样可能会有对齐的问题。或者更简单的办法是,将类型指针转换为char指针,然后相减。例如: int a; char *p1 = (char*)&a; char *p2 = (char*)(&a + 1); int size = p2 - p1; 这样,&a+1是指向下一个int的位置,转换成char指针后,两者的差就是int的大小。这可能是一个可行的方法。同样的,对于其他类型,比如double,也可以用似的方法。 那用户的问题是如何不用sizeof,所以这个方法应该可行。那如何将这个思路转化为代码呢?比如,定义一个宏或者函数,接受类型作为参数,然后返回其大小。 例如: #define GET_SIZE(type) ((size_t)((char *)((type *)0 + 1) - (char *)((type *)0))) 不过,这里使用了0指针的算术运算,这在C语言中是否是未定义行为?因为对空指针进行加减操作可能有问题。不过,在某些编译器中,这可能被允许,只要不进行解引用操作。但这是否具有可移植性呢? 或者,另一种方法是声明一个数组,比如type arr[2],然后计算(char*)&arr[1] - (char*)&arr[0]。这样得到的差值就是类型的大小。比如: int main() { int arr[2]; size_t size = (char*)&arr[1] - (char*)&arr[0]; printf("%zu\n", size); return 0; } 这个方法应该可行,而且不需要使用sizeof。同样,对于其他类型,只要替换数组的类型即可。或者,可以将其封装为一个宏: #define GET_SIZE(type) ((size_t)((char*)&((type*)0)[1] - (char*)&((type*)0)[0])) 这可能会有问题,因为访问0指针的数组元素可能被视为未定义行为。不过,如果只是计算地址差而不解引用,可能编译器会允许。但这是否安全? 或者,更安全的做法是声明一个实际变量,例如: type var; size_t size = (char*)(&var + 1) - (char*)&var; 这里,var是一个变量,&var+1是指向下一个type元素的地址,转换为char指针后,两者的差就是type的大小。这种方法可能更可靠,因为var是一个实际存在的变量,虽然可能在栈上,但地址运算合法。 所以,具体的实现可以是这样的: 比如,对于int类型: int a; size_t size = (char*)(&a + 1) - (char*)&a; 这样得到的size就是int的大小。同样的方法适用于其他数据类型,如double、结构体等。 那用户可能想要的是一个通用的方法,或者针对特定类型的方法。比如,可以写一个宏,接受类型参数: #define GET_SIZE(type) ((size_t)((char *)((&((type){0})) + 1) - (char *)(&((type){0})))) 这里,使用复合字面量创建一个type类型的临时对象,然后取其地址,加1得到下一个元素的地址,然后计算差值。这可能更通用。 不过,复合字面量是C99的特性,可能在旧编译器中不支持。或者,使用变量声明的方式: type dummy; size = (char*)(&dummy + 1) - (char*)&dummy; 但这种方法需要在宏中声明变量,可能比较困难。或者,使用一个函数,例如: size_t get_size(type *dummy) { return (char*)(dummy + 1) - (char*)dummy; } 然后调用时传入一个类型指针的NULL,但这样可能会有问题。或者,让用户传入一个该类型的变量,然后在函数中计算。 不过,用户的问题是求数据类型的大小,所以可能需要针对不同的类型有不同的处理。但用户可能需要一个通用的方法,所以用宏可能更合适。 另外,还可以通过结构体对齐的方式来计算。例如,定义一个结构体包含两个char数组,然后计算它们的偏移量。但这种方法可能不太直接。 总结起来,最可靠的方法可能是通过指针运算,即用变量地址加1后的地址差来计算。例如,声明一个变量,取它的地址,加1,转换为char指针,然后减去原来的地址,得到字节数。 所以,示例代码如下: #include <stdio.h> int main() { int a; size_t int_size = (char*)(&a + 1) - (char*)&a; printf("Size of int: %zu\n", int_size); double b; size_t double_size = (char*)(&b + 1) - (char*)&b; printf("Size of double: %zu\n", double_size); struct example { char c; int i; }; struct example s; size_t struct_size = (char*)(&s + 1) - (char*)&s; printf("Size of struct example: %zu\n", struct_size); return 0; } 这个方法的原理是,对于类型为T的变量var,&var + 1会指向下一个T元素的地址,即跳过整个T的大小。将这两个地址转换为char*(因为char的大小是1字节),它们的差值就是T所字节数。 但需要注意的是,这种方法可能不适用于所有情况,比如对于位域或者某些特殊类型,但通常对于基本类型和结构体是有效的。 另外,用户可能希望得到一个通用的宏,可以替换类型参数。例如: #define GET_SIZE(type) ((size_t)((char *)(&((type *)0)[1]) - (char *)(&((type *)0)[0]))) 但这样使用空指针可能会有问题,因为对空指针进行加减操作是未定义行为。虽然实际中很多编译器可能允许这种计算,因为它不涉及解引用,但严格来说是不安全的。因此,更安全的方法是使用实际变量的地址,如前面的示例。 因此,正确的解决方法是利用指针算术运算,将变量地址加1后的差转换为char指针来计算字节数。这种方法不需要使用sizeof,且适用于大多数数据类型。</think><< 不使用sizeof求数据类型字节数的方法是利用指针算术运算。通过计算相邻元素地址差值来确定数据类型大小。以下是具体实现方法: 示例代码: ```c #include <stdio.h> int main() { int a; size_t int_size = (char*)(&a + 1) - (char*)&a; printf("Size of int: %zu\n", int_size); double b; size_t double_size = (char*)(&b + 1) - (char*)&b; printf("Size of double: %zu\n", double_size); return 0; } ``` 实现原理: 1. 通过`&variable + 1`获取下一个同类型元素地址 2. 将两个地址强制转换为`char*`类型指针 3. 计算地址差值即为该类型字节数 4. 此方法利用了指针算术的特性:指针+1操作会自动跨越整个数据类型长度 注意事项: - 必须使用具体变量实例而非类型名称 - 对void类型和函数指针不适用 - 结构体计算可能包含填充字节 - 不适用于寄存器存储类型(register修饰变量)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值