不使用sizeof,如何求出数据类型的字节数

32位机器下,int型变量占用的内存空间大小为4个字节,如果不用sizeof的话可以通过以下方式:

定义宏

	#include<stdio.h>
	#define MySizeof(Value)	(char*)(&Value+1)-(char *)&Value
	int main()
	{
		int i;
		double	f;	
		double	a[4];
		double	*q;
		printf("%d\n",MySizeof(i));
		printf("%d\n",MySizeof(f));
		printf("%d\n",MySizeof(a));
		printf("%d\n",MySizeof(q));
		return 0;
	}

输出结果: 4

8

32

4

<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修饰变量)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值