C与指针琐碎点

1、结构体定义结束要有分号,函数定义没有分号;
2、结构体【结构体数组】变量初始化可以用大括号形式,但C中不能用大括号进行赋值,注意赋值和初始化的区别;
3、条件编译的三种类型:

#define A 1 #define A #define A
#if A #ifdef A #ifndef A
#define B 1 #define B 1 #define B
#else #else #else
#define D 1 #define D 1 #define D
#endif #endif #endif


4、strlen函数的判断条件:*string++!='\0'

5、左值与右值的理解:

数组名是一个指针常量

左值意味着一个位置,右值意味着一个值

——参见《C和指针》[《POINTERS ON C》]Kenneth A. Reek著 5.4.3&6.11节指针表达式

6、printf中%s输出是输出字符串时所用的格式符,在输出项中给出字符指针变量名string,则系统先输出它所指向的一个字符数据,然后自动使string加1,使之指向下一个字符,然后在输出一个字符......如此直到遇到字符串结束标志'\0'为止。可以进行字符串的整体输出

printf中%c输出则需要给定变量,而不是地址,例如:

char *p_char= 'F';

printf("%c",*p_char);

而printf("%c",p_char);则不会输出


7、字符型指针与数值型指针的最大不同在于:

char *a="china";

printf("%s\n",a);【给定指针地址,输出的是指针指向的内容】

int *a;

int i=10;

a=&i;

printf("%d\n",a);【输出的是变量i的地址,而非指针所指向的内容】

printf("%d\n",*a);【输出的是指针所指向的内容】

8、二级指针应用于指针数组,可以方便进行指针数组元素的自增索引或遍历

【可以将二级指针看从存在三类可用地址,一类是&p,一类是p+i,也就是指针数组元素的地址,最后一类是*p,也就是字符串的首地址】

char *name[]={"ABC","DEFdhoa","GHJL:","hoaf"}; //定义字符指针数组

char **p;

p=name;//二级指针的初始化,或者p=&name,结果都是一样的

*(p+1)表示D的地址,即"DEFdhoa"

*(p+2)表示G的地址,即"GHJL:"

*p+1表示B的地址

*(p+1)+1表示E的地址

*(*p+1)表示B

9、能否看出下述两个图执行结果的差别

例一:

for( vp = & values[N_VALUES]; vp > &values[0];)

*--vp=0;

例二:

for( vp = & values[N_VALUES-1]; vp >= &values[0];vp--)

*vp=0;

标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第一个元素之前的那个内存位置的指针进行比较。即vp++可以,数组元素后面越界的第一个指针仍能与数组元素指针比较,但是vp--存在问题。


10、使用指针容易出现的错误



11、指针用NULL初始化,感觉没有什么意义,也就是空指针意义不大,除了可以作为函数的返回值


12、位操作:

指定位置一:value | 1<<bit_number

指定位清零:value & ~(1<<bit_number)

测试指定位的值:value & 1<<bit_number


13、while(scanf("%d",&n),n!=EOF) //while(scanf("%d",&n)!=EOF)也行

在 UNIX中, EOF表示能从交互式 shell (终端) 送出 Ctrl+D (习惯性标准)。在微软的 DOS 与 Windows 中能送出 Ctrl+Z。


14、statistic 关键字

因为static变量也就是静态变量,在程序运行过程中被声明后就会一直保存在内存里,所以只能声明一次,第二次再访问那个函数时,给静态变量声明同时初始化的语句就不再执行了,而静态变量的值始终保存在内存里,也就是上次改变以后的值。没有static修饰的函数中的变量,只在函数被执行时占用内存,函数执行完毕后就被销毁,数据也就不存在了,所以每次都要声明,值也就不会变。

15、‘%’求余运算



16、函数形参:

function_name(char array[])使用时等价于function_name(char *array)

function_name(char array[10])也同样表示数组名传递,但是数组大小限定为10

只有数组名才能当做地址使用而不使用指针,变量名不可以这样做,只能用取址符号获得变量的内存地址

17、抽象数据类型就是把一些有一定关联的基本数据类型打包,然后当做新的数据类型使用。c++类使得抽象数据类型的可操作性更强了,真正实现了面向对象。


