Question: 目的是实现用邻接矩阵储存一个无向图，并打印，但是出了点问题

#include <stdio.h> #include <stdlib.h> #include <string.h>  #define MAX 100  typedef struct {     char vertex; }TVex;  typedef struct{     int adj; }TArc;  typedef struct {     TVex vexs[MAX];     TArc arcs[MAX][MAX];     int dds, bs; }TGraph;  void creatgraph(TGraph *g) {     int i,j,k, q, w;     char a,b;     printf("请输入顶点和边数个数");     scanf("%d %d",&g->dds,&g->bs);     for(i=0;i<g->dds;i++)     {         for(j=0;j<g->dds;j++)         {             g->arcs[i][j].adj = 0;         }     }     for(i=0;i<g->dds;i++)     {         g->vexs[i].vertex = getchar();     }     for(k=0;k<g->bs;k++)     {         scanf("%c %c", &a, &b);         for(i = 0;i < g->dds;i++)         {             if(g->vexs[i].vertex == a) {                 q = i;             }             if(g->vexs[i].vertex == b) {                 w = i;             }         }         g->arcs[i][j].adj = 1;         g->arcs[j][i].adj = 1;     } }  void showgraph(TGraph *g){     int i,j;     for(i=0;i<g->dds;i++)     {         for(j = 0; j < g->dds; j++)         {             printf("%d ", g->arcs[i][j].adj);         }         printf("\n");     } } int main(void) {     TGraph g;     creatgraph(&g);     showgraph(&g);     return 0; } 建议现将基础知识学牢固了。基本的数据结构，结构体引用元素都使用错误。 error都已改掉，对比一下吧～

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。  有时候，偶还用这个观察指定标识符的类型：//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

仅供参考：//C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+


Question: 数组应该如何赋值和输出

第一段输出的是数组a的首地址值，相当于&a[0]的值。

哈哈，我也犯了这个低级错误

数组只有初始化的时候可以使用大括号方式的语法，你第二段代码不能这样用，只能一个元素一个元素的赋值

要输出数组要用for循环  for (int i = 0; i < 3; ++i)         cout << a[i] << endl;

打酱油，漂过

int a[3]是定义数组，a[3]是指a[3]这个元素，你说有何区别

“变量赋值”和“变量初始化”不是一回事！ “变量赋值”发生在运行期，其写法遵循赋值语法规定。 “变量初始化”发生在编译期或运行期，其写法遵循初始化列表语法规定。

第一种方式： #include "stdafx.h" #include <iostream> using namespace std;   int a[3] = { 1, 2, 3 }; void main() {     for (int i = 0; i < 3; i++)         cout << a[i] << endl; } 第二种方式： #include "stdafx.h" #include <iostream> using namespace std;   int a[3]; void main() {     for (int i = 0; i < 3; i++)         a[i] = i+1;     for (int i = 0; i < 3; i++)         cout << a[i] << endl; }

int a[3] = {1,2,3};这个[3]表示数组的个数；  a[3] = {1,2,3};这个[3]表示下标三


Question: 请问为什么这个字符串一输出就会崩溃？

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

%s 需要的是 char*类型的字符串，但你提供的是char类型的字符

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

*&el                                 哇哈哈哈哈哈~~

#include <stdio.h> #include <string.h>  void main(void) {     char *el[] = { "无" };     char *e1 = el[0];      printf("%s\n", e1); }  el是字符指针数组，el数组的每个元素都是指针。因此e1就需要是指针。

el[0]表示你字符串第一个字符，*el[0]表示访问e1[0]地址的值；比如你字符串第一个字符时‘A’（65），那么e1 = *el[0];表示去65这个地址的数据出来给e1，而这个地址是OS内核空间，不允许你程序访问的；这是你报错的原因；  我觉得你的初衷肯定是把字符串第一个字符赋值给e1，那么直接用e1 = el[0]；即可；


Question: 请问16进制在编写程序时有什么用？

16进制表示方便，便于理解字节序。计算机中的都是二进制

二进制是基础，位运算比较高效，有时还更方便，比如掩码

计算机中数据都是用二进制存储，而八进制与十六进制可以比十进制更方便的表示二进制

当你在做数据传输, (比如网络数据传输,串口等),  并且要自定义一些协议时, 你就会发现16进制非常有用. 你要明确知道某个字节是表示什么东西, 以16进制打印出来看时, 就会更清晰.  存在即是合理

电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

对于一个32位数或buffer，16进制可以看到每个字节的值，这个用途比较常见的是wireshark抓到协议包，显示的就是16进制。

计算机内部存储、总线上传输、CPU处理的每一位都是二进制数，0或者1，电平的高或者低（正逻辑或者负逻辑），8位二进制数构成一字节。

在你想知道每个bit是0还是1的时候  1C8  可能一看就知道是   0001 1100 1000 456  根本看不出来

计算机的数制基础是二进制（利用TTL电平的高或低，简单，抗干扰强），二进制难以书写和记忆，4位二进制数等价于一位16进制数，3位二进制数等价于一位8进制数，所以16进制很常用。


Question: 使用了系统禁止的操作系统调用，看看是否越权访问了文件或进程等资源，求大牛解答

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 指针问题

引用 5 楼 zhao4zhong1 的回复:[quote=引用 2 楼 mark_qzh 的回复:] [quote=引用 1楼赵4老师 的回复:]两者均可  pop是val=*--p 搭配 push是p++;*p=val  pop是val=*p-- 搭配 push是*p=val;p++;val=*--p不是先--吗？如果先--了，val的值还是栈顶的值吗？[/quote] 那我就是张冠李戴了，你自行交换一下。[/quote] 正解！

引用 7楼paschen 的回复:看你栈怎么设计的，如果栈在压入元素后，指向的是栈顶元素前一个元素的话，出栈就用val=*--p嗯，我准备看一下数据结构

反正就是看你的p指向哪儿了，如果出栈是 val=*--p 代表的p指向的是栈顶后的一个元素。  在C语言里，我们习惯用第一个入界点和第一个出界点来描述一段数值范围，所以我们经常看到一段循环遍历数组的代码为： for (int i = 0; i < n; ++i)  此时数组下标范围为[0, n), 这是一个半开半闭的区间，n - 1 才是最后一个元素。  在《C陷阱与缺陷》的《3.6 边界计算与不对称边界》有讲到这一点，并且还讨论了为什么习惯用这种方式，楼主感兴趣可以看看。

引用 2 楼 mark_qzh 的回复:[quote=引用 1楼赵4老师 的回复:]两者均可  pop是val=*--p 搭配 push是p++;*p=val  pop是val=*p-- 搭配 push是*p=val;p++;val=*--p不是先--吗？如果先--了，val的值还是栈顶的值吗？[/quote] 那我就是张冠李戴了，你自行交换一下。

引用 1 楼 zhao4zhong1 的回复:两者均可  pop是val=*--p 搭配 push是p++;*p=val  pop是val=*p-- 搭配 push是*p=val;p++;  这个反了吧，val=*--p 搭配的push 应该是 *p=val;p++; 这个吧。

主要看你的栈是什么类型的，val = *--p；优先级是先--在计算--之后的p指向空间的值。  val = *p--;是先*，后-- 至于用哪个，要根据你的栈的结构，若p指向栈顶元素（已压栈的元素），那么用val = *p--；反之用val = *--p;

引用 1楼赵4老师 的回复:两者均可  pop是val=*--p 搭配 push是p++;*p=val  pop是val=*p-- 搭配 push是*p=val;p++;val=*--p不是先--吗？如果先--了，val的值还是栈顶的值吗？


Question: 关于memset初始化内容超过限制问题

其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

你的b只分配了四个字节，而memset是按照字节来算，memset(b,0,8)你这里要设置8个字节的内存，就溢出了；

越界破坏了栈，提示就那个意思  另外编译器怎么排列 a b c 三个变量是不确定的，未必一定是a b c 顺序排列，你可以看对应的汇编代码

越界行为，memset对于非b的区域初始化，其实和赋值是一样的，对于越界很容易导致段错误，数据不正确等结果； 我们的内存有管理机制，是系统的处理的

村子里各家种自家的地，法律上不允许越界，如果都守规矩就能有预定的收获，如果越界了，就可能得不到自己想要的东西

a b c 的内存顺序未必是 abc 或者 cba 编译器按照自己的逻辑 怎么排列好用就怎么排 越界之后 修改的未必是 a c 你检查a c 的值毫无意义

calloc free 管理的内存，术语称作堆 用个不恰当的比方来形容堆的话 你可以把他想象为飞机或者火车的座位！callo 和 free就是售票程序 并不是calloc创造了指针，free不是销毁了指针。 而是类似于售票程序只是给你一张票。并且在系统中标记那个座位有人定了 如果中途有人改签之类的情况，free只是把那个座位重新标记为可以再给别人 所以，你用calloc订购一个座位，如果这个航班乘员比较少。那么你也可以做到别的座位上。

用gcc试的可以通过，而且没有那段提示。 用vc debug试的遇到断言退出 用vc release试的没错误提示  可能就是某些gcc版本发现b越界赋值给你一句警告。

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。

函数内的局部变量是放在stack里的，因为栈是向下增长的，在进入一个函数之前，会先把参数和下一步要执行的指令地址（通过call实现）压栈，在函数的入口会把ebp压栈，并把esp赋值给ebp，在函数返回的时候，将ebp值赋给esp，pop先前栈内的上级函数栈的基地址给ebp，恢复原栈基址，然后把调用函数之前的压入栈的指令地址pop出来（通过ret实现）。 栈是由高往低增长的，而数组的存储是由低位往高位存的，如果越界的话，会把当前函数的ebp和下一跳的指令地址覆盖掉，如果覆盖了当前函数的ebp，那么在恢复的时候esp就不能指向正确的地方，从而导致未可知的情况，如果下一跳的地址也被覆盖掉，那么肯定会导致crash。

引用 5 楼 jianwufeng26 的回复:[quote=引用 3 楼 qq_36409192 的回复:] [quote=引用 2 楼 jianwufeng26 的回复:] [quote=引用 1 楼 qq_36409192 的回复:] memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误[/quote] http://blog.csdn.net/xyzso1z/article/details/70333085?locationNum=1&fps=1[/quote] 看了，还是没明白，  memset(b,0,8)应该是把b之后的4字节也初始化为0了；a,b,c正常输出了，但为什么会出现stack smashing detected   这个错误呢？  [/quote] 正常输出并不等于没有错误。就像scanf输入一样，并不会检查是否溢出了。

引用 3 楼 qq_36409192 的回复:[quote=引用 2 楼 jianwufeng26 的回复:] [quote=引用 1 楼 qq_36409192 的回复:] memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误[/quote] http://blog.csdn.net/xyzso1z/article/details/70333085?locationNum=1&fps=1[/quote] 看了，还是没明白，  memset(b,0,8)应该是把b之后的4字节也初始化为0了；a,b,c正常输出了，但为什么会出现stack smashing detected   这个错误呢？

memset(b,0,8);  是将数组b的内容全部赋值为0，又因为数组b只开辟了四个字节的空间，而你却把从b[o]开始以后的8个字节全部赋值为0，后面的四个字节的空间不属于你的，则会栈溢出操作

引用 2 楼 jianwufeng26 的回复:[quote=引用 1 楼 qq_36409192 的回复:] memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误[/quote] http://blog.csdn.net/xyzso1z/article/details/70333085?locationNum=1&fps=1

引用 1 楼 qq_36409192 的回复:memset(buffer, 0, sizeof(buffer))  把你的8改一下，改成sizeof(b)。 嗯，我知道应该这么改，我只是不明白出错的机理，想知道为什么会产生这个错误


Question: c语言程序调试结果为什么会和运行结果不一致

引用 7 楼 zhao4zhong1 的回复:num不初始化，里面有对应内存中以前的值。  恩，非常感谢。

