C语言进阶教程(一)(转自Peter Fačka)

来源:互联网 发布:淘宝搬家 网站 编辑:程序博客网 时间:2024/05/01 20:43

                     C语言进阶教程

        C语言是系统编程,嵌入式系统编成的语言,同时也是许多应用程序的选择。如果想对计算机编程有严肃的兴趣又不接触C语言似乎是不可能的。全方位的理解C语言和它”阴暗“的角落尤其是个挑战。这篇文章试着去提供浅显的实例来阐释C语言的一部分。包括:整型提高,内存分配,数组与指针变换,明确的内联,插值和矢量交换。

 

整体溢出与提升

 

  大多数C程序员倾向于假定整型的基本操作是安全的。事实上,这很容易出问题,考虑一下如下代码:

int main(int argc, char** argv) {

    long i = -1;

    if (i < sizeof(i)) {

         printf("OK\n");

    }

    else {

         printf("error\n");

    }

    return 0;

  当变量i被转成无符号整型会发生什么。由于sizeof运算,因此它的值不再是-1,而是size_t的最大值(原文如此)。发生这种变化的原因在C99/C11标准的”通常算法转换“一章中有描述:

“如果运算对象有无符号整型的值不小于其他运算对象,则有符号整型的运算对象将被转换成无符号整型。”

C标准定义size_t为最少16 bits的无符号整型。通常情况下size_t与给定架构的长一致。这使得int型的长度至少与size_t相同,上述规则强制转化int为无符号整数。

这给了我们整型长度的可移植性问题。C标准并没有明确的规定short,int,long,long long和他们的无符号形式的长度。只有强制性的最小长度。举个例子,x86_62架构,long型在Linux里是64-bits但在64位Windows下是32-bits。让代码更具移植性的一般方法是用长度特定化的变量如C99的stdint.h头文件中定义的uint16_t或者int32_t。它定义了三种长度的整型变量:

有明确特殊的长度:uint8_t,uint16_t,int32_t,等等。

带有特殊长度的最小变量:uint_least8_t,uint_least16_t,int_leasr32_t等等。

有特殊长度的最高效的变量:uint_fasr8_t,uint_fast16_t,int_fast32_t等等。

 

不幸的是,使用stdint.h不能保护我们原理所有问题。C标准的”完整提升法则“中说:

如果一个整型变量可以代表所有原型变量的值,值被转变为整型变量,否则值被转变为无符号整型变量。这些都叫做整型提高,所有其他种类不被整型提高改变。

因此下面的代码在32位平台上返回65536,而在16位平台上返回0。

uint32_t sum()

{

    uint16_t a = 65535;

    uint16_t b = 1;

    return a+b;

}

  整型提高保护值和符号。无论一个“简单的”字符变量是否被以“已经定义”对待。

  字符变量如何实现通常根据硬件架构或者OS,它通常被特别平台的ABI规定。如果你想自己找出来的话,万一char变为了signed char,下面的代码会打出-128,-127(x86架构),否则会打出128,129。GCC有funsigned-char转换来在x86架构上进行强制无符号。

char c = 128;

char d = 129;

printf("%d,%d\n",c,d);


如有任何见解与建议欢迎发送邮件至:frank.tancf@gamil.com

原文转自:http://pfacka.binaryparadise.com/articles/guide-to-advanced-programming-in-C.html

0 0
原创粉丝点击