18、stdarg.h——可变参数列表(原理:函数参数是以栈的形式存取,从右至左入栈

function(type1 para1,...)
{
va_list argp;//定义一个可变参数列表
va_start(argp,para1);//初始化把argp变量设置为指向可变参数部分的第一个参数,也就是para1的后面那个参数
...
va_arg(argp,int);//获取可变参数的当前参数,返回指定类型并将指针指向下一参数,该宏接受两个参数,va_list变量和参数列表中下一个参数的类型,返回当前指向参数的值,并使va_list变量指向下一个可变参数
...
va_end(argp);//清空va_list可变参数列表
}
这些宏存在两个基本的限制:1.这些宏无法判断实际存在的参数的数量;2.这些宏无法判断每个参数的类型

19、#define DEBUG(...) printf(__VA_ARGS__)

20、ERROR——"initializer element is not a constant"

 In C, global variables can only be initialized with constants, such as numeric values, NULL or fixed strings.

21、sizeof(数组名)返回的是该数组的长度,以字节为单位

22、C语言中编译器是不对数组的下标进行检查,因此编写代码要注意防止越界

效率不是唯一的因素,通常代码的可读性和简介性更重要

23、C循环效率的提高



24、尽量避免使用全局变量,本着函数“内聚性”强,“耦合性”弱的特点,函数之间只通过形参进行交互。

全局变量可供本文件的其它函数使用,存放于静态存储区;

局部变量只能供函数自身使用,

静态局部变量(static)存放在静态存储区,两个特点:只进行一次初始化赋值,并保留函数执行的结果;编译会自动初始化为0;

自动局部变量(auto)存放在动态存储区,三个特点:每次调用临时分配,函数结束则回收内存空间;编译器不会进行初始化,所以结果是未知的;只有自动局部变量和形参能声明成寄存器变量(register);

extern全局变量是为了扩展变量的作用域,一般全局变量作用域是从变量声明处到文件结束,如需要在更早处或别的文件中使用,则需在更早出或需要调用的文件中extern声明;

static全局变量是为了全局变量只能被本文件使用,而不能被其他文件引用;

static函数为内部函数,只能被本文件的其它函数调用,而不能被其他文件引用,用于解决不同文件中的同名的内部函数;

extern函数为外部函数,在需要调用的文件中使用,表示该函数是在其他文件中定义的外部函数;

25、关于二维数组的指针作为函数参数

形参一:funcation_name(int *array,...)

函数使用形式包括:

*array++,通过array的自增遍历二维数组的所有元素;
定义新的数组指针,int (*p)[10]=array;再使用(*(p+i)+j)来指定特定的数组元素;

形参二:function_name(int *array[10],...)

这种形式的指针可以直接来指定特定位置的元素,使用方法如上所示。

26、string.h

使用字符串函数首先要确保buffer足够大,其次要注意下面的小细节:

char * strcpy(char *str1,char *str2)函数中如果str2字符串合法(含有'\0',即NUL字符),则不会产生异常错误;

对于strncpy则不会自动添加'\0',因此使用此函数时就要小心,以防越界造成的程序崩溃


对于strncat会在拷贝完成后,自动加上'\0'字符。

27、字符及字符串函数

字符串处理函数:(string.h)


字符处理函数:(ctype.h)



内存操作函数


28、printf打印百分号"%%"

29、关于const修饰的问题

function(char *const str,...):不能对str进行'++'操作,但可以使用*str='*'改变其值

function(char const *str,...):可以对str进行'++'操作,但不可以使用*str='*'来改变其值,如果使用“char *temp=(char *)str;”,则可以间接修改*str的值。

对进行传入指针,最好进行拷贝,以便随时恢复指针原始值

30、void main(int argc,char **argv[ ])

argc=执行所带参数个数+1;

argv[0]表示字符串"./a.out"的首地址;

argv[1]表示命令所带第一个参数的地址;

31、字符指针与字符数组区别

区别一:字符数组保存的字符串存放在内存的栈中,而字符指针指向的字符串保存在内存的静态存储区中

区别二:字符数组保存的字符串属于字符串变量,可以被修改,而字符指针指向的字符串是属于字符串常量,不能被修改。


【会出现:访问了不存在的内存地址、访问了系统保护的内存地址、访问了只读的内存地址等等情况

32、结构体

【结构体变量名不能作为指针常量,只能代表变量,与数组名作为指针常量有区别】

a、结构体可以进行整体赋值

typedef

{

...

}List;

List ls1,ls2;

ls1={...};

ls2=ls1;

b、结构体指针'+1'操作

如果该结构体指针指向一个结构体数组,加一表示后面那个结构体元素;

如果指向某个结构体,则为非法操作,因为对标量值加一;

c、结构体位对齐,即sizeof(结构体变量)不等于实际的成员占字节的总和

具体详见

http://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html

http://jayji.info/struct-bound-align/

33、数组的元素存储于内存中连续的位置,当一个数组声明时,它所需的内存在编译时就被分配。

符号NULL定义于"stdio.h",它的字面常量是0;

内存动态分配函数在ANSI标准中建议在“stdlib.h”头文件包含,而很多编译器则要求用“malloc.h”,而不是“stdlib.h”;

malloc分配动态内存后要手动初始化,而calloc分配内存过后初始化为0;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值