引用 6 楼 user-3 的回复:[quote=引用 4 楼 a501900309 的回复:] [quote=引用 2 楼 user-3 的回复:] char num[M] = {0}; 初始化一下字符串数组 /******  确实就正常了，非常感谢。 但是为什么用这 for(i = 0;i < M;i++) if(!(num[i] >= '0' && num[i] <= '9')) num[i] = 0; 把非‘0’到‘9’的值改为0，则会出现运行和调试不一致的问题呀？[/quote]因为你没有初始化，所以num里边的值不确定，debug模式下和release模式对未初始化的变量处理不一样，所以要养成初始化变量的好习惯。顺便说一下，如果像我那样初始化了，第一个for循环就没有啥必要了。[/quote]   恩恩，非常感谢

#include <stdio.h> #include <string.h>  #define M 50  int main() {     char num[M];     //int n,mask,t,d,index,count,i;     int i;     int sum = 0;      scanf("%s", num);     for(i = 0; i < strlen(num); i++)         if(!(num[i] >= '0' && num[i] <= '9'))             num[i] = 0;     // puts(num);     for(i = 0;i < M;i++){         if(num[i] >= '0'&&num[i] <='9' )             sum += (num[i] - '0');     }     printf("%d\n",sum);     return 0; } 输入的不到M（50）个，后面的数据都是随机值。所以第一个for循环的判断条件用strlen计算一下输入的字符个数；scanf会自动加上字符串的结束标记'\0'（值等价与0） 若输入的非'0'~'9'，num[i] = 0;0和'\0'是一样的，所以后面puts调试的输出遇到'\0'结束输出，调试的和sum 的结果不一致。

num不初始化，里面有对应内存中以前的值。

引用 4 楼 a501900309 的回复:[quote=引用 2 楼 user-3 的回复:] char num[M] = {0}; 初始化一下字符串数组 /******  确实就正常了，非常感谢。 但是为什么用这 for(i = 0;i < M;i++) if(!(num[i] >= '0' && num[i] <= '9')) num[i] = 0; 把非‘0’到‘9’的值改为0，则会出现运行和调试不一致的问题呀？[/quote]因为你没有初始化，所以num里边的值不确定，debug模式下和release模式对未初始化的变量处理不一样，所以要养成初始化变量的好习惯。顺便说一下，如果像我那样初始化了，第一个for循环就没有啥必要了。

引用 3 楼 zhao4zhong1 的回复:其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  我还是小白，前面一句是看懂了，但能不能麻烦结合具体语句解释下，比如哪条语句会让计算机因为什么原因而出错了，我

引用 2 楼 user-3 的回复:char num[M] = {0}; 初始化一下字符串数组 /******  确实就正常了，非常感谢。 但是为什么用这 for(i = 0;i < M;i++) if(!(num[i] >= '0' && num[i] <= '9')) num[i] = 0; 把非‘0’到‘9’的值改为0，则会出现运行和调试不一致的问题呀？

char num[M] = {0}; 初始化一下字符串数组

#include<stdio.h> #define M 50 //int vmask(int n); int main(){ //char str[][10] ={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"}; char num[M]; int n,mask,t,d,index,count,i; int sum = 0; for(i = 0;i < M;i++)num[i] = 0; scanf("%s",num); //	puts(num); for(i = 0;i < M;i++){ if(num[i] >= '0'&&num[i] <='9' ) sum += (num[i] - '0');  } printf("%d\n",sum); return 0; }


Question: c语言多重for循环如何优化

nested for loops can be reduced to one level. 只要循环之间没有额外语句，多少重的循环都可以写成一层的，但是未必一定会更有效，得看情况。

试了一下，应该可以把上面的四重循环改成二重循环，如下：  	int h = height - sw - sw, w = width - sw - sw,num= (sw * 2 + 1); 	for (a = 0; a < h * w; a++) { 		i = a / h + sw; 		j = a % h + sw; 		sum = 0; 		calGaussCoef(pGaussCoef); 		for (b = 0; b < num*num; b++) { 			m = b / num - sw; 			n = b %num- sw; 			indexI = (i + m) * width + j + n; 			indexG = (m + sw) * slen + n + sw; 			sum += pSrcImg[indexI] * pGaussCoef[indexG]; 		} 		pDstImg[i * width + j] = (unsigned char)(sum); 	}

先讲一下你的代码准备实现什么效果

代码上看  1 calGaussCoef(pGaussCoef);  这个是多次重复调用，完全可以扔到循环外面去  2 最内层循环里面的这两句 indexI = (i+m)*width + j+n; indexG = (m+sw)*slen + n+sw; 乘法完全可以用加法来替代掉  从算法上看， 从一个大图片上取sw*sw的一个小正方形里面的所有像素 和 一个固定的系数矩阵挨个乘法后求和后放到一个新的图像数据去 这个乘法的过程没有重复发生的地方， 算法就无法优化  能优化的是可以考虑利用现代计算机多核的特性做并行计算了， 上述乘法之间的数据彼此之间互不影响，并行计算是可行的

循环切换类似函数调用，会涉及到出栈/入栈操作，所以可以通过减少循环切换达到优化 大循环在里面，小循环在外面，减少切换次数 把不是重复操作的指令放到循环外面，减少循环体本身开销

引用 1 楼 user-10 的回复:两层循环也叫多层？ 废话流

过早的优化是万恶之源！  无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

引用 12 楼 optimistiveho 的回复:引用 9楼bravery36 的回复:四层就四层，也没有什么大不了的，而且只有优化算法才能减少运算量，这种代码没有什么好优化的，你能想到的编译器早就做了。但我们老师说还能优化 能 普通变量 改为 寄存器变量 i++ 改为 ++i 换一下内外层循环 简单函数改宏函数  加减乘除计算改用位运算 但都意义不大  这种代码 不改逻辑  真想优化是 自己动手嵌入汇编

优化的策略是：内大外小，即循环次数是内层大，外层小；

优化的策略是：内大外小，即循环次数是内存大，外层小； http://blog.csdn.net/caolipeng_918/article/details/38453761

引用 6楼lin5161678 的回复:[quote=引用 5 楼 optimistiveho 的回复:] [quote=引用 4楼ckc 的回复:]把外层可以计算的尽可能放到外层，减少在内层的运算， 比如indexI = (i+m)*width + j+n; 就可以把 (i+m)*width + j 放到一个临时变量里，在外层就计算好，这样在n循环的时候就只计算 indexl=临时变量+n 不过这个是小技巧，有些编译器也许会帮你处理过了先谢谢，如果将两个for变成用一个for和一个if来判断行不行呢，怎么样改[/quote]只调整循环层次没意义 影响效率的是循环次数 没办法降低循环次数 考虑修改循环层数  大部分是炫技游戏[/quote]大神，要是我把去掉第四层的话可以吗

引用 1 楼 qq_36409192 的回复:两层循环也叫多层？仔细看是四层  ps 没缩进是楼主的问题了

引用 5 楼 optimistiveho 的回复:[quote=引用 4楼ckc 的回复:]把外层可以计算的尽可能放到外层，减少在内层的运算， 比如indexI = (i+m)*width + j+n; 就可以把 (i+m)*width + j 放到一个临时变量里，在外层就计算好，这样在n循环的时候就只计算 indexl=临时变量+n 不过这个是小技巧，有些编译器也许会帮你处理过了先谢谢，如果将两个for变成用一个for和一个if来判断行不行呢，怎么样改[/quote]只调整循环层次没意义 影响效率的是循环次数 没办法降低循环次数 考虑修改循环层数  大部分是炫技游戏

引用 4楼ckc 的回复:把外层可以计算的尽可能放到外层，减少在内层的运算， 比如indexI = (i+m)*width + j+n; 就可以把 (i+m)*width + j 放到一个临时变量里，在外层就计算好，这样在n循环的时候就只计算 indexl=临时变量+n 不过这个是小技巧，有些编译器也许会帮你处理过了先谢谢，如果将两个for变成用一个for和一个if来判断行不行呢，怎么样改

有没有大神帮忙

引用 1楼user-10 的回复:两层循环也叫多层？然后呢，怎么优化

两层循环也叫多层？


Question: 麻烦c语言老师们解惑

主要是取模运算，是得到余数。 另外， 如果不取模，某个数的阶层已经大于factorial的取值范围了，取模能够保证数据的值不越界

即factorial = (factorial * j % MOD); 从25为0； 感觉您自己应该已经找到答案了呀

因为24的各级数之和是94313，之后所有数取模值为0，即25! % 1000000 = 0，之后所有的都一样


Question: 求教能否在允许阶段生成宏？

宏是条件编译阶段就已经确定了， 它不能在运行的时候再区分运行那个分支。 如果在运行的时候来确定使用哪个分支，建议使用全局变量。

不行的，　宏只能用常量的，不能用变量赋值。 l但宏可以在编译时指定宏的值，如：　gcc test.c -Ddirc=0x7788    // 相当于在源码里"#define dirc 0x7788"


Question: 关于C语言提取文本文件特定内容的方法，求大佬指教

仅供参考：//NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %31[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8

引用 3 楼 qq_28163175 的回复:[quote=引用 2 楼 user-2 的回复:] 自己动动手把行号清了吧， Linux中用命令行运行 ./a.out 北极熊。    1 #include <stdio.h>   2 #include <string.h>   3    4 int main(int argc, char *argv[])   5 {   6     char buf[1024];   7     char *pstr;   8     int offset = 0;   9     FILE *fp = NULL;  10       11     if (argc < 2) {  12         printf("Useage: [name] \n");  13         return -1;  14     }     15       16     fp = fopen("./2.txt", "r");  17     if (fp == NULL) {  18         printf("open file error!\n");  19         return -1;  20     }     21     while (fgets(buf, sizeof(buf), fp) != NULL) {  22         if (strstr(buf, argv[1]) != NULL) {  23             printf("%s", buf);  24         }     25     }     26       27     fclose(fp);  28       29     return 0;  30 }大佬 ，这个我也能打印出来，但是不符合题目要求啊[/quote]  啥意思？你是想把所有信息输出为一行？那每次读的一行数据把最后一个换行替换掉啊。最后再补个换行。

引用 2 楼 user-2 的回复:自己动动手把行号清了吧， Linux中用命令行运行 ./a.out 北极熊。    1 #include <stdio.h>   2 #include <string.h>   3    4 int main(int argc, char *argv[])   5 {   6     char buf[1024];   7     char *pstr;   8     int offset = 0;   9     FILE *fp = NULL;  10       11     if (argc < 2) {  12         printf("Useage: [name] \n");  13         return -1;  14     }     15       16     fp = fopen("./2.txt", "r");  17     if (fp == NULL) {  18         printf("open file error!\n");  19         return -1;  20     }     21     while (fgets(buf, sizeof(buf), fp) != NULL) {  22         if (strstr(buf, argv[1]) != NULL) {  23             printf("%s", buf);  24         }     25     }     26       27     fclose(fp);  28       29     return 0;  30 }大佬 ，这个我也能打印出来，但是不符合题目要求啊

求大佬指教，自己C语言基础太差。。求指教!


Question: 指针函数怎么释放calloc? 为什么calloc创建后可以放入比创建空间更多的内容？

其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

calloc free 管理的内存，术语称作堆 用个不恰当的比方来形容堆的话 你可以把他想象为飞机或者火车的座位！callo 和 free就是售票程序 并不是calloc创造了指针，free不是销毁了指针。 而是类似于售票程序只是给你一张票。并且在系统中标记那个座位有人定了 如果中途有人改签之类的情况，free只是把那个座位重新标记为可以再给别人 所以，你用calloc订购一个座位，如果这个航班乘员比较少。那么你也可以做到别的座位上。

calloc 申请的内存用 free 释放  越界没出错只能证明运气好，不能说明什么

首先，在main函数里这样释放是可以，因为释放calloc申请的空间，只需要将申请的地址传递给free形参即可释放。strtime返回的即申请的空间的首地址。 其次，calloc申请2个字节，很明显不够，":0%d"至少要用3个字节才能存放，再加上字符串的'\0'也要占用一个字节的空间，所以至少需要4个，这样申请会导致存放的数据溢出，有可能会出现多错误或覆盖后面的数据或数据被覆盖； 建议申请足够使用的空间；

":0%d"这不是三个字节，这是3个字符（至少，因为后边的time不知道是几位数） 编译器不管放不放的下，放多了可能会破坏其他数据，存在安全隐患 动态申请的内存，需要手动释放（放弃控制权）的，否则直到程序退出会一直占用着系统空间


Question: 发现个有趣的现象，关于gcc -O编译优化和多线程资源共享的问题

据我所知，在多核CPU环境下，即使寄存器，仍需考虑线程安全。

-O 优化会使去掉代码段某些内容。

引用 1 楼 zhao4zhong1 的回复:据我所知，在多核CPU环境下，即使寄存器，仍需考虑线程安全。 当然此时总比内存在概率上更不易发生访问冲突。

这个问题我也遇到过，加了-O后多线程的冲突减少，但是不知道原因呢……关注关注


Question: 大哥帮看看

Windows: 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  Linux： 进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

Junly→July

理解和讨论之前请先学会如何观察！  //char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

搜“C语言 函数指针”

没有看懂   关注两性健康 热点资讯

#include <stdio.h>  char y(char *p[],int x);  int main(void) {     char *e[12]={"Jan","Feb","Mar","Apr","May","June","July","Aug","Sep","Oct","Nov","Dec"};     int n;     char (*l)(char**, int);     l = y;     scanf("%d",&n);     l(e, n);      return 0; } char y(char *p[],int x) {     printf("%s %d\n",*(p+x+1),x);     return 0; } 定义的函数指针，与函数y的类型不匹配。首先需要明白，函数指针是指向函数的指针，那么定义的函数指针l不能指向e，因为e是一个字符指针数组。注意名称都不一样的。 另外，定义的函数指针l的参数类型也不匹配。需要定义成 char (*l)(char **, int);因为函数y的形参是char**类型的。 另外，建议再对上面的代码做一些优化：如下， #include <stdio.h>  int print_month_name(char **p,int x);  int main(void) {     char *e[12] = {"Jan", "Feb", "Mar", "Apr", "May",         "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"};     int n;     int (*pfunc)(char**, int);      pfunc = print_month_name;      scanf("%d", &n);     pfunc(e, n);      return 0; } int print_month_name(char **p, int x) {     if (x > 12 || x < 0) {         printf("Input error!\n");         return 0;     }     printf("%s %d\n",*(p + x - 1), x);     return 0; } 加上对x的判断，防止输入的数据导致读取e的元素越界，提示段错误；


int main() { 	struct node *head = (struct node *)malloc(sizeof(struct node));; 	head->next = NULL; 	head->value = 0; 	 	/*for (int n = 7; n > 0; --n)*/ 		push(&head, 7); 		push(&head, 5); 		push(&head, 4); 		print_list(&head);    void push(struct node* *head_ref, int value)           //带头结点的 { 	struct node *new_node = (struct node *)malloc(sizeof(struct node)); 	new_node->value = value; 	if ((*head_ref)->next== NULL) 	{ 	    (*head_ref)->next = new_node; 		new_node->next = NULL; 		return; 	} 	new_node->next = (*head_ref)->next; 	(*head_ref)->next = new_node; 	 }    void print_list(struct node **head) { 	for (struct node *curr = (*head)->next; curr != NULL; curr = curr->next) 		printf("%d ", curr->value); }

主函数 中  head是NULL，之后调用push(&head, n);传入head的地址  push函数中，new_node->next = (*head_ref)->next;，这里head_ref实际就是head的地址，(*head_ref)为NULL  (*head_ref)->next; 访问空指针，故会导致崩溃

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

#include <stdio.h> #include <stdlib.h>  struct node {     int value;     struct node *next; };  void push(struct node **head_ref, int value);  void print_list(struct node *head);  void reverse(struct node **head_ref);  void reverse_with_recursion(struct node **head_ref);  int main() {     struct node *head = NULL;     int n;      head = (struct node *)malloc(sizeof(struct node));     if (!head)         return -1;     head->next = NULL;     for (n = 7; n > 0; --n)         push(&head, n);     print_list(head);     reverse(&head);     printf("after reverse: \n");     print_list(head);      reverse_with_recursion(&head);     print_list(head);      return 0; }  void push(struct node **head_ref, int value) {     struct node *new_node = (struct node *)malloc(sizeof(struct node));     new_node->value = value;     new_node->next = (*head_ref)->next;     (*head_ref)->next = new_node;    /* 将新节点插入头节点之后*/ }  void print_list(struct node *head) {     struct node *curr;     for (curr = head; curr != NULL; curr = curr->next)         printf("%d ", curr->value);     putchar(10); }  void reverse(struct node **head_ref) {     struct node *prev = NULL;     struct node *curr = *head_ref;     while (curr != NULL) {         struct node *next = curr->next;         curr->next = prev;         prev = curr;         curr = next;     }     *head_ref = prev; }  void reverse_with_recursion(struct node **head_ref) {     struct node *first = *head_ref;     struct node *rest = (*head_ref)->next;     if (rest == NULL)         return;     reverse_with_recursion(&rest);     first->next->next = first;     first->next = NULL;     *head_ref = rest; }  在push函数里，传入的head是指向NULL，所以若对(*head_ref)->next引用next必然会导致段错误； 既然是定义带哨兵的链表，先在main函数里定义哨兵节点，并初始化next指针。

struct node *new_node =（struct node *） malloc(sizeof(struct node));  malloc函数默认返回值为void*  然后编译就没有问题了


Question: C#如何调用dll（C语言）中全局变量

我就喜欢教听话的乖孩纸。

引用 5 楼 zhao4zhong1 的回复:不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？ 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话，文本文件的格式问题可参考json或xml  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！  谢谢5L dalao给的建议，两种语言互调对我来说确实是复杂且易出错的傻事，根据5L dalao的意见，我决定采用文本输入输出，直接调用C的exe文件来运行，这样简单很多，而且修改也方便。 也谢谢其他dalao的回答，让我知道了动态库其实就是函数库的基本知识。感叹一句，不是计算机专业的学生编程困难真是多多！不过还是谢谢大家的热心回答！

建议还是使用函数比较合适，从模块化和便于维护代码的角度上考虑，建议定义函数。

在c中把全局变量的读写封装成函数 c#通过P/Invoke来调用函数

建议采用函数封装的方式实现，动态库其实就是函数库，主要提供函数的封装。全局变量可以通过函数的接口的方式提供。

在你需要调用的源文件中加 extern double temperature

在你需要调用的源文件中加 extern double temperature


Question: 能不能在if语句中定义宏

