发新话题
打印

[原创]C语言蛛丝计划 学习中我所看见的细节总结(第四部分)

[原创]C语言蛛丝计划 学习中我所看见的细节总结(第四部分)

文章作者:冰血封情[E.S.T]
信息来源:邪恶八进制 中国

我不会为关注细小的东西而忽视全局的 只是想学的更加细致一些 以便一步一个脚印(一刀一道伤疤[s:51])
坚持自己的路 不要在意别人的眼光 第四篇总结 贵在坚持 我们在进步:)

019全局变量和局部变量
为了我的学习 无锋大哥和东方兄弟都曾经唠叨过这个问题 现在果然如他们所言 感谢小组兄弟给我的帮助呀..............
如果说外部变量(有的时候也叫全局变量)的作用域为整个程序并不准确 而应该说外部变量的作用域为包含该变量定义的整个源代码文件 如果整个程序包含在一个源代码文件中 则这两种有关作用域的说法是等价的
那么啥时候使用外部变量呢?仅当程序的所有或大部分函数都需要使用某个变量 才应该将其声明为外部变量 如果只有一些函数需要访问某个变量 那么你应该把该变量作为参数传递给这些函数 而不是声明外部变量

下面说一个重要的问题 书上这么说
如果没有显式的初始化外部变量(给它赋值) 那么在定义外部变量的时候 编译器将把它初始化为0 而对待没有初始化的内部变量 则不会这样做
现在我用VC++6来测试一下 如下程序
复制内容到剪贴板
代码:
#include <stdio.h>

int fuck1;

int main(void)
{
     int fuck2;
     printf("fuck1 = %d, fuck2 = %d", fuck1, fuck2);

     return 0;
}
大家可以看见 fuck1和fuck2都没初始化 编译的时候会出现一个警告
Cpp1.cpp(8) : warning C4700: local variable &#39;fuck2&#39; used without having been initialized
执行结果是
fuck1 = 0, fuck2 = -858993460
看来至少在VC++6下是这样的:)

020静态变量和动态变量
嘿嘿 静态变量的值竟然是动态的 动态变量却不变 为什么呢 跟我来...
首先看一个程序
复制内容到剪贴板
代码:
#include <stdio.h>

void func1(void);

int main(void)
{
     int count;

     for (count = 0; count < 20; count++)
     {
          printf("At interation %2d: ", count);
          func1();
     }

     return 0;
}

void func1(void)
{
     static int x = 0;
     int y = 0;

     printf("x = %2d, y = %2d\n", x++, y++);
}
这里呢 x被声明成静态变量 而y是动态的 于是运行的结果如下:
引用:
At interation  0: x =  0, y =  0
At interation  1: x =  1, y =  0
At interation  2: x =  2, y =  0
At interation  3: x =  3, y =  0
At interation  4: x =  4, y =  0
At interation  5: x =  5, y =  0
At interation  6: x =  6, y =  0
At interation  7: x =  7, y =  0
At interation  8: x =  8, y =  0
At interation  9: x =  9, y =  0
At interation 10: x = 10, y =  0
At interation 11: x = 11, y =  0
At interation 12: x = 12, y =  0
At interation 13: x = 13, y =  0
At interation 14: x = 14, y =  0
At interation 15: x = 15, y =  0
At interation 16: x = 16, y =  0
At interation 17: x = 17, y =  0
At interation 18: x = 18, y =  0
At interation 19: x = 19, y =  0
可以看见动态变量由于每次调用是重新建立的 所以一直都是0 但是静态的就不同了
但是书上说改成下面这样会出现y也递增的情况 在我的VC++6上没有出现:)
复制内容到剪贴板
代码:
#include <stdio.h>

void func1(void);

int main(void)
{
     int count;

     for (count = 0; count < 20; count++)
     {
          printf("At interation %2d: ", count);
          func1();
     }

     return 0;
}

void func1(void)
{
     static int x;
     int y;

     printf("x = %2d, y = %2d\n", x++, y++);
}
而让我感觉到奇怪的是 我的编译器只报了一个错
Cpp1.cpp(23) : warning C4700: local variable &#39;y&#39; used without having been initialized
也就是说呀 static int x;不初始化 竟然在VC++6下没报错 后来运行后发现y的值不确定 可是x却一直是0
看来 static int x;默认的x也是赋值为0的哦...

021外部静态变量和寄存器变量
如果客观条件不允许 申请也没有用的 寄存器变量是个被动状态哦
可以使用static将外部变量声明为静态的 比如
static float fuckyou;

int main(void)
{
     /* Additional code goes here */
}
静态外部变量和常规外部变量的区别在于作用域
常规外部变量对于其所在的文件中的函数而言 都是可见的 同时 其他文件中的函数也可以使用它的说
静态外部变量只位于他所在的文件中 且在它的定义之后的函数中可见 以后就可以体会了 不着急

寄存器变量使用如下方法声明
register int fuckyou;
这里有个细节需要注意的是 register只能用于简单的数值变量 而不能用于数组和结构 另外 它也不能用于静态变量和外部变量...
您不能定义指向寄存器变量的指针

022存储类型指导原则及同名局部全局变量
一些存储类型的决定指导原则
首先考虑动态局部存储类型
如果变量(如循环计数器)将被频繁使用 则在其定义中加上关键字register
在除main()函数之外的函数中 如果变量的值需要在两次调用函数之间保持不变 则将它声明为静态的
对于大部分和全部函数都要使用的变量 应该声明为全局的

