《C和指针》摘录(一)

来源:互联网 发布:淘宝 中药材 真假 编辑:程序博客网 时间:2024/06/01 08:54

以下均为个人看了《C和指针》Reek著 人民邮电出版社后将之前不清楚或觉得需要强调的摘抄的:

预处理指令:
如下均为预处理指令:

#include <stdio.h>#include <string.h>#define MAX_COLS 20

预处理指令(preprocessor directives)由预处理器(preprocessor)解释,预处理器读入源代码,根据预处理指令对其进行修改,然后把修改过的源代码递交给编译器。

环境
翻译环境:源代码被转换为可执行的机器指令
执行环境:用于实际执行代码
例如:交叉编译器,在一台机器上运行,但它所产生的可执行代码运行于不同类型的机器上。

字符串常量:
被双引号括起来的一串字符
eg:”Hello” 在内存中占据6个字节的空间,(结尾有一个NULL)

—————–常用printf格式代码——————–
%d 十进制
%o 八进制
%x 十六进制 (十六进制中,可以使用字母ABCDEF或abcdef)

—————–常用scanf格式代码——————–
%d 读取一整型值
%f 读取一浮点数
%c 读取一字符
%s 读取一字符串

注:前三种因为读取标量值,所以变量参数前加“&”eg

scanf("%d",&columns[num]);

—-类型————————–最小范围——-
unsigned char —————- 0~255
short int —————— -32767~32767
unsigned short int———- 0~65535
int ————————— -32767~32767

浮点数默认情况:double类型,后面跟一个L或l:long double / F或f:float类型

指针:

int* a, b, c;   //b c为intint *a, *b, *c;int a, *pi;pi = &a;    //pi的值为内存中某个特定位置的地址(a的存储地址),*操作符使机器指向那个位置

NULL指针:要使一个指针变量为NULL,可以给他赋一个零值。
可以把字符串常量赋值给一个“指向字符的指针”,不能将其赋值给一个字符数组,因为字符串常量的直接值是一个指针!:

char *message = "hello";等效于:char *message;message = "hello";

函数如果不显式地声明返回值类型,默认返回整型。

const:

int const a;等效于:const int a;int const *pci;         //不能修改它所指向的值int * const cpi;        //指针是常量,它的值不能修改,但能修改它所指向的整型的值

static

static int c(int d){    ...}

可以防止它被其它源文件调用

extern:
为一个标识符指定external链接属性,可以访问在其他位置定义的这个实体

变量的存储类型
在代码块之外声明的变量:存储于静态内存中,不属于堆栈的内存,静态变量。
在代码块内部声明的变量:缺省存储类型是自动的,存储于堆栈中,自动变量。

可以通过static,将存储类型从自动变为静态。具有静态存储类型的变量在整个程序执行过程中一直存在,而不仅仅在声明它的代码块的执行时存在。但,注意:修改变量的存储类型并不表示修改该变量的作用域,仍只能在该代码块内部按名字访问。

局部变量由函数内部使用,不能被其它函数通过名字引用。缺省情况下存储类型为自动:一,当这些变量需要时才为他们分配存储,可以减少内存的总需求量;二,在堆栈上为它们分配存储可以有效地实现递归。
static关键字总结
当它用于函数定义时,或用于代码块之外的变量声明时:

只能在声明他们的源文件中访问

当它用于代码块内部的变量声明时:

如上(变量的存储类型中)所述,用这种方式声明的变量在程序执行之前创建,在程序的整个执行期间一直存在,而不是:每次在代码块开始执行时创建,在代码块执行完毕后销毁。

示例:

int a = 5;      //链接属性为默认的:externalextern int b;   //b的定义可以在此or其他地方static int c;   //static修改链接属性为internal//以上三个存储类型为静态,不存储于堆栈中,在程序执行之前创建并一直保持他们的值,直到程序结束。int d(int e){    ...    {        int a;        ...    }//a的作用域本来是全程序,但该{}内有同名的变量,所以在该{}内,a指的是这{}里定义的     //a,{}结束之后a指的是开头定义的a    ...}

例子,在一组字符串中查找:

int find_char(char **strings, char value)       //strings: 指向字符串的指针的指针{    char *string;    while((string = *strings++) != NULL)    //指针数组以NULL指针结束    {        while(*string != '\0')             //string:指向字符串的指针,字符串以'\0'结尾        {            if(*string++ == value)                return 1;        }    }    return 0;}

指针运算:

当一个指针和一个整数量执行算术运算时,整数在执行加法运算前始终会根据合适的大小进行调整:    合适的大小:指针所指向类型的大小    调整:整数值和“合适的大小”相乘两个指针相减:结果类型是一个有符号整数类型,值为两个指针在内存中的距离(以数组元素的长度为单位,而不是字节!   &p[j]-&p[i] = j - i )

函数:

追踪递归函数:

变量创建于运行时堆栈上的,以前调用的函数变量仍保留在堆栈上,但他们被新函数的变量所掩盖,因此不能被访问。对于下面这个求阶乘问题:factorial(n) = 1                   (n = 0)               n * factorial(n-1)  (n > 0)如果用 递归函数 来做,会在运行时有些开销:参数必须压到堆栈中,为局部变量分配内存空间,寄存器的值必须保存。当递归函数的每次调用返回时,上述这些操作必须还原,恢复成原来的样子。:
long factorial(int n){    if( n == 0)        return 1;    else        return n * factorial(n - 1);}
    所以不如用 迭代 来算阶乘:
long factorial(int n){    int result = 1;    while( n > 1)    {        result *= n;        n -= 1;    }    return result;}
0 0