[原创]C语言使用点滴
最近用c写密码学实验,收获了少许,感觉还有用。当然,有的东西可能大家都早用惯了~~~+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
有使用c操作文件时需要预先得到文件的长度,可以先打开文件,记录文件指针的位置,再使用fseek来定位到文件末尾,然后重新ftell文件指针的位置,二者相减则得到长度。不过c库函数里提供了一个现成的函数:
#include <io.h>
File *fp = fopen("...", "rb+");
long fLength = filelength( fileno(fp) );
其中fileno(fp)是用来获取文件句柄。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在c里fseek(FILE *fp)得到文件指针的当前位置,该位置是从0开始索引的。如果一个文件长度为5个bytes,则索引到4。而filelength( fileno(FILE *fp) )就像strlen(char *str)函数,得到的是文件字节个数5而不是4。另外,fseek(FILE *fp, 0, SEEK_END)使用后文件指针位置为5,fseek(FILE *fp, 0, SEEK_SET)使用后文件指针位置为0。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
c的教程里都说c里的函数参数传递方式有两种,值传递和地址传递。因此有时候在传递一个指针时会产生误解,例如下面的代码:
int *c;
void f(int *c)
{
c = (int *)malloc(sizeof(int));
}
f函数执行后并没有改变c的值,因为c里存的是某个地址值,就像f(int i)函数一样,还是值传递。
要改变上述c的值,就要用双指针,或者使用return:
int *c;
void f(int **c)
{
*c = (int *)malloc(sizeof(int));
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在c里,函数的局部变量都是分配在堆栈上的,函数执行完后,局部变量区就自动释放了。因此不能在子函数里用指针指向一个局部变量,例如:
int *c;
void f(int **c)
{
int cs[20];
*c = c;
}
数组也是分配在堆栈上的,f函数执行完后,cs数组也就释放了,所以int *c指向无效的区域。
而在c里只有堆才会在整个程序执行完后释放,因此上述代码要如下修改:
int *c;
void f(int **c)
{
*c = (int *)malloc(sizeof(int)*20);
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
如果有
int i = 0xff;
int j = -1;
在编译器编译时,两个都是整型,低8位都是1,但0xff是正数,而-1是负数,因此对于0xff则i的高八位是0,对于-1则j的高八位是1。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在c语言里,fputc的原理是将一个字节取出,放到一个int型的低8位里,而fgetc如果参数是一个int类型时,则将该参数的低8位取出,写到文件里。因此,在使用fgetc读文件并判断文件是否结束时,应使用int变量而不是char型变量来接收该函数的返回值。使用int变量,根据其原理,只要还有字节可读,就算遇到中文字符(最高位可能为1)也不会得到复数,因为高8位仍为0,而只有在读不到字节时才直接返回-1。
当然,判断文件结束也可以使用fread()函数,如果读不到字节了则返回0。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在c里结构体作为函数参数时是按值传递。
例如:
struct {
int a;
int b;
}test;
test t;
f(test t)
{
t.a = 5;
t.b = 6;
}
执行了f以后,t里面的各个元素值并没有改变。因为t是按值传递的。要改变t里元素的值,可以传递t的地址。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
c里的移位运算符<< 和 >> 都是有符号的移位。不存在绝对移位。
因此如果对char c 进行右移 c >>= 2,如果c的最高位是1,则最左边的两位都填上了1。
因此要实现绝对右移,则可以将c的补上去的两位与为0,具体规律如下:
#include <math.h>
char AbsRightShit(char c, int n)
{
c >>= n;
c &= (char)(pow(2,8-n)-1);
return c;
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++