那么计算机是如何区分局部和全局变量的呢
现在还不用讨论这么NB的东西 我TMD太菜 但是可以指出 当局部变量的名称和全局变量的名称相同时 在局部变量的作用域内(该局部变量所在的函数中)程序将暂时忽略全局变量(不知道NND翻译的合适不合适)直到进入局部变量的作用域外 就GO ON

023程序流程控制的琐碎总结
这个 我自己总结的都头晕拉 哈哈
首先是system()函数 它可以执行系统命令 直接写在括号里或者用字符串都可以 但是要注意 可移植性不好 因为不同的操作系统的命令不同
其次是书上有条题目问switch语句可以检查哪两种类型的变量?答案说是long 和char 或者int
另外 我过然犯了书上唠叨很多次的错误 把=和==弄混了
复制内容到剪贴板
代码:
#include <stdio.h>

int main(void)
{
     char x;

     puts("Input: ");
     scanf("%c", &x);

     if( x == 98 || x == 121) //这里应该是==而不是= 要不是便宜器提醒 我他妈的就又SB了
     {
          putchar(x);
     }
     else if( x == 78 || x == 110)
     {
          putchar(x);
     }
     else
     {
          puts("Y or N ?");
     }

     return 0;
}
024getchar和getch的两个例子程序分析
下面是一个演示getchar()的小代码段
复制内容到剪贴板
代码:
#include <stdio.h>

#define MAX 10

int main(void)
{
     char ch, buffer[MAX+1];
     int x = 0;

     while ((ch =getchar()) != &#39;\n&#39; && x < MAX)
          buffer[x++] = ch;

     buffer[x] = &#39;\0&#39;;

     puts(buffer);
     printf("%s\n", buffer);

     return 0;
}
从那个while循环开始就要细细研究了 这个代码虽然短 但是第一次学习我真的有点糊涂 一定要扎实过去 好好分析 流程如下
首先我们初始化x为0 而用来存放字符串的数组buffer声明了11个单位的空间 如果说最后一个用来放\0那么为什么要x<MAX而不是x<(MAX+1)呢?
嘿嘿 弄糊涂了 其实初始化为0 那么循环加到9就是10个数字了 那么达到10其实就是第11个位置 也就是最后一个 那当然要退出循环了
此时的x应该是10那么 正好是第11个字符空下来放上字符串末尾的\0
后面我用puts(buffer);和printf("%s\n", buffer);其实只是想复习一下打印字符串 书上是没有前面的puts的

下面我们来看看getch
复制内容到剪贴板
代码:
#include <stdio.h>
#include <conio.h>

int main(void)
{
     int ch;

     while ((ch = getch()) != &#39;\r&#39;)
          putchar(ch);
     return 0;
}
哈哈 更短 那么有什么好说的呢?嘿嘿 你没注意到&#39;\r&#39;么?为什么前面是&#39;\n&#39;这里却是&#39;\r&#39;呢?
之所以将每个字符同\r这个回车比较 因为getch()这个函数是不对输入进行缓冲的
对输入进行缓冲的函数 比如getchar() 会自动把回车转换成换行符 所以必须检测输入是否为\n 而不对输入进行缓冲的字符输入函数 不进行这种转换 因此回车仍然为\r 那么程序就必须检测\r
另外注意一下 如果不用putchar(ch);可就看不到回显了 因为getch是不回显的
你可以用下面的小代码来检测 但是注意 getch()会立刻返回相应字符不会像getchar()一样等到回车才一个个返回 因此下面的代码是打完字符立刻反馈SHIT的
复制内容到剪贴板
代码:
#include <stdio.h>
#include <conio.h>

int main(void)
{
     int ch;

     while ((ch = getch()) != &#39;\r&#39;)
          printf("SHIT!\n");
     return 0;
}
如果想更清楚的看看getch()不回显的特性 你可以把下面的代码 跟第24个总结的第一个代码对比一下 一目了然 不同的地方我做了注释
复制内容到剪贴板
代码:
#include <stdio.h>
#include <conio.h> //老大 你可以要看清楚 这个 可是正经的头文件要包含的 不然你用getch 用个毛呀?

#define MAX 10

int main(void)
{
     char ch, buffer[MAX+1];
     int x = 0;

     while ((ch =getch()) != &#39;\r&#39; && x < MAX) //getch()是人都能看的见 但是\r哦 前面分析过的
          buffer[x++] = ch;

     buffer[x] = &#39;\0&#39;;

     puts(buffer);
     printf("%s\n", buffer);

     return 0;
}
PS 我的流氓书上说 getch()不是ANSI标准命令 Symantec Borland的编译器都支持 还说Microsoft的编译器支持的是_getch()
那我就觉得奇怪了 我用VC++6调试getch()也通过呀
于是我就干脆测试了一下 发现下面的竟然也可以?fuck 这JB什么时候的书呀 都tmd过时了 果然 IT没有新东西 学到就TMD过时了
复制内容到剪贴板
代码:
#include <stdio.h>
#include <conio.h>

int main(void)
{
     int ch;

     while ((ch = _getch()) != &#39;\r&#39;)
          putchar(ch);
     return 0;
}
qq310926是我唯一用号,除此之外有其他号码号自称邪八冰血封情,则非本人。

TOP

发新话题