引用 8 楼 qazaq408 的回复:[quote=引用 7 楼 cfjtaishan 的回复:] if else是需要在函数体里才能使用的，独立函数体外，可以考虑使用条件编译。#ifdef #else #endif 这样的操作是否满足你的要求： #include <stdio.h>    int main(void) {     int flag = 0;  #if flag == 1 #define VAR #else #define HOR #endif   #ifdef VAR     printf("Hello!\n"); #else     printf("World\n"); #endif     return 0; } 谢谢  我还想顺便问下，在宏定义是如果 #if 的条件是个枚举值 #if OS == QType::Window 然后编译的时候说 error: token "::" is not valid in preprocessor expressions 是不是预编译里不能包含:: 这个符号？[/quote] 在C语言里没有遇到过这个符号，C++会有。

引用 7 楼 cfjtaishan 的回复:if else是需要在函数体里才能使用的，独立函数体外，可以考虑使用条件编译。#ifdef #else #endif 这样的操作是否满足你的要求： #include <stdio.h>    int main(void) {     int flag = 0;  #if flag == 1 #define VAR #else #define HOR #endif   #ifdef VAR     printf("Hello!\n"); #else     printf("World\n"); #endif     return 0; } 谢谢  我还想顺便问下，在宏定义是如果 #if 的条件是个枚举值 #if OS == QType::Window 然后编译的时候说 error: token "::" is not valid in preprocessor expressions 是不是预编译里不能包含:: 这个符号？

引用 4 楼 zgp891206 的回复:2楼正解，使用条件编译 通过宏实现条件编译我知道，但我现在的问题是如何通过代码判断生成不同的宏?

引用 4 楼 zgp891206 的回复:2楼正解，使用条件编译 那想楼上这种情况，如何根据不同的代码定义不同的宏？

2楼正解，使用条件编译

引用 2 楼 hdt 的回复:if else 是运行时确定的 #define 是编译期 不能混用 c有条件编译 #ifdef #else #endif 实际情况差不对是这样的，比如c++的Qt里，有个功能是通过区分系统  #ifden Q_OS_WINDOW //调用window的api函数修改系统时间 #endif #ifdef Q_OS LINUX //调用linux的api函数修改系统时间 #endif  这样代码就可以不做修改在不同的系统上编译，运行时调用对应的系统api函数，但这里问题是他的这两个宏是怎么定义的？ 是在前面的代码里有  if(/*判断操作系统类型函数*/ == Window)     #define Q_OS_WINDOW if(/*判断操作系统类型函数*/ == Linux)     #define Q_OS_LINUX  他是用这样的形式么？我现在遇到到类似的情况，我就不知道这两个红Q_OS_WINDOW和Q_OS_LINUX他是通过什么方式定义的？

第一段代码不知道为什么试反色。。。全选可以看见


Question: 初学，请教float数据类型问题。

使用精度更高的double   int main(void) { 	double weight; 	double value; 	weight = 7.00000000001; 	value = 7.00000000004; 	printf("%.12f\n", weight + value); 	if (weight == value) 	{ 		printf("true\n"); 	} 	return 0; }

浮点的不要直接 == 来比较，通常的做法是取差值，然后判断是否在一个已定义好的误差内，小于定义的误差就认为是相等的。

浮点数格式 http://bbs.csdn.net/topics/390676437

直接用float类型是很难做到精确的，因为float有效位是小数点后面6位。需要考虑其他方式，使用double是能够做到更接近，但是也做不到完全的精确。

浮点只能近似保存如果要精度高，要么就提高浮点的长度，比如用double，或者就事先放大倍数，加法后再除去倍数。


Question: 总和固定的多个随机数

引用 1 楼 wanggui2015 的回复:在0-4095之间随机15个数，排序，这15个数将0-4095分为16个区间，取每个区间的范围长度就是你要的16个随机数 多谢，有用！

引用 1 楼 wanggui2015 的回复:在0-4095之间随机15个数，排序，这15个数将0-4095分为16个区间，取每个区间的范围长度就是你要的16个随机数 这个办法也是比较可行的～

仅供参考 #define MAX_NUM 4095		// 总和 #define NUM 16			// 随机数总个数 #define BLOCK 5			// 分的块数，如果觉得随机数不均匀，可以调大块数  int _tmain(int argc, _TCHAR* argv[]) { 	srand((unsigned)time(0)); 	int num = MAX_NUM; 	int numPerBlock = NUM/BLOCK; 	int test = 0;		// 测试随机结果是否正确 	for (int k = 0; k < BLOCK; ++k) 	{ 		int n = MAX_NUM / BLOCK; 		for (int i = 0; i < numPerBlock; ++i) 		{ 			int nTemp = 0; 			if (i == numPerBlock - 1 && NUM%BLOCK == 0) 			{ 				nTemp = n; 			} 			else 				nTemp = rand() % (n - (numPerBlock - i)+1) + 1; 			printf("第%d个= %d\n", k*numPerBlock +i+1, nTemp); 			test += nTemp; 			n -= nTemp; 			num -= nTemp; 		} 	}  	// 处理余下的 	for (int m = 0; m < NUM%BLOCK;++m) 	{ 		int nTemp = 0; 		if (m == NUM%BLOCK - 1) 		{ 			nTemp = num; 		} 		else 			nTemp = rand() % (num  - (NUM%BLOCK -m) + 1) + 1; 		printf("第%d个= %d\n", numPerBlock*BLOCK + m + 1, nTemp); 		test += nTemp; 		num -= nTemp; 	} 	test == MAX_NUM ?printf("随机结果正确！\n"):printf("随机结果有误！\n"); 	return 0; }


Question: 可执行文件加壳的问题

《Windows PE权威指南》 看雪论坛 ……


Question: 请教问什么b的值变为了50

a是b的引用，这两个变量就绑定在一起了，两个值同时改变~

a是b的引用，对a的改变就相当于对b的改变

本质上来说，引用就是指针。 指针定义： int a = 123; int* p = &a; *p = 999 ---------------------- 引用类型 int a = 123; int& r = a; r = 999;  仔细一比较，不难发现，其实引用就是指针。

指针即地址 引用即别名

这是引用，不是指针取址

这是C++相对C而言独有的引用功能，引用即类似C语言里的typedef

int &a = b; 这里a是b的引用  你可以理解成a只是b的一个别名，他们实际是同一个变量  所以修改a 实际就是修改b  具体内容楼主可搜索：引用

int &a = b;  a和b引用了同一块内存地址，修改a的值就等于修改了b的值  建议楼主去看一下C++里面的引用类型


Question: 字符串加密，数据结构

建议使用malloc和realloc，realloc可用于内存空间增加和减少。不论是行不确定，还是列不确定，都可以用realloc增加行数和列数。并且是动态增加和减少。

动态数组 malloc  或者弄个链表


Question: 字符串大小的问题

拙作 http://blog.csdn.net/hou09tian/article/details/69841380，主要说的是strlen与sizeof处理字符数组与字符指针的事情 请多指教

1是数组元素个数，2是char*占的字节数，既sizeof(char *)。sizeof()输出的是类型所占内存的大小。 如果要求字符串的长度，用strlen()，这样的话1和2的输出结果是一样的。

很简单：数据类型不同。 s 是指针变量----char * Test (数组名)是常指针----const char *  常指针就是一个常数，实质就是一个无符号int整数。

数组与指针是两种不同的类型  数组与指针的联系是数组名可以退化为指针  数组作为函数参数时会自动退化为指针  sizeof 指针 得到的是指针的大小（32位程序是4）  sizeof 数组 得到的是数组的大小   如果需要在函数中知道数组的大小，可再添加一个参数，将数组大小传入到函数

第一个是数组，sizeof之后是数组的长度，即元素的个数； 第二个是指针，即形参是一个接收一个地址的指针，sizeof的值是4（32为系统下）。 理论上，数组名也是指针，可以理解成指针常量，因为数组名不能做左值，即不能在赋值号左边；它是指针但是还不能等同于普通指针变量。


Question: 关于GNU C语言中字符串大小的问题

因为参数s是一个指针，虽然实参是数组，但是传递的值，即数组名是一个地址值，传递给形参s（指针）。sizeof一个指针，在32为系统里，所有指针的长度（sizeof)都是占4个字节


Question: 进行链表的合并，运行为啥会出错？

创建链表的函数里，没有将申请的哨兵节点赋值给链表头。因为执行完创建链表后没有得到链表的头节点。建议如下修改： void CreateLinkList(LinkList *L, int n)//前插法创建单链表 {     //int a[6]={1,2,3,4,5};     int i;     LinkList s = NULL;     s = (LinkList)malloc(sizeof(LNode));     s->next = NULL;     *L = s;     for (i = n; i>0; --i)     {         LinkList p = (LinkList)malloc(sizeof(LNode));         //scanf("%d ",p->data);         p->data = i;         p->next = s->next;         s->next = p;     } }

void CreateLinkList(LinkList *L, int n)//前插法创建单链表 {     //int a[6]={1,2,3,4,5};     int i;     LinkList s = NULL;     s = (LinkList)malloc(sizeof(LNode));     s->next = NULL;     *L = s;    /*将哨兵节点赋值给头节点*/     for (i = n; i>0; --i)     {         LinkList p = (LinkList)malloc(sizeof(LNode));         //scanf("%d ",p->data);         p->data = i;         p->next = s->next;         s->next = p;     } }

void CreateLinkList(LinkList *L, int n) { LinkList s; ...... *L=s; }  这样应该可以，你自己调试下

CreateLinkList 有问题  LinkList s = *L; 后面s 又malloc过，已经不指向L了。  你单步调试下，执行完下面这两句la,lb还是野指针 CreateLinkList(&la, 4); CreateLinkList(&lb, 4);

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。


Question: 基于CentOS的SFTP代理程序，C语言编写，有哪位大神可以给个实例吗？

寻找的时候，注意看代码的环境，一般Linux环境下使用的就可以

百度搜相关关键字。


Question: 有没有能用于运动目标检测的AVI格式的视频啊，求大神

引用 1 楼 zhao4zhong1 的回复:使用QQ影音自带的转换工具转换为不压缩的AVI。 不压缩的avi格式是哪种啊，为啥我这错误一直是无法找到解压装置解压视频流？谢谢那

引用 1 楼 zhao4zhong1 的回复:使用QQ影音自带的转换工具转换为不压缩的AVI。 我试一下，谢谢！

使用QQ影音自带的转换工具转换为不压缩的AVI。

安装QQ影音后没准所需的视频解码器也随之安装了。


Question: 为什么超过后面几个不能正常排序？

引用 4 楼 paschen 的回复:区别malloc、realloc 与 calloc 参数上的差异  改成：  psTemp = realloc(pS, capacity * sizeof(char*)) 非常感谢哦！

引用 3 楼 cfjtaishan 的回复:#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h>  #define BUF_LEN 100                    // Length of input buffer #define COUNT        5                 // Initial number of strings  int main(void) {     char buf[BUF_LEN];                  // Input buffer     size_t str_count = 0;               // Current string count     size_t capacity = COUNT;            // Current maximum number of strings     char **pS = (char **)calloc(capacity, sizeof(char*));    // Pointers to strings     char** psTemp = NULL;               // Temporary pointer to pointer to char     char* pTemp = NULL;                 // Temporary pointer to char     size_t str_len = 0;                 // Length of a string     bool sorted = false;                // Indicated when strings are sorted      printf("Enter strings to be sorted, one per line. Press Enter to end:\n");     while(fgets(buf, BUF_LEN, stdin) != NULL)     {         if(str_count == capacity)         {             capacity += capacity/4;             printf("%d\n", capacity);             if(!(psTemp = (char **)realloc(pS, capacity * sizeof(char *))))                 return 1;             pS = psTemp;         }         str_len = strlen(buf) + 1;         if(!(pS[str_count] = (char *)malloc(str_len)))             return 2;         strcpy(pS[str_count++], buf);     }      int i;     while(!sorted)     {         sorted = true;         for(i = 0 ; i < str_count - 1 ; ++i)             if(strcmp(pS[i], pS[i + 1]) > 0)             {                 sorted = false;                 pTemp= pS[i];                 pS[i] = pS[i + 1];                 pS[i + 1]  = pTemp;             }     }      // Output the sorted strings     printf("Your input sorted in ascending sequence is:\n\n");     for(i = 0 ; i < str_count ; ++i)     {         printf("%s", pS[i]);         free(pS[i]);         pS[i] = NULL;     }     free(pS);     pS = NULL;      return 0; }  realloc的地方出了问题，确切的说是realloc第二个参数有问题，第二个参数是变更之后的空间大小，即原来的空间加上新的空间（若是增加）的大小；所以，需要的是capacity * sizeof(char *)的大小；如果只是capacity那么相当于空间缩小了，所以再输入字符串就越界了。 另外，判断fges的返回值，建议和NULL判断。如何退出循环输入呢？可以使用ctrl+d（Linux下），或ctrl+z（windows下）。非常感谢，这个失误我检查了很久都没有发现！ 谢谢

引用 1 楼 coverlo 的回复: 输入到第六个就会报错， 是我指针哪里弄错了吗？


Question: 本人萌新求大佬解答下

为什么可以存放多个字符串，因为你每次输入的字符串都是放在了同一缓存里（数组a），即第二次的输入将第一次的输入覆盖了。其实，是一个缓存循环利用了。

谢谢啦大佬哈

引用 4 楼 androidioskl 的回复:哪也不对啊如果覆盖掉了 呢么我第一次输入abcd 地二次输入abc那第二次也是abcd但是第二次等于abca。 第二次输入abc只覆盖掉第一次abc但是d没有覆盖掉啊  上面的描述是你实际测试中得到的结果，还是你的想法。%s输入会自动加上'\0'，这个你是否考虑进去。 scanf，%s输入会将字符串结束标记'\0'加上。若是以%s输出，你是看不到上一次残留在缓存里的（数组a里）的数据的。除非，你一个个的输出，按照%c。 第一次输入abcd,第二次输入abc，那么，在第二次的abc后面会加上一个'\0'一样将第一次的'd'字符覆盖。当然，第一次输入的abcd后面也会加上一个'\0'

百度搜索相关关键字，弄清楚scanf输入的机制。

兄弟，数组名a是一个地址，你给printf的第二参数是一个地址。 你怎样操作相当于对数组a进行了9次写入（当然你实际上只写入了6次）。 scanf（）函数遇到空格，tab,回车就会停止读入。 所以第一次读入的是ghjgk， 并且打印了ghjgk 第二次读入的是gjhgj 并打印了gjhgj，由于没有换行符也没有空格，所以就直接在ghjgk后面打印 第三次读入的是gkgk 并在第二次打印的结果后面继续打印。 。。。 以此类推，最后所有的打印都写在一行上， 所以给了你以此读取所有的错觉。  我也是刚学，不知道对不对


Question: 帮忙看看，这段代码哪里错了

