看库源码:
通过观看rand()函数可以知道
int rand() { return holdrand = holdrand * 214013L + 2531011L; };其实每次rand都是排列好的了数字 是因为srand随机出第一位数字。(按照时间创造首次排位 初始化一次就可以了) 所以放在main开始处就不用每次调用的时候再重新刷新一次随机种子
链接在以前笔记中已经谈及,链接是生成obj以后 生成exe的时候出现的问题 所以比编译错误更难查找的到 总结如下:
全局变量的声明(不是实现),需要extern关键字声明放在头文件中实现放在cpp文件中如何不闪烁,并且实现任意位置输出 在C库函数,没有办法实现任意地方位置输出。 必须在window提供的函数去实现(API)。 使用必须包含window.h. 如果没有用到以前的彩色库文件 那么我们自己可以封装一个函数 帮助我们使想输出的东西,在任意位置输出 下面使用万能的Hello Word作为测试
#include"stdafx.h" #include<stdio.h> #include<Windows.h> void MoveCursorTo(int nRow, int nCol) { COORD loc; loc.Y = nRow; loc.X = nCol; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), loc); } int main(void) { MoveCursorTo(10, 10); printf("Hello\r\n"); MoveCursorTo(20, 20); printf("World\r\n"); return 0; }通过F12得知 COORD是一个结构体
输出结果验证正确 好做完上次笔记总结 今天来说一说指针
C语言中发明了指针,使得我们可以直接方便操作内存,极大的提高了程序的灵活性 同时也提高了C语言程序员的门槛. 指针的基本语法 这里使用实例说明
int main() { int nValue = 0x1234; char chValue = 'A'; short sValue= 0xCCDD; int* pnValue= NULL; char* pchValue = NULL; short* psValue = NULL; pnValue = &nValue; pchValue = &chValue; psValue = &sValue; //指针里面存放的是地址 printf("%p %p %p\r\n", pnValue, pchValue, psValue); printf("%p %p %p\r\n", &nValue, &chValue, &sValue); //解引用 加上* 就是这个地址所指到的东西 printf("%x %x %x\r\n", *pnValue, *pchValue, *psValue); printf("%x %x %x\r\n", nValue, chValue, sValue); return 0; }结果如下
指针有两个内涵 先用代码体会
int main() { //定义指针 int* pnValue= NULL; char* pchValue = NULL; short* psValue = NULL; int nValue = 0xAABBCCDD; pnValue = &nValue; pchValue = (char*)&nValue; psValue = (short*)&nValue; //输出地址 printf("%p %p %p\r\n", pnValue, pchValue, psValue); //输出内容 printf("%x %x %X\r\n", *pnValue, *pchValue, *psValue); return 0; }结果如下
可以知道地址是一样的,但是内容不同了 这就反映出指针的本质,它其实不仅仅是一个地址 指针包括两个内涵:
地址(指向哪里)解释方式(如何把所指的东西取出来) 理解以上,就很快的明白了 为什么C语言不允许: 不同类型不能去指向 pValue=&nValue;与指针有关的运算除了,取地址 & 与解引用 * 以外还有
+,-运算符++,-- 自增自减运算符 通过实例来学习: int main() { //定义指针 int* pnValue= NULL; int nValue = 0x1234; pnValue = &nValue; printf("%p\r\n", pnValue); printf("%p\r\n", pnValue-1); printf("%p\r\n", pnValue-2); printf("%p\r\n", pnValue+1); printf("%p\r\n", pnValue + 2); return 0; }可以看到以上的程序,不是简单的数学意义的相加减 而是(指向Type类型的指针):
pValue+i的地址=pValue+i*sizeof(type);除此之外 两个指针是不能相加的,因为没有什么意义,但是同类型的指针是可以相减的
int main() { char chArry[] = { 0, 3, 9 }; char* pchValue1 = chArry; char* pchValue2 = &chArry[2]; printf("%d\r\n", pchValue2 - pchValue1); return 0; }指针的相减不是数学意义的相减,实际上,两个指向type类型相减:
p1-p2 所得的结果为: ((int)p1-(int)p2)/sizeof(type)它的直接意义,就是用来计算两个地址所隔的元素个数
以前就提及到,数组的名字就是数组的首地址. 精确的讲数组名就是一个包含解释方式的数组首地址. 当数组作为参数传递的时候,实际会退化成指针传递.
void MyFun(int arry[], int nCount) { printf("%d\r\n", arry[nCount]); printf("%d\r\n", *(arry + 2)); } int main() { int nArry[] = { 1, 2, 3 }; MyFun(nArry, 2); return 0; }字符串不是C语言的基本数据类型,因为字符串生来变长 为了能够解决操作变长的数据,我们就需要约定,字符串怎么样才算结束 在C语言中的约定是 以0x00为结束符号. 实际上
int main() { char *pchValue = "Hello"; "Hello"; return 0; }这里的单独"Hello"是没有出错的 其实这背后是做了很多的事情的.
在局部区域分配一个空间,能够放下’h’ ‘e’ ‘l’ ‘l’ ‘o’ 五个字母,以及结束标志0x00将h e l l o所对应的ASCII值,填充到上一步区域中.将结束字符放在上一步区域的末尾,作为结束标志.将第一步分配空间的首地址,作为值返回pchValue所指的东西就是 字符串返回的首地址。 具体而言,当参数分别如下时,sizeof返回的值表示的含义如下:
数组——编译时分配的数组空间大小;指针——存储该指针所用的空间大小(存储该指针的地址的长度,是长整型,应该为4);类型——该类型所占的空间大小;对象——对象的实际占用空间大小;函数——函数的返回类型所占的空间大小。函数的返回类型不能是void。 strlen(…)是函数,要在运行时才能计算。参数必须是字符型指针(char*)。当数组名作为参数传入时,实际上数组就退化成指针了。功能是:返回字符串的长度 退化对比程序如下 int main() { char chArry[20] = "hello"; printf("%d\r\n", sizeof(chArry)); // 根据上面描述可以知道 但运行对象为数组的时候 编译时候分配的空间 printf("%d\r\n", strlen(chArry));// 计算的是退化为指针后的数组 return 0; }为了更加熟悉函数,我们自己制作自己的字符串函数吧
先在MSDN上找到原型 strlen
#include"stdafx.h" #include<stdio.h> #include<string.h> size_t Mystrlen(const char *string) { int ReCount = 0; while (*string != '\0') { ReCount++; string++; } return ReCount; } int main() { printf("%d\r\n",Mystrlen("HelloWorld")); return 0; }strcmp
int Mystrcmp(const char *string1, char *string2) { int nRet = 0; while (*string1 != '\0') { if (*string2 != '\0') { nRet = *string1 - *string2; if (nRet != 0) { return *string1 - *string2; } } else { return *string1 - *string2; } string1++; string2++; } return *string1 - *string2; }strcpy
char* Mystrcpy(char *str1, char *str2) { char *pContent = NULL; pContent = str1; while (*str1 != '\0'&&*str2 != '\0') { *str1= *str2; str1++; str2++; } *(str1) = '\0';//后面的数据处理为0 return pContent; }strcat
char* Mystrcat(char *str1, const char *str2) { char *pnContent = NULL; pnContent = str1; while (*str1 != '\0') { str1++; } while (*str1 == '\0'&&*str2!='\0') { *str1 = *str2; str1++; str2++; } return pnContent; }