Xiaodong's profile千米马的厩PhotosBlogListsMore ![]() | Help |
千米马的厩千米之行,亦始于足下 杂想孤舟泛海,彼岸何岸? 漫漠人生,今昔何昔? 逝去的日子已不可再续,唯有回忆慢慢咀嚼, 青春如汗水般不知不觉蒸发,留下的只是淡淡的咸, 搭错了列车总有到站的一刻,我的列车还会经过这一站吗? 失眠闹钟响了一遍又一遍,晕晕糊糊的爬起来,匆匆洗漱,匆匆赶班车,甚至没时间吃早饭!
两周都如此,难道持续了一年的失眠消失了?这是好事还是坏事? 怀念失眠的日子,可以很早起床,看书想事,悠悠然的洗漱吃早饭,然后再度着方步去上班。 有所得必有怕失啦,多了睡眠时间却少了清醒的时间:) 温习几个程序问题关键字:sizeof, extern "C", for循环的效率
sizeof
再仔细查阅了一下圣经--ISO标准,附1;
首先,这个操作数求出来的是一个类型按byte计算的大小(The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type)
个人觉得这个操作符完全可以看作是一种编译期行为,就是说运算在编译的时候已经完成了,编译器在编译后会把 sizeof(...)替换成一个常量(数据类型为标准中说的size_t);对那些在编译时无法确定大小的数据做sizeof操作都是错误的,或者说使用了编译时不能确定类型大小的数据都是不合法的;
下面看看几种计算结果(假定int的大小是32bit):
sizeof(2); //2是int型, 结果为4
sizeof(2*8); //2*8计算后的结果是int型, 结果仍是4
char* s;
sizeof(s); //s 指针类型,结果是4
char s[5];
sizeof(s); //s 是数组类型,其大小为5, 结果是5
char* s = "Hello";
sizeof(s) //s 还是指针,千万别当成了数组, 结果还是4,
char s[] = "Hello";
sizeof(s); //s 在这里可是数组, 所以结果是5;
size_t func(char s[])
{
return sizeof(s); // 这里s又变成指针了(如果是数组,编译器怎么知道它大小?), 结果是4
}
size_t func(char s[])
{
return sizeof(s[5]); // 嗯,很容易搞混,这里s[5]已经是char类型了(就是s指向的第5个char),结果
// 是1
}
char s[5];
sizeof(s[0]); //这个就比上面那个容易辨认些了,结果是1
typedef struct _A
{ int i;
struct _A *next;
}A;
sizeof(A); //A是一个structure,一个int 加一个指针,结果为8
接上面的定义:
A *a;
sizeof(a); //a 是一个指针,结果不说了
typedef struct
{
char c;
int i;
}B;
sizeof(B); //c是一个byte,i是4个byte, 但结果却不是5,这里有个指针对齐的问题.这也是标准中提到
// 的padding, 处理器访问int须是4的倍数地址访问,在这个结构里,c 占了一个字节, 后面3
// 个字节都不能做为i 的访问地址,所以编译器会在c的后面加上3个字节的padding, 这样,
// 结果应该是8;
typedef struct
{
char c;
int i;
char c2;
}C;
sizeof(C); // 结果是12, c2后面也会被编译器加上3个padding, 确保紧跟这个结构后面的数据访问是
// 4字节对齐的
typedef struct
{
char c;
char c2;
int i;
}D;
sizeof(D); //结果是8, 对char的访问地址可以是奇数.
typedef struct
{
char c;
short s16;
char c2;
int i;
}E;
sizeof(E); //结果是12, s16是short对它的访问可以是2倍数的地址,所以c后面填了一个byte的
// padding, c2后面填了3个 byte的padding.
所以呢,在创建结构的时候有个原则,按数据大小来放置成员,能省不少空间.
extern "C"
嗯,标准里有较详细的描述, 抄袭在附2备查.
for 循环的效率:
这是曾经面试被问及的一个问题:
for( i = 0; i<10; i++);
for( i =10; i>0; i-- ); 哪个效率更高?看arm-GCC输出结果,+比-少一条指令,这样看应该是第一个的效率更高一些了。 第一条输出的结果: mov r3, #9 .L6: subs r3, r3, #1 bpl .L6 第二条输出的结果:
mov r3, #10
.L6: sub r3, r3, #1 cmp r3, #0 bgt .L6 再看x86-gcc的输出结果也一样:
movl $9, %eax
.p2align 2,,3 .L6: decl %eax jns .L6 movl $10, %eax .p2align 2,,3 .L11: decl %eax test1 %eax, %eax jg .L11 [注]以上汇编是加了-O2优化选项的,如果未加优化选项,效率是一样的;
附1: 下面的内容摘自:ISO/IEC 9899:1999 (E)
6.5.3.4 The sizeof operator
Constraints 1 The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member. Semantics 2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant. 3 When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. When applied to an operand that has array type, the result is the total number of bytes in the array.84) When applied to an operand that has structure or union type, the result is the total number of bytes in such an object, including internal and trailing padding. 4 The value of the result is implementation-defined, and its type (an unsigned integer type) is size_t, defined in <stddef.h> (and other headers). 5 EXAMPLE 1 A principal use of the sizeof operator is in communication with routines such as storage allocators and I/O systems. A storage-allocation function might accept a size (in
bytes) of an object to
allocate and return a pointer to void. For example: extern void *alloc(size_t); double *dp = alloc(sizeof *dp); The implementation of the alloc function should ensure that its return value is aligned suitably for conversion to a pointer to double.
6 EXAMPLE 2 Another use of the sizeof operator is to compute the number of elements in an array: sizeof array / sizeof array[0] 7 EXAMPLE 3 In this example, the size of a variable-length array is computed and returned from a function: #include <stddef.h> size_t fsize3(int n) { char b[n+3]; // variable length array return sizeof b; // execution time sizeof } int main()
{ size_t size; size = fsize3(10); // fsize3 returns 13 return 0; } 附2: 下面的内容摘自:ISO/IEC 14882:1998(E)
7.5 Linkage specifications
linkagespecification:
extern stringliteral { declarationseqopt} extern stringliteral declaration The stringliteral indicates the required language linkage. The meaning of the stringliteral is implementationdefined.A linkagespecification with a string that is unknown to the implementation is illformed. When the stringliteral in a linkagespecification names a programming language, the pelling of the programming language’s name is implementationdefined. [Note: it is recommended that the spelling be taken from the document defining that language, for example Ada (not ADA) and Fortran or FORTRAN (depending on the vintage). The semantics of a language linkage other than C++ or C are implementationdefined.]
Every implementation shall provide for linkage to functions written in the C programming language, "C", and linkage to C++ functions, "C++".
[Example:
complex sqrt(complex); // C++ linkage by default extern "C" { double sqrt(double); // C linkage } —end example] Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not stablish a scope. A linkagespecification shall occur only in namespace scope (3.3). In a linkagespecification, the specified language linkage applies to the function types of all function declarators, function names, and variable names introduced by the declaration(s). [Example:
extern "C" void f1(void(*pf)(int)); // the name f1 and its function type have C language // linkage; pf is a pointer to a C function extern "C" typedef void FUNC(); FUNC f2; // the name f2 has C++ language linkage and the // function’s type has C language linkage extern "C" FUNC f3; // the name of function f3 and the function’s type // have C language linkage void (*pf2)(FUNC*); // the name of the variable pf2 has C++ linkage and // the type of pf2 is pointer to C++ function that // takes one parameter of type pointer to C function —end example] A C language linkage is ignored for the names of class members and the member function type of class member functions. [Example:
extern "C" typedef void FUNC_c(); class C { void mf1(FUNC_c*); // the name of the function mf1 and the member // function’s type have C++ language linkage; the // parameter has type pointer to C function FUNC_c mf2; // the name of the function mf2 and the member // function’s type have C++ language linkage static FUNC_c* q; // the name of the data member q has C++ language // linkage and the data member’s type is pointer to C function }; extern "C" { class X { void mf(); // the name of the function mf and the member // function’s type have C++ language linkage void mf2(void(*)()); // the name of the function mf2 has C++ language // linkage; the parameter has type pointer to C function }; } —end example] If two declarations of the same function or object specify different linkagespecifications (that is, the linkagespecifications of these declarations specify different stringliterals), the program is illformed if the declarations appear in the same translation unit, and the one definition rule (3.2) applies if the declarations appear in different translation units. Except for functions with C++ linkage, a function declaration without a linkage specification shall not precede the first linkage specification for that function. A function can be declared without a linkage specification after an explicit linkage specification has been seen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.
At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. Two declarations for an object with C language linkage with the same name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same object. [Note: because of the one definition rule (3.2), only one definition for a function or object with C linkage may appear in the program; that is, such a function or object must not be defined in more than one namespace scope. For example,
namespace A { extern "C" int f(); extern "C" int g() { return 1; } extern "C" int h(); } namespace B { extern "C" int f(); // A::f and B::f refer to the same function extern "C" int g() { return 1; } // illformed,the function g with C language linkage // has two definitions } int A::f() { return 98; } // definition for the function f with C language linkage extern "C" int h() { return 97; } // definition for the function h with C language linkage // A::h and ::h refer to the same function —end note]
Except for functions with internal linkage, a function first declared in a linkagespecification behaves as a function with external linkage.
Example:
extern "C" double f(); static double f(); // error is illformed(7.1.1). ] The form of linkagespecification that contains a bracedenclosed declarationseq does not affect whether the contained eclarations are definitions or not (3.1); the form of linkagespecification directly containing a single declaration is treated as an extern specifier (7.1.1) for the purpose of determining whether the contained declaration is a definition. [Example:
extern "C" int i; // declaration extern "C" { int i; // definition } —end example] A linkagespecification directly containing a single declaration shall not specify a storage class. [Example:
extern "C" static void f(); // error —end example] [Note: because the language linkage is part of a function type, when a pointer to C function (for example) is dereferenced, the function to which it refers is considered a C function. ] 9 Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementationdefined and languagedependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved. 远方远方有多远? 于是,我们一路走来,一步三回头,生怕哪一天真的就看不见他们了,我们不时的闭起眼,回想着他们的殷殷叮嘱.真的,他们就在我们身边. 小的时候,看着远处的山,总想知道山的那边是什么?今天,已不知到了多少个山的那边的那边,虽然还没有到达心中的远方,但也还没有发现自己在划圈,累了,就闭起眼,想想他们,我相信,终有一天会到达心中的那个远方...... 夏日的回忆 常常想起家乡夏日雨后的那种感觉,那是一种风雨过后的舒畅。清香的空气,深深的吸一口,闭上眼慢慢回味,感受自然的亲切;明朗的天空,湛蓝湛蓝的,一眼就看的透彻,让人恨不能就立刻插上翅膀去尽情翱翔;这时,你再背向太阳,看向那遥远的天际,一道七彩的拱桥横跨了半边天,仿佛要把远方的山梁连向更远的山梁。 雨后,伙伴们又都走出了家,呼吸着清香的空气,照着暖暖的阳光,坐在房前屋后看彩虹。有人说:那是龙在吸水,龙要喝饱了准备下一次下雨;有人说:那是仙人在搭桥,接那些在雨中淋湿了翅膀的仙女回家;弟弟说:哥,我长大了也要做一个,你带我到天上去玩!最后大家都没话说了,就指着彩虹说:“真漂亮!” |
|
||||||
|
|