引用 1 楼 自信男孩的回复:# include <stdio.h> # include <malloc.h> # include <stdlib.h> # include <time.h>  typedef struct Node {     int data;     struct Node * pNext; }NODE, *PNODE;  void createlist(PNODE *L, int n) {     PNODE p,r;     int i;      srand(time(0));     *L = (PNODE)malloc(sizeof(NODE));     r = *L;     r->pNext = NULL;     for(i=0; i<n; ++i)     {         p = (PNODE)malloc(sizeof(NODE));         p->data = rand()%100+1;         p->pNext = r->pNext;         r->pNext = p;      } }  void traversal_list(PNODE pHead) {     PNODE p = NULL;     p = pHead->pNext;     while (p) {         printf("%d ", p->data);         p = p->pNext;     }     printf("\n"); }   int main(void) {     PNODE pHead = NULL;     createlist(&pHead,5);     traversal_list(pHead);      return 0; }  这是一个带有岗哨的单链表，问题主要是出在头节点（岗哨节点）没有初始化pNext的值，即没有执行 r->pNext = NULL; //或者 (*L)->next = NULL; 详见上面的代码；如果没有这一步的初始化，那么输出的时候就不能判断结束即找不到NULL； 上面输出时，我去掉了NULL != p,改成while(p)因为p为NULL时，即为假。while 退出 谢谢了


Question: 关于共享内存和队列的问题 求大神提供一个思路

再供参考： Microsoft SDK\samples\winbase\SharedMem\Consumer.Cpp Microsoft SDK\samples\winbase\SharedMem\Makefile Microsoft SDK\samples\winbase\SharedMem\Producer.Cpp Microsoft SDK\samples\winbase\SharedMem\Queue.h Microsoft SDK\samples\winbase\SharedMem\ReadMe.Txt Microsoft SDK\samples\winbase\SharedMem\Common.h

