[不指定 2005/11/08 09:16 | by turbozv ]
sizeof是C语言中的关键字,返回的结果是无符号整型常量size_t。

1)sizeof在编译期完成,我们应该把sizeof(xxx)看成一个size_t的常量,其中xxx的运算应完全忽略。如:
char i = 1;
int j = sizeof(i++);
int k = sizeof(i+0.1);
printf("%d %d %d", i, j, k); // 输出为 1 1 8,因为i++并不真正计算,sizeof只关心输入的数据类型,i+0.1被提升为double

同样,可以给一个函数让sizeof运算,如:
double ft(int *i) {
  (*i)++;
  return (*i) * 3.14;
}
void main()
{
  int i = 1;
  int j = sizeof(ft(&i));
  printf("%d %d", j, i); // 输出为 8 1,因为ft()并没有运算,sizeof只关心ft()的返回类型是double(8)
}

2)对数组的sizeof。n个元素数组的大小是一个元素大小的n倍,常用sizeof(arr)/sizeof(arr[0])计算一个数组的长度(而且大家尽可放心编译器直接将其优化为一个整数,而不是两个整数的除运算)


3)对结构的sizeof,有两个影响因素: 结构中的元素的最大长度M,编译器的对齐设置N。
规则一:编译器对齐属性为N(1, 2, 4, 8, 16)字节(VC中用#pragma pack(N), 或者/ZpN,默认/Zp8)
规则二:当N大于元素最大长度M时,以M为准计算
#pragma pack(1)
struct {
  char a;
  char b;
  int c;
  double d;
  char *e;
} str_a;
printf("%d", sizeof(str_a)); //  输出为18, a:1,b:1, c:4, d:8, e:4,最小单位1

#pragma pack(4)
struct {
  char a;
  char b;
  int c;
  double d;
  char *e;
} str_a;
printf("%d", sizeof(str_a)); //  输出为20, ab:4, c:4, d:8, e:4,最小单位4

#pragma pack(16)
struct {
  char a;
  char b;
  int c;
  double d;
  char *e;
} str_a;
printf("%d", sizeof(str_a)); //  输出为24, abc:8, d:8, e:8,最小单位8(因为8<16,以8为准)

    另外,经过在VS2005上的尝试,对于#pragma pack(N),N为其他异常值的情况下(3, 5, 6, 7, -1, "xxx", 1.3....),以M为准


     来给大家出一道考试题目,请写出输出结果:

int i = sizeof('a');
printf("%d", i);

     我就不给出答案了(提示:用C和CPP作为文件后缀分别试试
大家觉得没有问题的话再来几道:

int i = sizeof("a");
printf("%d", i);


int i = sizeof("a" + 1);
printf("%d", i);

... 未完 ...

<转载请注明出处>
Reference:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_pluslang_sizeof_operator.asp
学习 | 评论(9) | 引用(10) | 阅读(17640)
chrislgh
2005/11/23 18:23
这很可能说明ANSI C标准对于 \"\"a\"会被当作一个char *类型还是一个char [2]类型\"这样的问题是无定义的, 它依赖于编译器的实现. 所以, 不要将这种数作为sizeof的操作数.
turbozv
2005/11/23 09:30
让我感觉很奇怪的问题就是M$的VS6, VS2005
在遇到sizeof(\"abcabc\" + 1)的时候,答案是7

当然gcc都是4
turbozv
2005/11/11 19:51
\"对于\"其中xxx的运算应完全忽略\"的说法,并不准确\"
我说明的意思是在运行期完全忽略,复引用运算符也是在编译期可以决定的,所以决定以后sizeof就是一个size_t的常量,里面的xxx内容就会被忽略。
chrislgh
2005/11/11 07:50
sizeof运算符有如下的典型用法:
1. 计算空间大小, 最常见的是malloc的参数,例如:
 data_type_t *p = (data_type_t *)malloc(sizeof(*p));
 
2. 遍历数组时计算元素个数, 比如
#define _dim(arr) sizeof(arr)/sizeof(*(arr))
int i;
int iarr[] = &leftsign;1, 2, 3&rightsign;;
for (i = 0; i < _dim(iarr); i++) &leftsign;...&rightsign;

对于\"其中xxx的运算应完全忽略\"的说法,并不准确, 比如在上述用法1中,就使用了复引用运算符,而这会影响sizeof的计算结果,其关键原因在与这样的计算是否会影响sizeof的操作数的类型。比如int i; sizeof(i)和sizeof(i++)的结果是一样的,其原因是它们的结果都是sizeof(int),而在例子中sizeof(p)和sizeof(*p)不一定相同是因为sizeof(p)的结果是sizeof(data_type_t *)而sizeof(*p)的结果是sizeof(data_type_t)。
我的建议是,除了使用复引用运算符外,不要在sizeof的操作数中使用其他运算符,在实际应用中,我也从来没有遇到过需要使用其他运算符的情形。
sizeof运算符的结果的本质是编译器为某类型分配了多少空间,该值以字节为单位。例如:
void foo(void) &leftsign;int arr[3]; printf(\"foo sizeof(arr) = %d\n\", sizeof(arr)); bar(arr); &rightsign;
void bar(int arr[3]) &leftsign; printf(\"bar sizeof(arr) = %d\n\", sizeof(arr)); &rightsign;
在foo中,arr的类型为int[3],在bar中arr的类型为int *, 在参数列表中写作int arr[xxx], int[]和int *的完全等效的,C运行时只会传递foo中长度为3*sizeof(int)的arr的起始位置给bar做为参数,它将占据sizeof(int *)的空间。
请记住最根本的原因和最基本的用法,请避免可能让人迷惑的用法, 比如sizeof('a'),你一眼看出'a'是一个char类型还是一个int类型吗? 或是sizeof(\"a\"), 你在不查阅任何编程手册的情况下马上回答出\"a\"会被当作一个char *类型还是一个char [2]类型么? 如果你不能, 请不要这样用。记住,在任何时候,都应该使用最直接的表达法。
turbozv
2005/11/11 02:00
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_clang_C_Keywords.asp
查资料就要看权威的22
小峰
2005/11/10 23:18
sizeof不是关键字,是操作符

转自水木清华 career_ms区
bur
2005/11/10 19:54
哈哈,我学得认真哈。V哥的网上培训,难得啊。em17
turbozv
2005/11/10 18:52
笔误啊~ bur真是细心啊,我已经修正过来了coolsmile
bur
2005/11/10 10:09
V哥,最后一个注释多写了个c:
//  输出为24, abc:8, c:4, d:8, e:8,最小
应为:
//  输出为24, abc:8, d:8, e:8,最小
分页: 1/1 第一页 1 最后页