仅供参考：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef _MSC_VER     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _MSC_VER     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef _MSC_VER void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX; CRITICAL_SECTION cs_BBB; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int main() { #ifdef _MSC_VER     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX);     InitializeCriticalSection(&cs_BBB); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef _MSC_VER     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef _MSC_VER     DeleteCriticalSection(&cs_BBB);     DeleteCriticalSection(&cs_HEX);     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }

引用 2 楼 zhu339111520 的回复:std::atomic  不好意思 没写清楚 c语言实现

std::atomic

很多进程间通讯的办法，比如可以使用内存映射  http://blog.csdn.net/wangkechuang/article/details/7728365

共享内存和队列，注意做到互斥，所以需要用到互斥锁，以达到进程间通信时的同步。


Question: devc++求解

建议加上一些编译选项（比如一些比较严格的编译选项），看看是否有warning?，或者隐式声明之类的。

扔掉dev c++ 换 Visual C++ 2010 Express简体中文版http://pan.baidu.com/s/1bnwRVLt

我不信，编译器会自动给你做一些事情，但是不可能去掉所有的头文件都可以运行，这些头文件肯定满足一些特定的规律，比如在项目中、在根目录、在共享目录等等，但是你写一个头文件把它放到桌面上，他肯定不会自动引用


Question: 请教一下关于malloc和free的问题

引用 3 楼 qq_34287840 的回复:[quote=引用 1 楼 shihengzhen101 的回复:] malloc和free应该是对应的，但是这个free可以放在程序的最后，如果你需要不断的malloc那么堆是会“满”，到时候会出现申请不到内存的情况，当然如果是程序的最后free不写也没什么问题，但写上时最规范的 我想问下如果满了的话 是会提示出现断点吗？[/quote] 不会出现断点，但是当你尝试向heap分配内存时，如果内存空间不够，你的指针将会是NULL，当你尝试通过该指针对内存空间进行读写时，就会报错，这是running error；所以，良好的编程习惯是，每次用malloc/new申请空间后，都要检测下指针是不是NULL，如果是直接LOG报错！别给自己留坑！

按规则来说，每malloc一块memory空间，都需要用free去释放它，但是具体在哪里释放，什么时候释放是根据你的设计走的！你在addNode函数中malloc了一块空间，如果函数返回后这个空间不想用了（或者说addNode函数没有把该空间的指针传递出去），就一定要在addNode函数中free它，不然肯定内存泄漏！如果你在addNode外还想用到这个空间，那么addNode中肯定不能free该空间，等到你程序到了不再会使用到这块空间的时候再去free它；

首先来看看malloc的声明，void *malloc(unsigned int num_bytes);参数是你从堆中申请内存的大小，你不断的增加节点的时候，堆内存是一直在增加的，如果溢出了，程序是直接奔溃的，不会给你任何提示。在专业的开发中有专门的工具来检测程序中是否有申请的内存没有释放的。这就是C语言的精髓所在，内存的管理在于程序员来控制。当然没个几年经验是hold不住的。

你从村委会申请承包的地，不种了最好去注销了，以便让别人来种，而不是不吭声

引用 3 楼 qq_34287840 的回复:[quote=引用 1 楼 shihengzhen101 的回复:] malloc和free应该是对应的，但是这个free可以放在程序的最后，如果你需要不断的malloc那么堆是会“满”，到时候会出现申请不到内存的情况，当然如果是程序的最后free不写也没什么问题，但写上时最规范的 我想问下如果满了的话 是会提示出现断点吗？[/quote] 不会，一个程序可用的内存是有限的，操作系统负责分配，成功分配到内存malloc会返回内存的指针，否则应该会返回NULL，所以对malloc的返回值做判断即可

引用 3 楼 qq_34287840 的回复:[quote=引用 1 楼 shihengzhen101 的回复:] malloc和free应该是对应的，但是这个free可以放在程序的最后，如果你需要不断的malloc那么堆是会“满”，到时候会出现申请不到内存的情况，当然如果是程序的最后free不写也没什么问题，但写上时最规范的 我想问下如果满了的话 是会提示出现断点吗？[/quote] 首先malloc是在堆上申请的空间，堆上的空间相对是比较富裕的，比栈大的太多了。一般不会出现申请不到的情况，除非你一直不停的申请，并且中间也不释放，每次申请的也挺多。至于你将malloc申请之后的加入到链表这是正常的操作，只要你加入到链表的链表头能够找到，那么在程序的最后或者链表不需要的时候将其一起释放即可。 堆上的空间相对栈是宽裕的，如果申请多的内存空间，建议在堆上

感谢大家的回复！感激不尽

引用 1 楼 shihengzhen101 的回复:malloc和free应该是对应的，但是这个free可以放在程序的最后，如果你需要不断的malloc那么堆是会“满”，到时候会出现申请不到内存的情况，当然如果是程序的最后free不写也没什么问题，但写上时最规范的 我想问下如果满了的话 是会提示出现断点吗？

这个问题就相当于一个故事有开头，你觉得要不要个结尾呢？


Question: 求大神指导关于malloc函数的问题

引用 1 楼 user-2 的回复:我严重怀疑是你的堆满了，内存泄露了。。。 没有很有力的证据证明是堆满，内存泄漏了，因为从程序里来看，结构体的大小一定大于4个字节，但是申请空间时，只申请4个字节，对结构体里的元素赋值时，自然是内存越界了，导致非法地址访问。

引用 4 楼 cfjtaishan 的回复:PThrTreeNode s = (PThrTreeNode)malloc(sizeof(PThrTreeNode)); 这句有问题，malloc的参数是申请的字节数，sizeof得到是4个字节吧（32位系统），因为sizeof是指针。实际上应该是结构体的大小，但是申请4个字节长度（指针长度）没有返回NULL，所以判断是否申请成功是不能检查出来的。 PThrTreeNode s = (PThrTreeNode)malloc(sizeof(ThrTree)); 是我大意了，我写成这样就不会越界了，感谢前辈！！！

引用 4 楼 cfjtaishan 的回复:PThrTreeNode s = (PThrTreeNode)malloc(sizeof(PThrTreeNode)); 这句有问题，malloc的参数是申请的字节数，sizeof得到是4个字节吧（32位系统），因为sizeof是指针。实际上应该是结构体的大小，但是申请4个字节长度（指针长度）没有返回NULL，所以判断是否申请成功是不能检查出来的。 [img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/54.gif] [/img]那我想请问下我该如何申请呢？是直接申请结构体大小的空间吗？谢谢！

我还发现只要用release模式不用debug。。。就没问题了。。有人能告诉我是为啥吗

引用 1 楼 user-2 的回复:我严重怀疑是你的堆满了，内存泄露了。。。 怎样才能判断堆有没有满呢。。本人初学，请大神赐教

我严重怀疑是你的堆满了，内存泄露了。。。


Question: 问题可能有些简单，但还是请各位大神抽空帮忙看一下/(ㄒoㄒ)/~~这个要怎么改

引用 楼主 qq_38748751 的回复:C代码： #include<stdio.h> #include<string.h> #include<stdlib.h>  void main() { 	char* inputcode = ""; 	int judge; 	while(1) 	{ 		printf("请输入abc：\n"); 		scanf("%c",&inputcode);  		if(strcmp(inputcode,"abc")==0) 			judge=1; 		else 			judge=0;  		if(judge==1) 			break;  	} 	printf("login\n"); } 附图：  引用 楼主 qq_38748751 的回复:C代码： #include<stdio.h> #include<string.h> #include<stdlib.h>  void main() { 	char* inputcode = ""; 	int judge; 	while(1) 	{ 		printf("请输入abc：\n"); 		scanf("%c",&inputcode);  		if(strcmp(inputcode,"abc")==0) 			judge=1; 		else 			judge=0;  		if(judge==1) 			break;  	} 	printf("login\n"); } 附图： 谢谢

#include<stdio.h> #include<string.h> #include<stdlib.h>  int main() {     char inputcode[32] = "";     int judge;     while(1)     {         printf("请输入abc：\n");         scanf("%s", inputcode);          if(strcmp(inputcode,"abc")==0)             judge=1;         else             judge=0;          if(judge == 1)             break;      }     printf("login\n");      return 0; } inputcode要定义成字符数组（栈上申请空间）或通过malloc申请空间（堆上）； 对于字符串输入，要使用%s


Question: c语言static 问题

可以参考一下这个博文http://blog.csdn.net/libing403/article/details/72934198

了解一下c语言存储类别，可以去看看这个资料http://blog.csdn.net/libing403/article/details/72934528

引用 12 楼 lin5161678 的回复:引用 11 楼 xuhaoee 的回复:C标准规定，全局变量和静态变量都在编译时分配空间，并放在数据段中，且分配的空间是连续的！所以你的static变量才会在全局变量后面，你数组越界，不小心修改了static变量空间的数据，所以才会出现这样的问题！标准规定中 没说分配在数据段 也没说连续 不了解不要乱说 哈哈，兄台说的是，这肯定不是C的标准，而是某一版本编译器自己的行为，不同编译器可能处理不同，多谢提醒~

引用 15 楼 tomsoft 的回复:[quote=引用 13 楼 lin5161678 的回复:] [quote=引用 9 楼 tomsoft 的回复:] [quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界，值是随机的，无讨论价值。  同样的编译器，这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界，其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则，数组越界在当代程序设计中是不允许的，但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题 [/quote]  说的没错，Debug或Release版本或GCC下得-O0或-O2的运行结果会存在不同，这主要是因为不同状态下编译器优化的方式不同，造成全局变量的分配顺序不同，但是，如果是确定版本，这个值是唯一的，即您运行多少次是25还是25，因为其变量的分配位置已经固定 ---- 编译器的优化原则所确定，不可能因为您现在运行是25下次就变成了100，所以，我之前讲了，这个单纯从应用角度上是个错误的案例，但如果从编译器角度我们深入讨论这个问题还是蛮有趣的 ----- 我只希望我们从编译器优化角度探讨一下，这不是一件很有趣的事情吗？ 在相同条件下这个值是固定的“ 都有可能导致结果不同说随机毫无问题”，所以您这句话我并不完全认同，从单纯应用没有错  另外，我之前也说过，对于我们这些老古董C/C++程序员，早先编程最喜欢玩的就是零长度数组，即指定数组的长度是0，利用数组越界访问其后的内容，以实现变长度数组。但这些都是老技巧，即必须对编译器足够了解。如清楚已初始化数据段和未初始化数据段如何分配等等。。。。[/quote]  根本就是对编译器的处理机制再讨论，具体的编译器不一样，结果也不一样。所以说是随机，是没有问题的。

V1[2]是一个长度为2的数组，在C语言里第一个元素是v1[0],第二个是v1[1], 你求和是写成了v[2]这是一个下标越界的情形，V1[2]的值是不确定的，可能与你其他变量的值相同，也可能是一个其他的随机值。如果v1数组的空间与static变量紧挨在一起，这时v1[2]的值可能就是static变量的值，总之v1[2]是不确定的，你把电脑关机，第二天开机再来build，运行这个程序，可能又是一个新的值。 static这里使用上没有什么问题，它是一个局部静态变量。

引用 11 楼 xuhaoee 的回复:C标准规定，全局变量和静态变量都在编译时分配空间，并放在数据段中，且分配的空间是连续的！所以你的static变量才会在全局变量后面，你数组越界，不小心修改了static变量空间的数据，所以才会出现这样的问题！  在早期的编译器中（近代编译器如Clang/LLVM已经太复杂，不讨论），编译的数据段会分成几个部分：已初始化数据段、未初始化数据段、Heap和Stack，因此，变量是否初始化，这个程序的值都会不一致，这主要是因为编译器在编译时分配空间的顺序。同时，因为考虑不同优化算法的影响，也会对变量的分配顺序造成影响，即Debug和Release版本其变量分配顺序也有变化，所产生值也是不同的。注意我之前的回复，相同意义的代码，仅仅因为赋值位置或变量是否初始化，这个值都会发生变化即是如此。  这个问题从对错上没有讨论余地，正像楼上众位高手所云，这是个错误示例。基于此，如果从对错角度，这个问题不需要讨论，我所说的一切都可以无视，以免引起无谓的口水仗

引用 13 楼 lin5161678 的回复:[quote=引用 9 楼 tomsoft 的回复:] [quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界，值是随机的，无讨论价值。  同样的编译器，这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界，其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则，数组越界在当代程序设计中是不允许的，但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题 [/quote]  说的没错，Debug或Release版本或GCC下得-O0或-O2的运行结果会存在不同，这主要是因为不同状态下编译器优化的方式不同，造成全局变量的分配顺序不同，但是，如果是确定版本，这个值是唯一的，即您运行多少次是25还是25，因为其变量的分配位置已经固定 ---- 编译器的优化原则所确定，不可能因为您现在运行是25下次就变成了100，所以，我之前讲了，这个单纯从应用角度上是个错误的案例，但如果从编译器角度我们深入讨论这个问题还是蛮有趣的 ----- 我只希望我们从编译器优化角度探讨一下，这不是一件很有趣的事情吗？ 在相同条件下这个值是固定的“ 都有可能导致结果不同说随机毫无问题”，所以您这句话我并不完全认同，从单纯应用没有错  另外，我之前也说过，对于我们这些老古董C/C++程序员，早先编程最喜欢玩的就是零长度数组，即指定数组的长度是0，利用数组越界访问其后的内容，以实现变长度数组。但这些都是老技巧，即必须对编译器足够了解。如清楚已初始化数据段和未初始化数据段如何分配等等。。。。

其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

引用 9 楼 tomsoft 的回复:[quote=引用 8 楼 jiftlixu 的回复:] V2[2] 数组越界，值是随机的，无讨论价值。  同样的编译器，这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界，其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则，数组越界在当代程序设计中是不允许的，但从编译器进行学术性讨论还是蛮有趣的。[/quote]同样的编译器 有优化和没优化 使用不同等级的优化 都有可能导致结果不同 说随机毫无问题

月经

引用 8 楼 jiftlixu 的回复:V2[2] 数组越界，值是随机的，无讨论价值。  同样的编译器，这个值并非随机 。在早期古董级C语言中有一种零长度数组就是利用了这种数组越界，其利用越界的数组实现变长度数组或简化访问。对于越界的处理体现了编译器生成代码的原则，数组越界在当代程序设计中是不允许的，但从编译器进行学术性讨论还是蛮有趣的。

V2[2] 数组越界，值是随机的，无讨论价值。

这个结果取决于编译器编译的结果，相同代码，修改如下： #include "stdafx.h" #include <stdio.h> int v0 = 3; int v1[2] = { 1,2 }; int v2 = 3;  int main() { //	v2 = 3; 	static int v4 = 7; 	int v3 = 3; 	int sum = 0; 	sum = v0 + v1[1] + v1[2] + v2 + v3 + v4; 	printf("%d\n", sum);  	return 0; } 其结果为21。其原因主要是紧跟v1[]之后的变量。在当前情况下，v1[]之后可能是v2或v4，这取决于编译器的行为。如果没有赋值语句，其存放顺序与变量出现顺序一致，因此，v1之后紧跟v2，这样v1[2]即是v2。但是，如果在一开始就有v2 =3，编译器从效能角度上先分配已初始化数据段，即顺序是v0,v1,v4,v2这样，v1[2]实际是v4即7 因此，正如楼上所说，这样越界使用是非常危险的，其结果是由编译器决定的。

v1[2]都越界了，讨论值没有意义

数组是从0开始计数的

静态变量也是存储在全局区，而不是栈上，但你这是未定义行为，不一定所有编译环境都这样

1[2]属于越界访问，不建议使用,虽然你恰好得到了V4的值，但这和顺序有关，结果未定义


Question: 自己尝试编写了个单链表，但是运行完了没出自己要的结果，求助

我自己解决了- -


Question: 帮忙解析代码

楼主的问题，主要是设计到结构体的使用。建议，将结构体类型看成类似简单类型一样，但是注意下结构体对与成员的引用方式。

struct customer              { int num;        结构体变量     char name[10];   // 存放姓名数组     char sex[10];    //数组 double money;  //变量 char obj[10];   //数组 struct customer *next;  //结构体类型指针，可以指向下一个成员 };      struct customer *       creat_by_input();                        //返回值为struct customer * 的  类似于  int * struct customer *       get_last_customer(struct customer *head); struct customer *       Print_menu_main()

就一个结构体和三个函数原型，没有什么可以解释的！ 如果这都不懂，那你应该回去看书而不是发帖


Question: 前辈们！请教（形参实参类型问题）

问题的答案楼上已经指出来了，建议楼主可以扩展阅读以下，K&R第二版里的【 附录A.6 转换】，里面详细讲解了各种情形下发生的转换，包括整形提升和算术类型转换等等，当然也包括void*指针与其他类型指针之间的转换。

隐式类型转换。 指针都是一个int数值，都是可以转换的。

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

1楼正解  不过还有个更带劲的，boost::any

http://www.360doc.com/content/10/0814/19/2379862_46047109.shtml 这算是C语言的一种转换，但是这种转换可以不显示（隐式类型转换），除了void的隐式转换，还有比如  unsigned int a = 10;  char b = -10; if (a + b > 0)     printf("Hello"); else     printf("World");  这个程序就是存在一个隐式类型转换，但是和void不一样。它是b在计算a+b时，先将b类型隐式提升为unsigned int，所以b的值-10，就是会编程一个很大的值。所以会输出World

int* 可以 隐式转换为 void*  实际上，任意类型指针均可隐式转换为void*，但反之不成立


Question: 关于链队列出队的疑惑

边界条件……

出队列时需要先判断队列是否为空，因为队列为空，则不能再次出队列，否则会出现指针指向空，或者数据出错。

#define QueueSize 100  /*假定预分配的队列空间最多为100个元素*/     typedef char DataType ; /*假定队列元素的数据类型为字符*/         typedef struct node{       DataType data;       struct node *next;   }QueueNode;         typedef struct{       QueueNode *front;  /*头指针*/       QueueNode *rear;   }LinkQueue;         /* 置队列空*/   void Initial(LinkQueue *Q)       /*将顺序队列置空*/   {           Q->front=Q->rear=NULL;   }          /*判队列空*/   int IsEmpty(LinkQueue *Q)   {       return Q->front==NULL&&Q->rear==NULL;   }         /*进队列*/   void Push(LinkQueue *Q,DataType x)   {       /*将元素x插入链队列尾部*/       QueueNode *p=(QueueNode *)malloc(sizeof(QueueNode));/*申请新结点*/       p->data=x;       p->next=NULL;       if(IsEmpty(Q))           Q->front=Q->rear=p;  /*将x插入空队列*/       else        { /*x插入非空队列的尾*/           Q->rear->next=p;     /*p链到原队尾结点后*/           Q->rear=p;           /*队尾指针指向新的尾*/       }   }         /*出队列*/   DataType Pop(LinkQueue *Q)   {       DataType x;       QueueNode *p;             if(IsEmpty(Q))       {           printf("队列为空");/*下溢*/           exit(1);       }             p=Q->front;                   /*指向对头结点*/       x=p->data;                    /*保存对头结点的数据*/       Q->front=p->next;             /*将对头结点从链上摘下*/       if(Q->rear==p)                /*原队中只有一个结点，删去后队列变空，此时队头指针已为空*/           Q->rear=NULL;             free(p);   /*释放被删队头结点*/       return x;  /*返回原队头数据*/   }         /* 取队列顶元素*/   DataType Front(LinkQueue *Q)   {       if(IsEmpty(Q))       {           printf("队列为空"); /*下溢,退出运行*/           exit(1);       }       printf("Q->front->data:%c \n",Q->front->data);//测试 若数据不为基本类型，则用其他方式显示       return Q->front->data;   }

引用 1 楼 qq_36409192 的回复:DataType Pop(LinkQueue *Q)   {       DataType x;       QueueNode *p;             if(IsEmpty(Q))       {           printf("队列为空");/*下溢*/           exit(1);       }             p=Q->front;                   /*指向对头结点*/       x=p->data;                    /*保存对头结点的数据*/       Q->front=p->next;             /*将对头结点从链上摘下*/       if(Q->rear==p)                /*原队中只有一个结点，删去后队列变空，此时队头指针已为空*/           Q->rear=NULL;             free(p);   /*释放被删队头结点*/       return x;  /*返回原队头数据*/   }    恳请给出完整的程序 包括链队列的定义


Question: hdu1242 提问

仅供参考：#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <graphics.h> int xs[10000]; int ys[10000]; int i=0,xx,yy; int fc,bc; void push(int x,int y) { 	xs[i]=x; 	ys[i]=y; 	if (i<10000-1) { 		i=i+1; 	} else { 		printf("stack overflow!\n"); 		exit(1); 	} } void pop(void) { 	i=i-1; 	xx=xs[i]; 	yy=ys[i]; } int check(int x,int y) { 	int	c;  	c=getpixel(x,y); /*	获取当前点的颜色 */ 	return ((c!=bc)&&(c!=fc));/* 如果颜色为边界色或填充色则不填充 */ } void seedfilling(int x,int y,int fill_color,int boundary_color) { 	fc=fill_color; 	bc=boundary_color; 	push(x,y); 	while (1) { 		if (i<=0) return; 		pop(); 		if (check(xx,yy)) { 			putpixel(xx, yy, 14);getch();  /* 加上这行显示当前填充状态 */  			putpixel(xx, yy, fill_color); /* 画点 */  			if (check(xx-1,yy  )) push(xx-1,yy	); 			if (check(xx  ,yy+1)) push(xx  ,yy+1); 			if (check(xx  ,yy-1)) push(xx  ,yy-1); 			if (check(xx+1,yy  )) push(xx+1,yy	); 			/* 去掉下面四句就是四连通 */ 			if (check(xx-1,yy-1)) push(xx-1,yy-1); 			if (check(xx-1,yy+1)) push(xx-1,yy+1); 			if (check(xx+1,yy-1)) push(xx+1,yy-1); 			if (check(xx+1,yy+1)) push(xx+1,yy+1);         }     } } void main() {     int a,b,color;     int gdriver = DETECT, gmode, errorcode;     int poly[10];  	initgraph(&gdriver,	&gmode,	"d:\\bc\\bgi");     a=150;     b=140;     color=4;     poly[0]=110;/* 第一个点的x坐标以及y坐标 */     poly[1]=110;     poly[2]=200;/* 第二点 */     poly[3]=105;     poly[4]=170;/* 第三点 */     poly[5]=120;     poly[6]=150;/* 第四点 */     poly[7]=170;     poly[8]=110;/* 多边形的起点与终点一样 */     poly[9]=110;     drawpoly(5,poly);/* 显示各点连接起来的多边形 */      /* 保证边界对八连通是封闭的 */     setviewport(0,1,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */     setviewport(1,0,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */     setviewport(1,1,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */      /* 恢复默认viewport */     setviewport(0,0,600,300,0);      seedfilling(a,b,color,15);  /* 种子填充多边形 */      getch();     closegraph(); }

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

但我还是不太懂我到底错哪了啊= =

引用 6 楼 user-2 的回复:OJ对格式要求比较严格，最后两个printf 的换行符 不一定在最后一次输出时要求出现。 也就是赵4老师说的，IO格式问题 然而这不是问题所在啊= =AC代码和我的输出格式一样啊，还是应该是算法出了问题

不想费劲，只瞎猜一下总可以吧。

引用 2 楼 zhao4zhong1 的回复:边界条件 输入输出格式 …… “多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，掰手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？恕小弟不才..什么意思，我的输入输出格式有问题吗= =才疏学浅，见谅，请说的详细一点

BTW：头像很养眼！

做了几组测试用例，也都通过了，不知道为什么，有没有大佬啊= =


Question: ~~看C反汇编代码的困惑~~~

感谢各位老师、同学们的热心回复！ 就此结贴吧，祝大家每天都开心、工作顺利、学习长进快！

1）这个是由两层循环组成的，可以使用for循环。 2）ptr ss:[esp+0x10],是一个局部变量，我们暂且命名他为count 3）mov edx,dword ptr ss:[esp+0x14]实际还是esp+10。因为之前有个push操作，所以之后会有add esp,0x4 所以应该只有一个局部变量。大致样子应该可以看出来

搜“白盒测试”。 汇编语言asm→obj1 C/C++语言→obj2 link obj1+obj2→exe或dll 只要保证“堆栈平衡”，“调用参数约定和返回值约定一致”即可。 调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx 你走入了误区。根本不需要“从汇编转换到C”这项技能。

就代码说事： 1）首先明确这个代码应该不是C++代码；如果是C++代码，会有ecx传入this指针，这样如果是ecx的某个偏移，就可以认定是类成员变量 2）反汇编首先要明白局部变量时保存在哪里。这个“dword ptr ss:[esp+0x140]”应该是局部变量。在函数调用时，局部变量时保留在堆栈上。 关于反汇编建议看卡巴斯基《黑客反汇编揭秘》，建议看第一版，不要看新的第二版本；那个是经典  关于IDAPro说明几条： 1）Windows代码，如果是Release代码，除非是dll库，不要指望可以反汇编出函数名。但Linux代码有机会 2）任何情况，成员变量和局部变量都是无法反汇编出来的。所以，如果辨识出变量，自己命名就好了 3）对于C++一定注意ecx，这是this指针，多数是突破口 4）C++中虚函数几乎无法反汇编，需要动态执行才可以确认。 5）不要迷信IDAPro那个自动将汇编变成C代码，那个功能基本是鸡肋：反汇编出来代码几乎不可读。我们都是手工反汇编。

感谢各位老师、同学的帮助！我想了又想，还是直接用代码来说明我的问题吧。下面的汇编代码是我用C写的一个函数的反汇编结果，源代码很简单，但当我不回忆源代码，直接看它的汇编，尝试还原的时候麻烦就来了。请各位老师、同学试着还原，期间我再提出让我头晕的问题点。有劳各位了，先祝大家天天开心，看完后也能让我跟着大家一块开心，谢谢！  00401000   push ecx                                 00401001   push ebx 00401002   push ebp 00401003   xor ebp,ebp 00401005   push esi 00401006   push edi 00401007   mov dword ptr ss:[esp+0x10],ebp 0040100B   xor edi,edi 0040100D   test ebp,ebp 0040100F   jl short 00401048 00401011   test edi,edi 00401013   jl short 00401032 00401015   lea eax,dword ptr ds:[edi+ebp] 00401018   lea ebx,dword ptr ds:[edi+0x1] 0040101B   lea esi,dword ptr ds:[eax+eax*4] 0040101E   shl esi,1 00401020   push esi 00401021   push 0x407034                         ;  ASCII "%d " 00401026   call 00401110 0040102B   add esp,0x8 0040102E   inc esi 0040102F   dec ebx 00401030   jnz short 00401020 00401032   push 0x407030                          ;  ASCII "\r\n" 00401037   call 00401110  0040103C   mov eax,dword ptr ss:[esp+0x14] 00401040   add esp,0x4 00401043   inc edi 00401044   cmp edi,eax 00401046   jle short 00401011                      00401048   push 0x407030                           ;  ASCII "\r\n" 0040104D   call 00401110                            00401052   mov edx,dword ptr ss:[esp+0x14] 00401056  add esp,0x4 00401059  add ebp,0xA 0040105C  inc edx 0040105D  cmp ebp,0x64 00401060  mov dword ptr ss:[esp+0x10],edx 00401064  jl short 0040100B 00401066  pop edi            00401067  pop esi            00401068  pop ebp            00401069  pop ebx            0040106A  pop ecx            0040106B  retn

是我没表达清楚，在研究逆向，面对上面的问题不知道接下来应该怎么走了。

《程序员的自我修养——链接、装载与库》

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George  前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题；他觉得前同事们应该用这些问题来问自己；实际上不管在哪里工作的开发者们都应该经常问问自己这些问题： ◆“要保证这个问题不会再出现，我该怎么做？” ◆“要想少出些Bug，我该怎么做？” ◆“要保证Bug容易被修复，我该怎么做？” ◆“要保持对变化的快速响应，我该怎么做？” ◆“要保证我的软件的运行速度，我该怎么做？” 如果大多数团队都能不时问一下自己，必定会从中得益，因为这些都是真正强而有力的问题。

没必要还原。 直接将asm格式的反汇编模块和C/C++代码链接到一起即可。

反汇编后的代码本来理解起来肯定是会困难  推荐先去看这本书：《C++反汇编与逆向分析技术揭秘》   虽然是C++的，但前面大部分内容适用于C

其实全局变量应很好看才对， gnu的编译器会把全局变量统一放到程序镜像的数据段里的，直接反汇编就可以看到了。至于局部变量，只能通过对它的操作来区别了。

使用IDA这种反编译软件，能够把二进制文件翻译成类c的伪代码。


Question: 怎么修改啊

两个错误： 1、main函数没有带类型,正确的写法 void main() { ... } 2、delay函数的参数定义错误，应该写出void delay(unsigned int i)

引用 5 楼 qq_38773731 的回复:error C2447: missing function header (old-style formal list?)什么意思啊 你定以header函数了吗？该函数可能没有先声明

此外，主函数中P1没有声明

去掉这两句中的code：  unsigned char code F_Rotation[4]={0x03,0x05,0x0D,0x09};//正转表格  unsigned char code B_Rotation[4]={0x09,0x0D,0x05,0x03};//反转表格      void Delay(unsigned inti)  改成：  void Delay(unsigned int i)

另外，延时函数里面需要加一行代码，否则瞬间就结束了，起不到延时作用  void Delay(unsigned inti)  //延时  {          while(--i)        {             Sleep(1);        }  }

#include <config.h>里面的函数或者类声明等  少了 }  或者 ;（分号），检查一下


Question: hdu1242 Runtime Error (ACCESS_VIOLATION)什么情况

引用 4 楼 IDJD_LPY 的回复:[quote=引用 3 楼 user-1 的回复:]         v1 = h.front();         h.pop();         for ( i = 0; i < 4; i++)         {             v2.x = v1.x + dir[i][0];             v2.y = v1.y + dir[i][1];  这块v2.x及v2.y有可能出现小于0的情况。你没有判断 是的，只是一个问题。。但是改完之后怎么直接WA了[/quote]  for ( i = 0; i < 4; i++)         {             v2.x = v1.x + dir[i][0];             v2.y = v1.y + dir[i][1];             if (v2.x == a.x&&v2.y==a.y)             {                 ax = v1.x; ay = v1.y;                 return true;             } 这块你找到一个结果就返回。但这个结果未必是最小时间如下测试用例： 7 8 r.xxxa#. ........ #..#x... ..#..#.# #...##.. .#...... ........ 正确答案应该是7，面你的答案应该是8

引用 3 楼 user-1 的回复:        v1 = h.front();         h.pop();         for ( i = 0; i < 4; i++)         {             v2.x = v1.x + dir[i][0];             v2.y = v1.y + dir[i][1];  这块v2.x及v2.y有可能出现小于0的情况。你没有判断 是的，只是一个问题。。但是改完之后怎么直接WA了

感觉不是数组越界，开得再大还是re

#include<stdio.h> #include<iostream> #include<queue> using namespace std;  int N,M; char map[210][210]; int ex,ey; int result; int flag[210][210];  int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};  struct point{        int x,y;        int time; };  bool check(int x,int y){      if(x>=0&&y>=0&&x<N&&y<M)return true;      return false; } int Search(int sx,int sy){     point t1,t2;     queue<point> Q;     t1.x=sx;     t1.y=sy;     t1.time=0;     Q.push(t1);     while(!Q.empty()){                  t1=Q.front();         if(t1.x==ex&&t1.y==ey){            if(result>t1.time)result=t1.time;         }         Q.pop();         for(int i=0;i<4;i++){                 int dx=t1.x+dir[i][0];                 int dy=t1.y+dir[i][1];                 if(check(dx,dy)&&map[dx][dy]=='.'){                     t2.x=dx;                     t2.y=dy;                     t2.time=t1.time+1;                     if(t2.time<flag[t2.x][t2.y]&&t2.time<=result){                         flag[t2.x][t2.y]=t2.time;                         Q.push(t2);                     }                 }                 else if(check(dx,dy)&&map[dx][dy]=='x'){                      t2.x=dx;                      t2.y=dy;                      t2.time=t1.time+2;                      if(t2.time<flag[t2.x][t2.y]&&t2.time<=result){                         flag[t2.x][t2.y]=t2.time;                         Q.push(t2);                     }                 }         }     }     return result; }  int main(){     int sx,sy;     int i,j;     while(scanf("%d%d",&N,&M)!=EOF){         memset(flag,50000,sizeof(flag));         for(i=0;i<N;i++){                 cin>>map[i];         }         result=500000;         for(i=0;i<N;i++){            for(j=0;j<M;j++){              if(map[i][j]=='r'){                 sx=i;                 sy=j;              }              else if(map[i][j]=='a'){                   map[i][j]='.';                   ex=i;                   ey=j;              }            }         }         int t=Search(sx,sy);         if(t==500000){           printf("Poor ANGEL has to stay in the prison all his life.\n");         }         else{              printf("%d\n",t);         }     }     return 0; } AC代码你参考下。我的做法是每次找到一个答案后，判断该值是否比已经找到的一个解还小，如果有就更新最小值

现在是  #define _CRT_SECURE_NO_DEPRECATE #include<stdio.h> #include<string.h> #include<queue> using namespace std; char map[400][400]; int visit[400][400], step[400][400]; int dir[4][2] = { {1,0},{-1,0},{0,1},{0,-1} }; int n, m,ax,ay; int i, j,z; bool t; struct node { 	int x, y; }; node a, r, v1, v2,v0; queue<node>h; bool search() { 	h.push(r); 	step[r.x][r.y] = 0; 	visit[r.x][r.y] = 1; 	while (h.empty()!=true) 	{ 		v1 = h.front(); 		h.pop(); 		for ( i = 0; i < 4; i++) 		{ 			v2.x = v1.x + dir[i][0]; 			v2.y = v1.y + dir[i][1]; 			if (v2.x>=0&&v2.y>=0) 			{ 				 				if (v2.x == a.x&&v2.y == a.y) 				{ 					ax = v1.x; ay = v1.y; 					return true; 				} 				if (visit[v2.x][v2.y] == 2&&v1.x==v0.x&&v1.y==v0.y) 				{ 					h.push(v2); 					visit[v2.x][v2.y] = 1; 					step[v2.x][v2.y] = step[v2.x][v2.y] + 1; 				} 				if (v2.x < n&&v2.y < m&& map[v2.x][v2.y] != '#'&&visit[v2.x][v2.y] == 0) 				{ 					 					if (map[v2.x][v2.y] == 'x') 					{ 						h.push(v1); 						visit[v2.x][v2.y] = 2; 						v0 = v1; 						step[v2.x][v2.y] = step[v1.x][v1.y] + 1; 					} 					if(map[v2.x][v2.y] == '.') 					{ 						h.push(v2); 					    visit[v2.x][v2.y] = 1; 						step[v2.x][v2.y] = step[v1.x][v1.y] + 1; 					} 				} 			} 		} 	} 	return false; } int main() { 	while (scanf("%d%d", &n, &m) != EOF) 	{ 		memset(map, 0, sizeof(map)); 		memset(visit, 0, sizeof(visit)); 		memset(step, 0, sizeof(step)); 		for (i = 0; i < n; i++) 		{ 			scanf("%s", map[i]); 			for (j = 0; j < m; j++) 			{ 				 				if (map[i][j] == 'a') 				{ 					a.x = i; a.y = j;  				} 				if (map[i][j] == 'r') 				{ 					r.x = i; r.y = j; 				} 			} 		} 		t = search(); 		while (h.empty() != true) 		{ 			h.pop(); 		} 		if (t == true) 		{ 			printf("%d\n", step[ax][ay]+1); 		} 		if (t == false) 		{ 			printf("Poor ANGEL has to stay in the prison all his life.\n"); 		} 	} 	return 0; }  刚刚改了几个问题，一个是循环一次后队列清零，一个是算法逻辑部分错误，但不知道为什么还是WA，有点崩溃。。

引用 5 楼 user-1 的回复:[quote=引用 4 楼 IDJD_LPY 的回复:] [quote=引用 3 楼 user-1 的回复:]         v1 = h.front();         h.pop();         for ( i = 0; i < 4; i++)         {             v2.x = v1.x + dir[i][0];             v2.y = v1.y + dir[i][1];  这块v2.x及v2.y有可能出现小于0的情况。你没有判断 是的，只是一个问题。。但是改完之后怎么直接WA了[/quote]  for ( i = 0; i < 4; i++)         {             v2.x = v1.x + dir[i][0];             v2.y = v1.y + dir[i][1];             if (v2.x == a.x&&v2.y==a.y)             {                 ax = v1.x; ay = v1.y;                 return true;             } 这块你找到一个结果就返回。但这个结果未必是最小时间如下测试用例： 7 8 r.xxxa#. ........ #..#x... ..#..#.# #...##.. .#...... ........ 正确答案应该是7，面你的答案应该是8[/quote] 改完了，还是WA。。

运行样例正确，但一直re，不知道为什么


Question: queue使用问题

using namespace std;

#include<stdio.h> #include<queue> 这是用的头文件，网上也查不到同样的问题


Question: 什么意思啊

谢谢了   明白了

类型没有定义，需要加上：  typedef unsigned int uint; typedef unsigned char uchar;  引用 楼主 qq_38773731 的回复:uint t=0; uchar t1=0; uchar k; error C2146: syntax error : missing ';' before identifier 't' error C2501: 'uint' : missing storage-class or type specifiers fatal error C1004: unexpected end of file found

类型未定义，这是你自定义类型？


Question: 定义了外部变量，子函数的参数又定义一次，是不是重复了，有没有简洁的方式

引用 1 楼 qq_35542689 的回复:怎么会是重复，在max函数里面定义的a,b变量的作用域只在max函数里面起作用，而定义在函数外边的变量是全局变量作用域在全局，并且你max()定义的是形参，你也可以定义为aa,bb 只要你传参进来了就行，其实并没有起到实质作用。而外部变量是确实存在的，是有值的  int max( int aa, int bb) c=max(a,b);  也就是说，子函数中可以定义为别的变量名，像这样int max( int aa, int bb)，在主函数中调用子函数时，为c=max(a,b);就建立了子函数形参和外部变量a b的联系，将a b引入了子函数的aa bb对吧

首先max的a,b和上面的定义是不一样的。在max函数的a,b叫做形参，实在函数栈max申请的局部变量；上面定义的a，b是在数据段上申请的全局变量；是不一样的。  声明和定义的区别主要是是否在内存给其分配空间，若分配了则是定义，不论是显示赋值还是不赋值（是随机值）。


Question: 二维字符串数组 应用gets()函数错在哪

请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢？

#include <stdio.h> #include <stdlib.h>  void rev_string(char s[][128],int n) {     int i,k;      for(i=0;i<n;i++) {         int j=0;         while(s[i][j])             j++;         for(k=0; k<j/2 ;k++){             int tmp=s[i][k];              s[i][k]=s[i][(j-1)-k];             s[i][(j-1)-k]=tmp;         }         printf("s[%d]=\"%s\"\n",i,s[i]);       }  }  int main() {     int i,n;     char carry[128][128];      printf("设定几维数组:");     scanf("%d",&n);     getchar();     for(i=0; i<n; i++){          gets(carry[i]);      }     rev_string(carry,n);      return 0; }  在scanf后面加一句getchar();即可 原因是gets是遇到回车结束输入，那么scanf输入后会输入回车，那么有一个回车符在输入缓存里，所以第一个gets读到了回车符直接返回了。所以是空串； 另外，建议使用fgets可以提高程序的安全性

没人呢 ？？

引用 4 楼 yaoqibbs 的回复:引用 1 楼 yaoqibbs 的回复:没人呢 ？？谢谢了 能否给举个简单的fgets（）函数的例子，我想在没学到指针。  char buf[32]; fgets(buf, 32, stdin); buf[strlen(buf)-1] = 0; /* 0 is equal to '\0'*/  stdin是标准输入（键盘）； fgets有一个问题，就是若输入的字符数少于第二个参数减1时，会将回车符加入到字符串中。所以，需要单独一步用于去掉回车符；

scanf 输入后缓冲区中还留下了换行符\n，会被之后的gets接收了，可以在scanf后加上getchar


Question: 一个二维数组两次输出结果不一样

楼上是什么意思，能解释下吗

#include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

我按你说的检查了，但是zn[0][t]和num[t]在t=1,2,3的时候都是正确的，好崩溃

我怀疑t = 0, t = 1时，num[t]的值为0

建议查一下t = 0时，t = 1, t = 2时，zn[0][t]的值，有可能是t = 0, t = 1, t = 2时，num[t]的值是多少

#include<stdio.h>//定义输入／输出函数  #include<stdlib.h>//定义杂项函数及内存分配函数  #include<string.h>//字符串处理  #include<math.h>//定义数学函数   #define N 2   //2列 #define L 1000  //100行  const char file_name[50] = "data.txt";    int main(int argc, char *argv[]) {        int i,t,c,p,q; 	int zm[40][36];//初水位  	int zn[i][t];//末水位  	//int cq[p][c];//水位库容  	double E[i][t];//余留期效益值 	double n[i][t];//t-1到t阶段的最优出力期望 	   	      FILE *fp;     int data[N][L] = {0};   //二维数组     int index[N] = {0};   //二维数组列下标     double temp;       int v, u;     int count = 0;  //计数器，记录已读出的浮点数     if((fp=fopen(file_name, "rb")) == NULL) {         //printf("请确认文件(%s)是否存在!\n", file_name);         exit(1);     }     while(1==fscanf(fp, "%lf", &temp)) {         data[count%N][(index[count%N])++] = temp;         count++;     }     for(v = 0; v < N; v++) {                 for(u = 0; u < index[v]; u++) {            data[v][u];         }        // printf("\n");     }     fclose(fp);                         int a=0,num[36]={0};         for(u = 0; u < 36; u++) { 		   // printf("%d\t",data[0][u]);		     		    //printf("%d\t",data[1][u]); 			//printf("\n"); 		  num[a]=data[0][u]-data[1][u]; 		  a++; 		          }  // for(a= 0; a < 36; a++)    //printf("%d\n",num[a]);        for(t= 0; t < 36; t++){         for(i=0;i <=num[t] ;i++){   		zn[i][t] =data[0][t];   		data[0][t]--; 		printf("%d\t",zn[i][t]); 				 			//	printf("%d\t",data[0][t]);	 			//	printf("\n");   	      }      	// printf("\n");   }	      		for(t= 0; t < 36; t++){          for(i=0;i <=num[t] ;i++){      	  printf("%d\t",zn[i][t]); 		   } 		 printf("\n"); 	}      }

int zn[i][t]; 这人i, t都是随机值，会不会zn导致栈溢出；这个地方要改一下，设定一个确认值； 另外，改一下输出，看看两个输出是否一样： for(t = 0; t < 36; t++){         for(i=0; i <= num[t]; i++){             zn[i][t] = data[0][t];             data[0][t]--;             printf("zn[%d][%d] =%d\t", i, t, zn[i][t]);          }      }      for(t= 0; t < 36; t++){         for(i=0;i <= num[t]; i++){             printf("zn[%d][%d] =%d\t", i, t, zn[i][t]);         }         printf("\n");     }


Question: debug assertion failed

引用 3 楼 user-2 的回复:还是贴下代码吧. 还有，malloc分配之后，都正确地释放了吗？都释放了。因为代码较长，局部变量结果都是正确的，找不到错误的块，所以没贴代码，非常抱歉啊。

引用 4 楼 doubyZZ 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] 建议贴出相关的代码～非常谢谢你，我可能找到了错误的地方。想请教一下你，我定义了一个int类型的数组，且用static修饰过了，然后用一个int 类型的指针指向它，请问会出问题吗？ 比如：static int a[20][30]={.......}; int *p=a[0];[/quote] 嗯，没问题。这个指针指向了a第一行的首地址。static只是说明a数组不是在栈上申请的（若a在函数里定义），而是在静态数据端申请的。

引用 2 楼 cfjtaishan 的回复:建议贴出相关的代码～非常谢谢你，我可能找到了错误的地方。想请教一下你，我定义了一个int类型的数组，且用static修饰过了，然后用一个int 类型的指针指向它，请问会出问题吗？ 比如：static int a[20][30]={.......}; int *p=a[0];

还是贴下代码吧. 还有，malloc分配之后，都正确地释放了吗？

建议贴出相关的代码～

不知道为啥上传不了图片


Question: 用递归实现n³

“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

递归相对于迭代而言，对于求n^3，迭代效率更高。

求n的三次方没必要用递归，直接pow(n,3)就可以了。

引用 3 楼 shihengzhen101 的回复: #include <stdio.h>   int mypow(int s, int n) {         return  (n-- > 0)  ?  (s * mypow(s, n) : 1; }   int main() {     printf("%d\n", mypow(2, 3));     return 0; }   改一下，少个括号   #include <stdio.h>   int mypow(int s, int n) {         return  (n-- > 0)  ?  (s * mypow(s, n)) : 1; }   int main() {     printf("%d\n", mypow(2, 3));     return 0; }

1楼很赞，我是小白，看了代码恍然大悟

#include <stdio.h>  int _pow(int s, int n) { 	if (n-- > 0) { 		return s * _pow(s, n); 	} else { 		return 1; 	} }  int main(int argc, char *argv[]) { 	printf("%d\n", _pow(2, 3)); 	return 0; }


Question: 关于C语言中简化函数定义的问题

今天才看到这个贴几年了，都还没有结贴，居然都已经忘记了当时发帖的初衷了。不过复习了一遍，收到了各位大神的很大启发，受教了。 此贴正式结束。多谢大家。

引用 10 楼 kingofghost 的回复:[quote=引用 8 楼 shihengzhen101 的回复:] 我没有搞懂，你为什要定义那么多一样的函数  简单讲，因为这些函数，是作为回调函数注册到下层的，而注册回调函数时，会判断此函数是否已经被注册，如果已经被注册，则不再注册。由于软件框架是使用的C/S模式，注册回调会在不同的client发起，所以会造成前一个client注册了回调，后一个client再注册，就会注册失败。[/quote]  那你就用宏定义呗，这样写起来还方便点，可能可读性会差点

#define 高招  但是弱弱的问一句，定义这么多一样的函数有必要吗。 函数名要有一定的意义，见名知意。 一个函数能实现，就在函数内部做分支呀。

引用 8 楼 shihengzhen101 的回复:我没有搞懂，你为什要定义那么多一样的函数  简单讲，因为这些函数，是作为回调函数注册到下层的，而注册回调函数时，会判断此函数是否已经被注册，如果已经被注册，则不再注册。由于软件框架是使用的C/S模式，注册回调会在不同的client发起，所以会造成前一个client注册了回调，后一个client再注册，就会注册失败。

仅供参考：#include <stdio.h> double A[300][100]; double valuex[300]; double valuey[300]; int i; double fun00(double x,double y) {return x  +   y  ;}; double fun01(double x,double y) {return x*x+ 3*y  ;}; double fun02(double x,double y) {return x  + 2*y*x;}; //...  fun03(double x,double y) {return ...+...   ;}; //... //...  fun98(double x,double y) {return ...+...   ;}; double fun99(double x,double y) {return x/2+20*y  ;}; double (*funNN[100])(double,double)={     fun00,     fun01,     fun02, //  fun03, //  ... //  fun98,     fun99, }; int main() {     double x,y;     int f,FN;      for (i=0;i<300;i++) {         valuex[i]=(double)i;         valuey[i]=(double)i;     }     FN=3;     for (i=0;i<300;i++) {          x=valuex[i];          y=valuey[i];          for (f=0;f<FN;f++) A[i][f]=funNN[f](x,y);     }     for (i=0;i<3;i++) {         for (f=0;f<FN;f++) printf("%lg ",A[i][f]);         printf("\n");     } 	return 0; } //0 0 0 //2 4 3 //4 10 10

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George  前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题；他觉得前同事们应该用这些问题来问自己；实际上不管在哪里工作的开发者们都应该经常问问自己这些问题： ◆“要保证这个问题不会再出现，我该怎么做？” ◆“要想少出些Bug，我该怎么做？” ◆“要保证Bug容易被修复，我该怎么做？” ◆“要保持对变化的快速响应，我该怎么做？” ◆“要保证我的软件的运行速度，我该怎么做？” 如果大多数团队都能不时问一下自己，必定会从中得益，因为这些都是真正强而有力的问题。

多态------

我没有搞懂，你为什要定义那么多一样的函数

功能一样为啥要一系列函数不是一个函数？

#define正解

其实就是函数指针数组，参考 http://blog.csdn.net/chenglibin1988/article/details/8916534  引用 楼主 kingofghost 的回复:比如，我要向定义一系列功能一样的函数： func1(x) func2(x) func3(x) func4(x) .....  这样写起来代码很难看，而且很多重复，如果要修改这些函数的实现，得每个函数都要修改，重复的工作也很多，并且容易有遗漏。 我想知道，有没有一个办法，可以用一个函数来代替所有这个函数的定义，并且在函数调用的时候，根据不同的情况调用不同的函数？  先谢谢各位大神！

lz可以搜下 “c语言 策略模式” 基本思想是用函数指针

建议定义函数指针，将具有相同参数（类型，个数）和相同返回值的函数用一个函数指针。


Question: Netbeans把C语言打包成exe的步骤是不是错了？


Question: 斐波那契法求极值C代码实现

百度搜相关关键字。

贴不了图片  很尴尬


Question: 求解 我是c语言新手，分类排序。偶数从大到小排列 ，奇数从小到大排列

for(i=0;i<j-1;i++) for(x=i+1;x<m;x++) { if(b[i]>b[i+1]) { b[i]=b[i+1]; temp=b[i]; b[i+1]=temp; } } for(i=0;i<k;i++) for(x=i+1;x<m;x++) { if(c[i]<c[i+1]) { c[i]=c[i+1]; remp=c[i]; c[i+1]=remp; } 这一段没看懂 printf("%d\n%d\n",b,c); 这首要做啥？

#include <stdio.h> #include <stdlib.h> #include <string.h>   typedef int (*pfunc)(int );  int is_even(int num) {     return !(num % 2); }  int is_odd(int num) {     return (num % 2); }  void select_asc_sort(int *arr, int num, pfunc chk_func) {     int i, j;     int min, tmp;      for (i = 0; i < num; i++) {         if (!chk_func(arr[i]))             continue;         min = i;         for (j = i+1; j < num; j++) {             if (!chk_func(arr[j]))                 continue;             if (arr[min] > arr[j])                 min = j;         }         if (min != i) {             tmp = arr[min];             arr[min] = arr[i];             arr[i] = tmp;         }     } }  void bubble_asc_sort(int *arr, int num) {     int i, j;     int tmp;      for (i = 0; i < num; i++)         for (j = 0; j < num - i - 1; j++)             if (arr[j] > arr[j+1]) {                 tmp = arr[j];                 arr[j] = arr[j+1];                 arr[j+1] = tmp;             }  }  void print_arr(int *arr, int len) {     int i;      for (i = 0; i < len; i++)         printf("%d  ", arr[i]);     putchar(10); }  //#define BUBBLE_SORT  int main() {     int i, n, k, cnt;     char word[16];     int num[100], *arr = NULL;      while (scanf("%s", word) != EOF) {         printf("Please input the number of array: ");         scanf("%d", &n); #ifdef BUBBLE_SORT         arr = (int *)malloc(sizeof(int) * n);         if (!arr) {             fprintf(stderr, "malloc error!\n");             exit(1);         }         if(strcmp(word,"odd") == 0) {             printf("%s\n", word);              for (i = 0, cnt = 0; i < n; i++) {                 scanf("%d", &num[i]);                 if (is_odd(num[i]))                     arr[cnt++] = num[i];             }             bubble_sort(arr, cnt);             for (i = 0, k = 0; k < cnt && i < n; i++)                 if (is_odd(num[i]))                     num[i] = arr[k++];             free(arr);         } else if (strcmp(word, "even") == 0) {             printf("%s\n", word);              for (i = 0, cnt = 0; i < n; i++) {                 scanf("%d", &num[i]);                 if (is_even(num[i]))                     arr[cnt++] = num[i];             }              bubble_sort(arr, cnt);              for (i = 0, k = 0; k < cnt && i < n; i++)                 if (is_even(num[i]))                     num[i] = arr[k++];             free(arr);         } #else         if(strcmp(word, "odd") == 0) {             printf("%s\n", word);             for (i = 0; i < n; i++)                 scanf("%d", &num[i]);             select_asc_sort(num, n, is_odd);         } else if (strcmp(word, "even") == 0) {             printf("%s\n", word);             for (i = 0; i < n; i++)                 scanf("%d", &num[i]);             select_asc_sort(num, n, is_even);         } #endif         printf("Show all numbers: \n");         print_arr(num, n);     }     return 0; }


Question: 一个奇怪的bug

引用 14 楼 zhujinqiang 的回复:断点下在0 & 1那行试试看。  结果一样的呀。

断点下在0 & 1那行试试看。

引用 12 楼 paschen 的回复:[quote=引用 8 楼 lxr5109 的回复:] [quote=引用 2 楼 paschen 的回复:] 0 & 1的结果肯定是0  看你断点断在哪了，或者看汇编，一般来说是编译器BUG的可能性很小  断点段在aaa = g_ArcDigitalInput.m_ArcDigitalIO & i; 这一行。 aaa是我测试的代码，原来的代码是给一个函数的输入参数赋值，就是上面注释的那行，也是一样的问题。还有一个比较有趣的是，这问题在Debug版本执行有问题，而release版本却没有问题。 原来的函数接口是：ERROR_ID ArcDIRead(__IN ARCDISIGNAL diindex, __OUT int *disignal) 这部分执行的代码是 	i = 1; 	i = i << diindex;     pthread_mutex_lock(&g_Mutex_ArcWeldingBasic);      if (g_ArcIOModule.m_Used > 0)     {         *disignal = g_ArcDigitalInput.m_ArcDigitalIO & i;     }  debug的部分汇编：       65:	c7 45 f4 01 00 00 00 	movl   $0x1,-0xc(%ebp)       6c:	8b 45 08             	mov    0x8(%ebp),%eax       6f:	89 c1                	mov    %eax,%ecx       71:	d3 65 f4             	shll   %cl,-0xc(%ebp)       74:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)       7b:	e8 fc ff ff ff       	call   7c <ArcDIRead+0x7c>       80:	a1 00 00 00 00       	mov    0x0,%eax       85:	85 c0                	test   %eax,%eax       87:	7e 11                	jle    9a <ArcDIRead+0x9a>  release的部分汇编：     1d94:	b8 01 00 00 00       	mov    $0x1,%eax     1d99:	89 f1                	mov    %esi,%ecx     1d9b:	d3 e0                	shl    %cl,%eax     1d9d:	23 05 04 00 00 00    	and    0x4,%eax     1da3:	89 03                	mov    %eax,(%ebx)     1da5:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)     1dac:	e8 fc ff ff ff       	call   1dad <ArcDIRead+0x4d>  我不知道贴这么些汇编试否能够说明问题？谢谢 [/quote]  你要断在下一行，断在这行的时候，这行的代码是还没有执行的[/quote]  嗯，我是断在这行，然后单步执行这行，然后再贴的结果，和断在下一行结果应该是一样的。

引用 8 楼 lxr5109 的回复:[quote=引用 2 楼 paschen 的回复:] 0 & 1的结果肯定是0  看你断点断在哪了，或者看汇编，一般来说是编译器BUG的可能性很小  断点段在aaa = g_ArcDigitalInput.m_ArcDigitalIO & i; 这一行。 aaa是我测试的代码，原来的代码是给一个函数的输入参数赋值，就是上面注释的那行，也是一样的问题。还有一个比较有趣的是，这问题在Debug版本执行有问题，而release版本却没有问题。 原来的函数接口是：ERROR_ID ArcDIRead(__IN ARCDISIGNAL diindex, __OUT int *disignal) 这部分执行的代码是 	i = 1; 	i = i << diindex;     pthread_mutex_lock(&g_Mutex_ArcWeldingBasic);      if (g_ArcIOModule.m_Used > 0)     {         *disignal = g_ArcDigitalInput.m_ArcDigitalIO & i;     }  debug的部分汇编：       65:	c7 45 f4 01 00 00 00 	movl   $0x1,-0xc(%ebp)       6c:	8b 45 08             	mov    0x8(%ebp),%eax       6f:	89 c1                	mov    %eax,%ecx       71:	d3 65 f4             	shll   %cl,-0xc(%ebp)       74:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)       7b:	e8 fc ff ff ff       	call   7c <ArcDIRead+0x7c>       80:	a1 00 00 00 00       	mov    0x0,%eax       85:	85 c0                	test   %eax,%eax       87:	7e 11                	jle    9a <ArcDIRead+0x9a>  release的部分汇编：     1d94:	b8 01 00 00 00       	mov    $0x1,%eax     1d99:	89 f1                	mov    %esi,%ecx     1d9b:	d3 e0                	shl    %cl,%eax     1d9d:	23 05 04 00 00 00    	and    0x4,%eax     1da3:	89 03                	mov    %eax,(%ebx)     1da5:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)     1dac:	e8 fc ff ff ff       	call   1dad <ArcDIRead+0x4d>  我不知道贴这么些汇编试否能够说明问题？谢谢 [/quote]  你要断在下一行，断在这行的时候，这行的代码是还没有执行的

你用日志输出每个地方的aaa值看看。  引用 6 楼 lxr5109 的回复:[quote=引用 1 楼 turingo 的回复:] 从你的图片上来看，那个1不像是1更像是字母i，你看看是不是打错了。  [quote=引用 楼主 lxr5109 的回复:] C程序，aaa、g_ArcDigitalInput.m_ArcDigitalIO和i都是unsigned int。 然后执行：aaa = g_ArcDigitalInput.m_ArcDigitalIO & i; 其中g_ArcDigitalInput.m_ArcDigitalIO = 0，i= 1。结果aaa居然等于1…… 其中g_ArcDigitalInput.m_ArcDigitalIO是全局变量，aaa和i都是局部变量。但是这段代 码被mutex保护了。 截图是这一句的执行结果    但后一句aaa = 0 & 1;结果又是正常的，aaa等于0[/quote]  是字母i，这个时候i就等于1[/quote]

引用 5 楼 cfjtaishan 的回复:建议将该函数的代码贴出来，同时与aaa有关的变量，可以先打印出来，这样缩小判定的范围。  aaa是测试代码，上面就一个unsigned int aaa=0;

引用 3 楼 zhujinqiang 的回复:局部变量先进行初始化 是个好习惯 赋值以后，和初值应该没有关系了吧？

引用 2 楼 paschen 的回复:0 & 1的结果肯定是0  看你断点断在哪了，或者看汇编，一般来说是编译器BUG的可能性很小  断点段在aaa = g_ArcDigitalInput.m_ArcDigitalIO & i; 这一行。 aaa是我测试的代码，原来的代码是给一个函数的输入参数赋值，就是上面注释的那行，也是一样的问题。还有一个比较有趣的是，这问题在Debug版本执行有问题，而release版本却没有问题。 原来的函数接口是：ERROR_ID ArcDIRead(__IN ARCDISIGNAL diindex, __OUT int *disignal) 这部分执行的代码是 	i = 1; 	i = i << diindex;     pthread_mutex_lock(&g_Mutex_ArcWeldingBasic);      if (g_ArcIOModule.m_Used > 0)     {         *disignal = g_ArcDigitalInput.m_ArcDigitalIO & i;     }  debug的部分汇编：       65:	c7 45 f4 01 00 00 00 	movl   $0x1,-0xc(%ebp)       6c:	8b 45 08             	mov    0x8(%ebp),%eax       6f:	89 c1                	mov    %eax,%ecx       71:	d3 65 f4             	shll   %cl,-0xc(%ebp)       74:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)       7b:	e8 fc ff ff ff       	call   7c <ArcDIRead+0x7c>       80:	a1 00 00 00 00       	mov    0x0,%eax       85:	85 c0                	test   %eax,%eax       87:	7e 11                	jle    9a <ArcDIRead+0x9a>  release的部分汇编：     1d94:	b8 01 00 00 00       	mov    $0x1,%eax     1d99:	89 f1                	mov    %esi,%ecx     1d9b:	d3 e0                	shl    %cl,%eax     1d9d:	23 05 04 00 00 00    	and    0x4,%eax     1da3:	89 03                	mov    %eax,(%ebx)     1da5:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)     1dac:	e8 fc ff ff ff       	call   1dad <ArcDIRead+0x4d>  我不知道贴这么些汇编试否能够说明问题？谢谢

引用 1 楼 turingo 的回复:从你的图片上来看，那个1不像是1更像是字母i，你看看是不是打错了。  [quote=引用 楼主 lxr5109 的回复:] C程序，aaa、g_ArcDigitalInput.m_ArcDigitalIO和i都是unsigned int。 然后执行：aaa = g_ArcDigitalInput.m_ArcDigitalIO & i; 其中g_ArcDigitalInput.m_ArcDigitalIO = 0，i= 1。结果aaa居然等于1…… 其中g_ArcDigitalInput.m_ArcDigitalIO是全局变量，aaa和i都是局部变量。但是这段代 码被mutex保护了。 截图是这一句的执行结果    但后一句aaa = 0 & 1;结果又是正常的，aaa等于0[/quote]  是字母i，这个时候i就等于1

局部变量先进行初始化 是个好习惯

从你的图片上来看，那个1不像是1更像是字母i，你看看是不是打错了。  引用 楼主 lxr5109 的回复:C程序，aaa、g_ArcDigitalInput.m_ArcDigitalIO和i都是unsigned int。 然后执行：aaa = g_ArcDigitalInput.m_ArcDigitalIO & i; 其中g_ArcDigitalInput.m_ArcDigitalIO = 0，i= 1。结果aaa居然等于1…… 其中g_ArcDigitalInput.m_ArcDigitalIO是全局变量，aaa和i都是局部变量。但是这段代 码被mutex保护了。 截图是这一句的执行结果    但后一句aaa = 0 & 1;结果又是正常的，aaa等于0


Question: 一段简短的代码，请教为什么子函数中的值输出了两次

既然写了cout就不用写return，把返回改为void， 或者是把cout那句直接删掉。

引用 3 楼 wang001678 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] 因为调用了aa()函数两次，所以输出3两次也算正常。但是输出的两次又在前面，应该是cout类似printf，参数压栈顺序是从右向左压栈，第二次调用aa()先执行，所以单独输出2次。 如果用d = aa();那么aa()函数执行了一次。 也就是说cout << a << "," << b << "," <<d<< endl;这句话在程序运行时先执行aa()的结果，也就是算出aa()后在屏幕上输出3，再执行在屏幕上连续输出123对吧[/quote] 压栈的顺序是这样的，先执行aa()函数，将返回值压入栈，然后继续将b,a依次压栈

楼上打字打错了，应该是参数的求值顺序。

C++17后输出就变成 3 1,2,3 // 最后的3是aa()里输出的3 3 // aa()返回3，main()里的cout输出3 了，所以不要随意假定参数的输出顺序。

是的  引用 5 楼 wang001678 的回复:[quote=引用 2 楼 turingo 的回复:]  cout << a << "," << b << "," << aa() << endl; /** 等价于 */ c = aa(); /** 这里打印3，并且返回3 */ cout << a << "," << b << "," << c << endl;   [quote=引用 楼主 wang001678 的回复:] 代码如下  #include "stdafx.h" #include <iostream> using namespace std; int a; int b; int d; int aa() { 	int c; 	a = 1; 	b = 2; 	c = a + b; 	cout << c << endl; 	return c; }   int main() {     aa(); 	cout << a << "," << b << "," << aa()<< endl; 	return 0; }  输出结果如图  其中3这个值被单独输出了两次 而如果加入变量d把主函数中代码改为d=aa()，3这个值就被单独输出一次，所以想请教为什么第一段代码中3单独输出了两次[/quote] 刚才回复的代码写错了输出流中d应该改为aa()， 也就是说cout << a << "," << b << "," <<aa()<< endl;这句话在程序运行时先执行aa()的结果，也就是算出aa()后在屏幕上输出3，再执行在屏幕上连续输出123对吧[/quote]

引用 2 楼 turingo 的回复: cout << a << "," << b << "," << aa() << endl; /** 等价于 */ c = aa(); /** 这里打印3，并且返回3 */ cout << a << "," << b << "," << c << endl;   [quote=引用 楼主 wang001678 的回复:] 代码如下  #include "stdafx.h" #include <iostream> using namespace std; int a; int b; int d; int aa() { 	int c; 	a = 1; 	b = 2; 	c = a + b; 	cout << c << endl; 	return c; }   int main() {     aa(); 	cout << a << "," << b << "," << aa()<< endl; 	return 0; }  输出结果如图  其中3这个值被单独输出了两次 而如果加入变量d把主函数中代码改为d=aa()，3这个值就被单独输出一次，所以想请教为什么第一段代码中3单独输出了两次[/quote] 刚才回复的代码写错了输出流中d应该改为aa()， 也就是说cout << a << "," << b << "," <<aa()<< endl;这句话在程序运行时先执行aa()的结果，也就是算出aa()后在屏幕上输出3，再执行在屏幕上连续输出123对吧

引用 2 楼 turingo 的回复: cout << a << "," << b << "," << aa() << endl; /** 等价于 */ c = aa(); /** 这里打印3，并且返回3 */ cout << a << "," << b << "," << c << endl;   [quote=引用 楼主 wang001678 的回复:] 代码如下  #include "stdafx.h" #include <iostream> using namespace std; int a; int b; int d; int aa() { 	int c; 	a = 1; 	b = 2; 	c = a + b; 	cout << c << endl; 	return c; }   int main() {     aa(); 	cout << a << "," << b << "," << aa()<< endl; 	return 0; }  输出结果如图  其中3这个值被单独输出了两次 而如果加入变量d把主函数中代码改为d=aa()，3这个值就被单独输出一次，所以想请教为什么第一段代码中3单独输出了两次[/quote] 也就是说cout << a << "," << b << "," <<d<< endl;这句话在程序运行时先执行aa()的结果，也就是算出aa()后在屏幕上输出3，再执行在屏幕上连续输出123对吧

引用 1 楼 cfjtaishan 的回复:因为调用了aa()函数两次，所以输出3两次也算正常。但是输出的两次又在前面，应该是cout类似printf，参数压栈顺序是从右向左压栈，第二次调用aa()先执行，所以单独输出2次。 如果用d = aa();那么aa()函数执行了一次。 也就是说cout << a << "," << b << "," <<d<< endl;这句话在程序运行时先执行aa()的结果，也就是算出aa()后在屏幕上输出3，再执行在屏幕上连续输出123对吧

cout << a << "," << b << "," << aa() << endl; /** 等价于 */ c = aa(); /** 这里打印3，并且返回3 */ cout << a << "," << b << "," << c << endl;  引用 楼主 wang001678 的回复:代码如下  #include "stdafx.h" #include <iostream> using namespace std; int a; int b; int d; int aa() { 	int c; 	a = 1; 	b = 2; 	c = a + b; 	cout << c << endl; 	return c; }   int main() {     aa(); 	cout << a << "," << b << "," << aa()<< endl; 	return 0; }  输出结果如图  其中3这个值被单独输出了两次 而如果加入变量d把主函数中代码改为d=aa()，3这个值就被单独输出一次，所以想请教为什么第一段代码中3单独输出了两次


Question: 请教为什么C语言中 char 数据类型所指定的字节大小没有起到作用？

引用 2 楼 MHLAH 的回复:[quote=引用 1 楼 turingo 的回复:] 1、sizeof得到的是数组大小； 2、字符串长度应该用strlen函数。  嗯，在过程中计算了sizeof 数组的大小。 这里有一个问题。  char name[4];  char 指定 name字符串数组的大小为 4； 但是在为 name字符串数组赋值时，我输入了 LiSongMing 共计10个字节； 按理说，已经超出了，我对 name 数组所占用内存的大小； 可是却没有造成任何可见的影响。 [/quote] scanf输入并不会检查你的输入是否越界，这也是为什么会有scanf_s的存在。

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

引用 3 楼 turingo 的回复:已经溢出了，没有影响是因为你的程序太小，后面的部分刚好没有被用到；没有影响不表示没有问题，只是运气好没有发作而已。  [quote=引用 2 楼 MHLAH 的回复:] [quote=引用 1 楼 turingo 的回复:] 1、sizeof得到的是数组大小； 2、字符串长度应该用strlen函数。  嗯，在过程中计算了sizeof 数组的大小。 这里有一个问题。  char name[4];  char 指定 name字符串数组的大小为 4； 但是在为 name字符串数组赋值时，我输入了 LiSongMing 共计10个字节； 按理说，已经超出了，我对 name 数组所占用内存的大小； 可是却没有造成任何可见的影响。 [/quote][/quote]  嗯，也就是说，这个越界操作，确实不被允许； 在指定数组的大小时，要尽量取大。 在运行时，sizeof 取得的name数组的大小值并没有因为其内字符多少的改变而改变。 使用strlen可以准确的捕捉到改变，sizeof则无法完成这一点。  谢谢了

已经溢出了，没有影响是因为你的程序太小，后面的部分刚好没有被用到；没有影响不表示没有问题，只是运气好没有发作而已。  引用 2 楼 MHLAH 的回复:[quote=引用 1 楼 turingo 的回复:] 1、sizeof得到的是数组大小； 2、字符串长度应该用strlen函数。  嗯，在过程中计算了sizeof 数组的大小。 这里有一个问题。  char name[4];  char 指定 name字符串数组的大小为 4； 但是在为 name字符串数组赋值时，我输入了 LiSongMing 共计10个字节； 按理说，已经超出了，我对 name 数组所占用内存的大小； 可是却没有造成任何可见的影响。 [/quote]

引用 1 楼 turingo 的回复:1、sizeof得到的是数组大小； 2、字符串长度应该用strlen函数。  嗯，在过程中计算了sizeof 数组的大小。 这里有一个问题。  char name[4];  char 指定 name字符串数组的大小为 4； 但是在为 name字符串数组赋值时，我输入了 LiSongMing 共计10个字节； 按理说，已经超出了，我对 name 数组所占用内存的大小； 可是却没有造成任何可见的影响。

1、sizeof得到的是数组大小； 2、字符串长度应该用strlen函数。

缓存溢出的数据是未定义的，即有可能会出问题的。为了保证程序的可靠性，还是杜绝导致溢出的操作


Question: C语言FFT程序怎么读取两个coe文件里的实部和虚部啊，求大神解答

fscanf


Question: 求修改C程序【数据挖掘之数据预处理】有人可以帮我改改吗？刚开始学不太懂

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。


Question: 新入门的菜鸟希望大牛帮忙。

随便写个文字游戏玩玩，边写边学习，会好玩很多。

[quote=引用 3 楼 huojiaxin 的回复:] 入门先不管这些概念性的东西，等你学完C跟C++后自然而然就理解面向过程跟面向对象的区别了。 学编程最需要的就是静心耐心，不要看了一本没看完又换一本，建议先看C primer plus，然后就是C和指针、C陷阱与缺陷、C专家编程这C语言三剑客了，静下心来看完，总会有收获的。

C语言教程（附带C语言100例）http://download.csdn.net/detail/zhao4zhong1/8830817

我的建议是看出也要加上实践，从实践中你能学到很多书上没有的东西。

本人有个问题希望大神解答。什么是面向对象什么是面向过程。这两个有什么区别？

引用 3 楼 huojiaxin的回复:本人有个问题希望大神解答。什么是面向对象什么是面向过程。这两个有什么区别？ 面对过程很简单，就是C的编程，C不支持面对对象。面对对象是一种编程思想，不会也没关系，照样可以写代码。

多看书多敲代码，不会的不理解的反复敲，直到懂为止

C语言视频没看过，书有不错的。


Question: 出现错误表达式必须是指向完整对象类型的指针

错误原因很明显。struct room room[6]; 这个用法没错的，这个只在 room.c 里面有，room.h 和 in.h 中都没有。但是 room.h 中有一个 void room(); 而 in.c 既包含了 room.h 也包含了 in.h，对于 in.c 可见的非结构体名称的 room 就只有一个 void room(); 也就是个函数名，而你对一个函数名进行 &room[i] 这样的调用当然会报错。struct room room[6]; 对于 in.c 是不可见的。虽然说 struct room room[6]; 这个用法没错，但是尽量避免这样使用。况且在你的全部的四个文件中，有 struct room，有 room[6]，有 void room()。你三个不同意义的 room，这是在迷惑编译器吧？

换个名字试试吧？结构体类型定义也用room，变量名也用room，感觉要出问题。

在in.c中定义一个room变量 struct room room[6];

这个错误明显是函数in()里room这个数组没定义啊

room有声明吗？？？


Question: 大哥来看了

输出指针地址建议用 %p，  %d是按十进制方式输出

此外  char h[2][5]={"gffdy","usfd"},(*y)[5],*j;  改成：  char h[2][6] = { "gffdy","usfd" }, (*y)[6], *j;  因为 "gffdy"是有6个元素

printf("%d\n", *（y + 1)); 这句你用的是中文的括号，要用英文的，改成：  printf("%d\n", *(y + 1));

#include<stdio.h> int main() {     char h[2][5] = {"gffdy","usfd"},(*y)[5],*j;     y=h;     printf("%p\n", y);     printf("%p\n",*(y+1)+1);     printf("%p\n",j);     j=*(y+1)+1;     printf("%p\n",j);     printf("%p\n",*(h+1)+1);     printf("%p\n",*(y+1));      return 0; } 输出地址要用%p或%P。

关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”   printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。

#include<stdio.h> int main() {     // 分配太小（5）不足以存储 下“dffdy”，字符串直接初始字符数组，会在最后增加一个 \0     char h[2][6] = { "gffdy", "usfd" }, (*y)[6], *j;     y = h;     printf("%d\n", y);     printf("%d\n", *(y + 1) + 1);     //printf("%d\n", j); //未初始化就使用     j = *(y + 1) + 1;     printf("%d\n", j);     printf("%d\n", *(h + 1) + 1);     printf("%d\n", *(y + 1));     return 0; }