Question: 读取文件提示null pointer assignment

引用 1 楼 user-1 的回复: #include <stdio.h> #include <dos.h> #include <stdlib.h>   typedef struct _goods { float price; int id;//编号 int leftnum;//剩余存量 int soldnum;//销售量 int income;//销售额 }GOODSINFO;   #define goodspath "c:\\goods.dat" #define GOODS 12  void goodsinit(GOODSINFO *);  int main() { GOODSINFO ps[GOODS] = {0};//原始货物信息 GOODSINFO pg[GOODS] = {0};//用于接收和显示货物信息 FILE *fp = NULL; int i = 0;  goodsinit(ps); //货物信息初始化  //货物信息写入 if ((fp=fopen(goodspath, "w")) == NULL) { printf("write file error"); exit(1); } for(i = 0; i < 10000; i++); //将货物信息写入文件 fwrite(ps, sizeof(GOODSINFO), GOODS, fp); //回溯指针 //	rewind(fp); //关闭文件 fclose(fp);  //读取货物信息 if ((fp=fopen(goodspath, "r")) == NULL) { printf("load file error"); exit(1); } //从文件读取货物信息 fread(pg, sizeof(GOODSINFO), GOODS, fp); //关闭文件 fclose(fp);  printf("%f", pg[0].price);  return 0; }   void goodsinit(GOODSINFO *pg) { int i = 0;  for (i=0 ; i<GOODS ; i++) { (pg + i)->id = i + 1; (pg + i)->leftnum = 50; (pg + i)->soldnum = 0; (pg + i)->income = 0; }  (pg + 0)->price = 2.5; (pg + 1)->price = 3.0; (pg + 2)->price = 2.5; (pg + 3)->price = 3.0; (pg + 4)->price = 3.5; (pg + 5)->price = 2.5; (pg + 6)->price = 3.0; (pg + 7)->price = 4.0; (pg + 8)->price = 2.5; (pg + 9)->price = 2.5; (pg + 10)->price = 5.0; (pg + 11)->price = 3.0;   }   知道哪里错了，多谢！


Question: 读取unsigned long型数据用%ul还是%lu?

引用 4 楼 zhao4zhong1 的回复:Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored. 机器人还在啊。。。被您整无语的时候我还在上大一，而现在我已经工作了。。。看你的等级小白糊弄的飞起啊

scanf 格式为 %[*][width][length]specifier  其中specifier只有u没有l

%lu

自己试一下不就知道了

新手求大神指教


Question: 关于用Visual Studio 2015写C语言遇到的问题~

scanf()报错是确确实实的  _CRT_SECURE_NO_DEPRECATE  或  _CRT_SECURE_NO_WARNINGS  可以修正。  偶尔在main()函数下出现“未声明的局部变量”是怎么回事呢

#pragma warning(disable:4996) ...

引用 1 楼 cjqpker 的回复:其实问题不是出在Visual Studio 2015上，而是出在其所使用的编译器上。scanf报错不至于，顶多给警告。 需要注意额事项太繁杂了，不如好好再翻一本C语言的书。 平时遇到的问题，注意积累，多半这些问题，编译器都会提醒你的 默认情况下，scanf之类不安全的函数，直接给错误。

看报错 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 工程中定义宏 _CRT_SECURE_NO_WARNINGS.即可继续使用scanf

搞不好人家的level设置是将警告作为错误。 引用 1 楼 cjqpker 的回复:其实问题不是出在Visual Studio 2015上，而是出在其所使用的编译器上。scanf报错不至于，顶多给警告。 需要注意额事项太繁杂了，不如好好再翻一本C语言的书。 平时遇到的问题，注意积累，多半这些问题，编译器都会提醒你的

楼上说的很对


Question: 函数参数的问题

1.为什么传给getlines函数的参数p地址为0? 调用时参数写错了 2.函数的参数跟外部的变量重名,在函数内是对哪个进行操作? 重写程序不要让函数的参数跟外部的变量重名 3.如果自定义的函数和标准库里的函数重名,调用的是哪个?和参数有关系吗? 重写程序不要让自定义的函数和标准库里的函数重名

1.为什么传给getlines函数的参数p地址为0?  这个得看该函数的定义了  2.函数的参数跟外部的变量重名,在函数内是对哪个进行操作?  用的是参数  3.如果自定义的函数和标准库里的函数重名,调用的是哪个?和参数有关系吗? 如果是C++的话，有重载机制，如果参数都一样的话，自定义的会将库函数覆盖

引用 3 楼 ant2012 的回复:1.为什么传给getlines函数的参数p地址为0?  这个得看该函数的定义了 函数原型:int readlines(char *lineptr[], int maxlines);                 int getlines(char *p, int lim); 执行了下面两句: readlines (lineptr=0x601080 <lineptr>, maxlines=5000) at textsort.c:30 30	int len, nlines = 0; (gdb)  31	while((len = getlines(lineptr[nlines], MAXLEN)) > 0){ (gdb)  getlines (p=0x0, lim=100) at textsort.c:51  为什么传给指针p的地址是0啊?

引用 1 楼 ashi198866 的回复:lineptr是一个指针数组，也没有看到你给里面的元素分配空间啊这样写不就是已经定义了一个指针数组啊?不是分配空间了啊,所以 " readlines (lineptr=0x601080 <lineptr>, maxlines=5000) "  这里有地址啊.

lineptr是一个指针数组，也没有看到你给里面的元素分配空间啊


Question: 三段代码的编译问题

bc++3.1 http://download.csdn.net/source/2805028

#include <graphics.h> 应该是TC下的图形库

问题应该在于  setPixel 这个函数未定义吧，我猜

lz贴一下错误信息吧

#include 'device. h"， 应该为双引号  另外楼主，能把编译错误信息贴一下么


Question: linux下的代码变量命名，求助

如果你是从Java来的，那么 public class Persion {} Person person; 你会觉得很自然，但真的如此么？ 如果有两个person怎么办？ 所以仔细想想，好的命名应该是person1/person2或者personA/personB， 更好的命名应该是Person LZ; Person me; Person bill; Person alice;这样的有具体含义的。 所以对于struct test; 我更倾向于struct test a;就和int a;一样，对于没有特定意义/含义的，给它个不确切的名字。 相比之下struct test _test已经算是很好的命名了，当然更推荐更有意义的名字。  int a; void a(); 冲突嘛？只要编译器认得出来，就不冲突，用来回答你第二个问题。

引用 12 楼 ri_aje 的回复:[quote=引用 楼主 caddor9100 的回复:] 比如一个结构体  windows :  typdef  struct tagTest {  }Test, *PtrTest;  linux 呢? struct test {  };  linux 下推荐小写，卧槽，导致 结构体做函数参数的时候，相当蛋疼，都不知道怎么命名了。比如：  void fun(Test test); //windows  void fun(test _test);// 无奈之下，我只好加_ 可以直接写 void fun (test test); [/quote] 这招儿 C 语言不认，只能写 struct test test 了。 我见过的其他(c++)全小写命名法一般都是加 _t 后缀，或者加前缀 a_, an_ 之类的。

引用 楼主 caddor9100 的回复:比如一个结构体  windows :  typdef  struct tagTest {  }Test, *PtrTest;  linux 呢? struct test {  };  linux 下推荐小写，卧槽，导致 结构体做函数参数的时候，相当蛋疼，都不知道怎么命名了。比如：  void fun(Test test); //windows  void fun(test _test);// 无奈之下，我只好加_ 可以直接写 void fun (test test);  引用 楼主 caddor9100 的回复:问题2：   struct column{ 	int            width; 	char           *label; 	char           *fmt; }*column = NULL;  *column这是什么鬼?  以前见过：  struct A {  }obj , *pA;  实例怎么可以和类型同名呢？ 先把基础打牢吧，赶上你这二把刀的， linux 也很无奈。

// Windows typedef struct _Test {     int _unused; } Test, *TestPtr;  void fun(Test *ptest);  // Linux  typedef struct _Test {     int _unused; } test_t;  void fun(test_t *ptest);

引用 2 楼 zxh707wk 的回复:引用 1 楼 user-8 的回复:话说，变量命名号称编程的第一难题……确实 巴别塔

引用 4 楼 jiqiang01234 的回复:可以用“驼峰”命名法，第一个单词的首字母小写，后面单词的首字母大写。如： int testNum; int getTestNum(); 引用 4 楼 jiqiang01234 的回复:可以用“驼峰”命名法，第一个单词的首字母小写，后面单词的首字母大写。如： int testNum; int getTestNum();    struct column{ int            width; char           *label; char           *fmt; }*column = NULL;  *column这是什么鬼?  以前只见过：  struct A {  }obj , *pA;  实例怎么可以和类型同名呢？

参考Tiny C Compiler中相关源代码片断。

引用 8 楼 zhao4zhong1 的回复:struct struct [tag] { member-list } [declarators];  [struct] tag declarators;  The struct keyword defines a structure type and/or a variable of a structure type. See Anonymous Structures and Unsized Array in a Structure for more information.  A structure type is a user-defined composite type. It is composed of "fields" or "members" that can have different types.  In C++, a structure is the same as a class except that its members are public by default.  Using a Structure  In C, you must explicitly use the struct keyword to declare a structure. In C++, this is unnecessary once the type has been defined.  You have the option of declaring variables when the structure type is defined by placing one or more comma-separated variable names between the closing brace and the semicolon.  For related information, see class, union, and enum.  Example 1  struct PERSON              // Declare PERSON struct type {    int   age;              // Declare member types    long  ss;    float weight;    char  name[25]; } family_member;           // Define object of type PERSON     struct PERSON sister;   // C style structure declaration    PERSON brother;         // C++ style structure declaration     sister.age  = 13;       // assign values to members    brother.age =  7; Structure variables can be initialized. The initialization for each variable must be enclosed in braces.  Example 2  struct POINT            // Declare POINT structure {    int x;               // Define members x and y    int y; } spot = { 20, 40 };    // Variable spot has                         //     values x = 20, y = 40 struct POINT there;     // Variable there has POINT type struct CELL             // Declare CELL bit field {    unsigned character  : 8;  // 00000000 ????????    unsigned foreground : 3;  // 00000??? 00000000    unsigned intensity  : 1;  // 0000?000 00000000    unsigned background : 3;  // 0???0000 00000000    unsigned blink      : 1;  // ?0000000 00000000 } screen[25][80];       // Array of bit fields  linux 内核代码里也有很多 结构体和实例同名的例子  擦，吃惊了。  这么蛋疼的 写法。

引用 6 楼 zhao4zhong1 的回复:引用 2 楼 zxh707wk 的回复:[quote=引用 1 楼 user-8 的回复:] 话说，变量命名号称编程的第一难题……确实 巴别塔[/quote]  帮忙看看5楼，这个奇怪的语法，是开一个开源库里的，而且出现次数很多。

命名并没有强制要求，仅仅属于个人习惯，好的习惯会给你带来很多好处而已；

引用 1 楼 user-8 的回复:话说，变量命名号称编程的第一难题……确实

话说，变量命名号称编程的第一难题……


Question: 菜鸟入门

应该是软件的问题，在我的vc6.0编译没问题

# include <stdio.h>  int main (void) {     float score;  	printf (“请输入您的成绩:\n”); 	scanf (“f%\n”, &score);  	if (score>100) 		printf (“这是在做梦！\n”); 	else if (score>=90 && score<100) 		printf (“优秀!\n”); 	else if (score>=80 && score<90) 		printf (“良好!\n”); 	else if (score>=60 && score<80) 		printf (“合格!\n”); 	else if (score>=0 && score<60) 		printf (“your没有及格!\n”); 	else 	    printf (“成绩太低无法统计!\n”); 		 	return 0; }

引用 11 楼 qq_30797775 的回复:那冒昧的问一下你用的那个？或者说您觉得那个号用  vc6.0比较小，而且不用在调试时加system("pause")，比较方便，但其不支持一些新C++标准，如不支持long long 型，不能在vecotr中嵌套vector，不完全支持友元 vs比较新，功能全，就是软件大

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

那冒昧的问一下你用的那个？或者说您觉得那个号用

vc6.0完整版，或者用vs

哦，谢谢，有没有好点的版本给我推荐

引用 6 楼 qq_30797775 的回复:# include <stdio.h>  int main (void) {     float score;  	printf (“请输入您的成绩:\n”);                  /*双引号必须是英文的*/ 	scanf (“f%\n”, &score);   /*应该是%f */     /*另外输入框不要加个\n，否则要多输入一行*/      	if (score>100) 		printf (“这是在做梦！\n”);             /*双引号*/ 	else if (score>=90 && score<100)    /*这里漏掉100分数*/ 		printf (“优秀!\n”);                           /*..........双引号..............*/ 	else if (score>=80 && score<90)    		printf (“良好!\n”);                           /*..........双引号..............*/ 	else if (score>=60 && score<80) 		printf (“合格!\n”);                              /*..........双引号..............*/ 	else if (score>=0 && score<60) 		printf (“your没有及格!\n”);                /*..........双引号..............*/ 	else 	    printf (“成绩太低无法统计!\n”);           /*..........双引号..............*/ 		 	return 0; } 改完之后的是这样的： # include <stdio.h> int main (void) {     float score; printf ("请输入您的成绩:\n"); scanf ("%f", &score);    if (score>100) printf ("这是在做梦！\n"); else if (score>=90 && score<=100) printf ("优秀!\n"); else if (score>=80 && score<90) printf ("良好!\n"); else if (score>=60 && score<80) printf ("合格!\n"); else if (score>=0 && score<60) printf ("your没有及格!\n"); else     printf ("成绩太低无法统计!\n"); return 0; } 另外劝一句不要用绿色版的了，我吃了两次绿色版的苦。

贴一下完整代码

不会，我才学了一点，想练练手。但是总是编译出错

楼主，你会不会双引号写成单引号了，贴下代码

楼主，你会不会双引号写成单引号了，贴下代码

印象中VC6不支持中文路径，但没用过绿色版。把路径改成全英文试试。 另外，如果想好好学一下C的话，建议还是正儿八经装个版本高一点的吧，比如vs2010， VC6毕竟有点太老了。


Question: C语言菜鸟求助

double per,n; 	int sum=0; 	printf("Please input n:\n"); 	scanf("%lf",&n); 	if(n<=5) 	{per=(1-(n-1)/100)*10;sum=per*n;} 	else if(n<=20) 	{per=(1-(4+(n-5)*0.4)/100)*10;sum=per*n;} 	else if(n<=50) 	{per=(1-(10+(n-20)*0.15)/100)*10;sum=per*n;} 	else if(n<=300) 	{per=(1-(14.5+(n-50)*0.03)/100)*10;sum=per*n;} 	else 	{per=(1-(4+(n-5)*0.4)/100)*10;sum=per*n;} 	printf("sum=%d,per=%lf\n",sum,per);

楼主，你的数学是谁教的呢 优惠x%，你在计算单价的时候，有没有除100，然后再用1 - 优惠率，然后在乘以原价呢

编程时脑子太累，小晕而已，何必与他人相关联！ 从你的话语中，可以看出，你喜欢东扯西扯，德行不是很高。

编程时脑子太累，小晕而已，何必与他人相关联！ 而且，这个真不是纯粹的数学问题，即使按我的程序运转，最后检查时无错误，显示时却出现极其离谱的数（无论输什么都是几十位数）请理解透计算机原理问题再准确回答，谢谢！

sum改成double还不行。哪位能帮着把程序改一下。谢谢！

sum改成double还不行。哪位能帮着把程序改一下。

sum 用double

按各位指点的改了一下，还不行。请各位再帮忙看一下。 #include<stdio.h> void main() { double per,n; int sum=0; printf("Please input n:\n"); scanf("%If",&n); if(n<=5) {per=(1-(n-1)/100)*10;sum=per*n;} else if(n<=20) {per=4+(n-5)*0.4;sum=per*n;} else if(n<=50) {per=10+(n-20)*0.15;sum=per*n;} else if(n<=300) {per=14.5+(n-50)*0.03;sum=per*n;} else {per=10*(1-0.22);sum=per*n;} printf("sum=%d,per=%10f",sum,per) }

输入double型数据时要用%lf

另外根据你给的公式感觉300件以上老板略亏呀，优惠了100%+

scanf()里用%lf格式，最后的else里面怎么不是按公式写的？最后算sum怎么不用乘单价？


Question: 求高手帮解决这个问题，用C语言

其实就枚举一下排列 int a[10],vis[10]; void check_print(){     // 0/12 + 3/45 = 6/78     int den12=a[1]*10+a[2],         den45 =a[4]*10+a[5],         den78 =a[7]*10+a[8];      if((a[0]*den45+a[3]*den12)*den78==a[6]*den12*den45)         printf("%d/%d+%d/%d=%d/%d\n",a[0],den12,a[3],den45,a[6],den78); }  void dfs(int d){     if(d==9) return check_print();     for(int i=1;i<10;i++) if(!vis[i]){         vis[i] =1;         a[d] =i;         dfs(d+1);         vis[i] =0;     } }  //call dfs(0)

//共有16个组合 #import <Foundation/Foundation.h>  //得到分数和组成分数的3个数 typedef struct number{     float num;     int a;     int b;     int c; }Number;  int main(int argc, const char * argv[]) {     //504，是因为C(9, 3)*6 = 504     Number numb[504] = {0};     int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};     int *p = a;     int e = 0;     //得到所有分数     for (int i = 0; i < 9; i++) {         for (int j = 0; j < 9; j++) {             for (int k = 0; k < 9; k++) {                 if (j != i && k != i && k != j) {                     //分子                     float molecular = *(p + i);                     //分母                     int denominator = *(p + j) * 10 + *(p + k);                     //将分数和构成分数的3个数存储到结构体中                     numb[e].num = (molecular / denominator);                     numb[e].a = *(p + i);                     numb[e].b = *(p + j);                     numb[e].c = *(p + k);                     //计算分数的个数                     e++;                 }             }         }              }     //确认下组成的分数是不是504个     printf("\n%d\n", e);     Number *p1 = numb;     //计数，看有几组这样的数     int count = 0;     for (int i = 0; i < 504; i++) {         for (int j = 0; j < 504; j++) {             if (j != i) {                 for (int k = 0; k < 504; k++) {                     if (k != i && k !=j) {                                                  //判断3个分数的组合是否满足题意                         BOOL Y = (p1 + i)->num + (p1 + j)->num == (p1 + k)->num;                         if (Y == 1) {                             //排除符合等式，但1~9重复用得组合                             BOOL Y1 = (p1 + j)->a ==(p1 + i)->a|| (p1 + j)->b == (p1 + i)->a||(p1 + j)->c == (p1 + i)->a;                             BOOL Y2 = (p1 + k)->a ==(p1 + i)->a|| (p1 + k)->b == (p1 + i)->a||(p1 + k)->c == (p1 + i)->a;                                                          BOOL Y3 = (p1 + j)->a ==(p1 + i)->b|| (p1 + j)->b == (p1 + i)->b||(p1 + j)->c == (p1 + i)->b;                             BOOL Y4 = (p1 + k)->a ==(p1 + i)->b|| (p1 + k)->b == (p1 + i)->b||(p1 + k)->c == (p1 + i)->b;                                                          BOOL Y5 = (p1 + j)->a ==(p1 + i)->c|| (p1 + j)->b == (p1 + i)->c||(p1 + j)->c == (p1 + i)->c;                             BOOL Y6 = (p1 + k)->a ==(p1 + i)->c|| (p1 + k)->b == (p1 + i)->c||(p1 + k)->c == (p1 + i)->c;                                                          BOOL Y7 = (p1 + j)->a ==(p1 + k)->a|| (p1 + j)->b == (p1 + k)->a||(p1 + j)->c == (p1 + k)->a;                             BOOL Y8 = (p1 + j)->a ==(p1 + k)->b|| (p1 + j)->b == (p1 + k)->b||(p1 + j)->c == (p1 + k)->b;                             BOOL Y9 = (p1 + j)->a ==(p1 + k)->c|| (p1 + j)->b == (p1 + k)->c||(p1 + j)->c == (p1 + k)->c;                                                          BOOL Y10 = Y1 || Y2 || Y3 || Y4 || Y5 || Y6 || Y7 || Y8 || Y9;                             if (Y10 != 1) {                                 //打印符合要求的组合                                 printf("(%f,%d,%d,%d)\n", (p1 + i)->num, (p1 + i)->a, (p1 + i)->b, (p1 + i)->c);                                 printf("(%f,%d,%d,%d)\n", (p1 + j)->num, (p1 + j)->a, (p1 + j)->b, (p1 + j)->c);                                 printf("(%f,%d,%d,%d)\n", (p1 + k)->num, (p1 + k)->a, (p1 + k)->b, (p1 + k)->c);                                 printf("\n");                                                                  count++;                             }                         }                     }                 }             }         }     }     printf("总共有%d组合\n", count);          return 0; }

//总共有11194组合 #import <Foundation/Foundation.h>  //得到分数和组成分数的3个数 typedef struct number{     float num;     int a;     int b;     int c; }Number;  int main(int argc, const char * argv[]) {     //504，是因为C(9, 3)*6 = 504     Number numb[504] = {0};     int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};     int *p = a;     int e = 0;     //得到所有分数     for (int i = 0; i < 9; i++) {         for (int j = 0; j < 9; j++) {             for (int k = 0; k < 9; k++) {                 if (j != i && k != i && k != j) {                     //分子                     float molecular = *(p + i);                     //分母                     int denominator = *(p + j) * 10 + *(p + k);                     //将分数和构成分数的3个数存储到结构体中                     numb[e].num = (molecular / denominator);                     numb[e].a = *(p + i);                     numb[e].b = *(p + j);                     numb[e].c = *(p + k);                     //计算分数的个数                     e++;                 }             }         }              }     //确认下组成的分数是不是504个     printf("\n%d\n", e);     Number *p1 = numb;     //计数，看有几组这样的数     int count = 0;     for (int i = 0; i < 504; i++) {         for (int j = 0; j < 504; j++) {             if (j != i) {                 for (int k = 0; k < 504; k++) {                     if (k != i && k !=j) {                         //判断3个分数的组合是否满足题意                         BOOL Y = (p1 + i)->num + (p1 + j)->num == (p1 + k)->num;                         if (Y == 1) {                             printf("(%f,%d,%d,%d)\n", (p1 + i)->num, (p1 + i)->a, (p1 + i)->b, (p1 + i)->c);                             printf("(%f,%d,%d,%d)\n", (p1 + j)->num, (p1 + j)->a, (p1 + j)->b, (p1 + j)->c);                             printf("(%f,%d,%d,%d)\n", (p1 + k)->num, (p1 + k)->a, (p1 + k)->b, (p1 + k)->c);                             printf("\n");                                                          count++;                         }                     }                 }             }         }     }     printf("总共有%d组合\n", count);          return 0; }

用递归得到所有排列， 对每种排列判断是否满足条件。  #include <iostream> #include <algorithm> //std::swap  bool judge(int(&vec)[9]){ 	//vec[2]/(10*vec[0] + vec[1]) + vec[5]/(10*vec[3] + vec[4]) = vec[8]/(10*vec[6] + vec[7])    int left  = (10* vec[0]+vec[1])*(10*vec[3] + vec[4])*vec[8];    int right = (10*vec[6] + vec[7]) * ( vec[2]*(10*vec[3] + vec[4] )+vec[5] * (10*vec[0]+vec[1])) ;    return left == right;	 } inline  void solve_aux(int(&vec)[9], int level) {   if(level < 1){      if(judge(vec)){        int i = 0;        for(; i + 1 < 9; ++i){          std::cout << vec[i] << ",";        }         std::cout << vec[i] <<std::endl;      }   }else{       for(int i = 0; i < level; ++i){          std::swap(vec[i], vec[level-1]);          solve_aux(vec,level-1);          std::swap(vec[i], vec[level-1]);       }   } }  inline  void solve(int(&vec)[9]) {    solve_aux(vec, 9);	 }  int main(){    int vec[] = { 1,2,3,4,5,6,7,8,9 };    solve(vec);     return 0;	 }   //vec[2]/(10*vec[0] + vec[1]) + vec[5]/(10*vec[3] + vec[4]) = vec[8]/(10*vec[6] + vec[7]) 5,6,4,9,8,7,2,1,3 9,8,7,5,6,4,2,1,3 2,6,5,7,8,9,1,3,4 7,8,9,2,6,5,1,3,4 7,8,5,2,6,1,3,9,4 2,6,1,7,8,5,3,9,4 4,8,7,9,6,1,3,2,5 9,6,1,4,8,7,3,2,5 3,4,9,6,8,2,1,7,5 6,8,2,3,4,9,1,7,5 9,6,7,3,2,1,4,8,5 3,2,1,9,6,7,4,8,5 3,9,4,7,8,1,5,2,6 7,8,1,3,9,4,5,2,6 5,1,9,6,8,2,3,4,7 6,8,2,5,1,9,3,4,7 9,6,5,3,2,1,8,4,7 3,2,1,9,6,5,8,4,7 3,4,6,5,1,8,2,7,9 5,1,8,3,4,6,2,7,9

首先九次循环遍历出所有分数和相同的情况 然后再选出九次循环都不想等的情况 具体怎么实现自己想吧


Question: 有一条C语言的语句看不懂，请高手帮我开脑洞

引用 3 楼 laery 的回复:#define _INTSIZEOF(n)   ((int)(sizeof(n) +sizeof(nt)-1)/ sizeof(int)) * sizeof(int)) 二楼兄应该要这样写吧? 感谢一楼的，帮我开脑洞. 分数不多，没技术分了，各10分，意思意思。 恩。

写成这样的话， 估计你就明白了  #define _INTSIZEOF(n)   (sizeof(n) + sizeof(int) - 1) / sizeof(int)

sizeof(int) - 1 = 3，所以一个数 & ~(sizeof(int) - 1)，就是将那个数的最低的三位清0，那么这个数的二进制形式一定变成了xxxxxx000b所以一定是4的倍数。而将这底三位清0有可能将原数减小，最多减小3（清0的那三位原本都是1的情况），所以前面要+(sizeof(int) - 1)。


Question: 为什么Procmon这个文件监控系统没有.SYS文件

在资源里面, 它运行时候再加载的

哪里没有？你看这个软件自己的行为呢


Question: 两句话难倒n多朋友圈

谢谢大家了,,,大神都出现了!非常感谢.

1.指针数组中p[0]中存放a的地址。 2.&p[0]表示取p[0]中指向a那个指针的地址，是一个二级指针。 好像楼上已经有朋友说得很清楚了。

引用 15 楼 u010165006 的回复:[quote=引用 14 楼 lin5161678 的回复:] [quote=引用 13 楼 u010165006 的回复:] [quote=引用 12 楼 lin5161678 的回复:] [quote=引用 3 楼 u010165006 的回复:] p[0]==*(p+0)==*p，两边取地址有： &p[0]==p，p就是数组元素p[0]的地址就是数组的首地址。 p[i]==*(p+i)，两边取地址有： &p[i]==p+i，元素p[i]的地址就是数组首地址p偏移i（p+i） 这个例子里&p应该是没有意义的。为什么你会有 &p 没意义的错觉[/quote] p是数组首地址，&p代表什么呢？[/quote] 一个数组指针啊  [/quote] 好像用处不大吧？一般传递数组首地址，传递数组指针在什么时候呢？[/quote]和你讨论的是 &p代表什么 而不是 有什么用处

引用 12 楼 lin5161678 的回复:[quote=引用 3 楼 u010165006 的回复:] p[0]==*(p+0)==*p，两边取地址有： &p[0]==p，p就是数组元素p[0]的地址就是数组的首地址。 p[i]==*(p+i)，两边取地址有： &p[i]==p+i，元素p[i]的地址就是数组首地址p偏移i（p+i） 这个例子里&p应该是没有意义的。为什么你会有 &p 没意义的错觉[/quote] p是数组首地址，&p代表什么呢？

引用 3 楼 u010165006 的回复:p[0]==*(p+0)==*p，两边取地址有： &p[0]==p，p就是数组元素p[0]的地址就是数组的首地址。 p[i]==*(p+i)，两边取地址有： &p[i]==p+i，元素p[i]的地址就是数组首地址p偏移i（p+i） 这个例子里&p应该是没有意义的。为什么你会有 &p 没意义的错觉

折问题问的，一下子拉低整个CSDN的智值

引用 14 楼 lin5161678 的回复:[quote=引用 13 楼 u010165006 的回复:] [quote=引用 12 楼 lin5161678 的回复:] [quote=引用 3 楼 u010165006 的回复:] p[0]==*(p+0)==*p，两边取地址有： &p[0]==p，p就是数组元素p[0]的地址就是数组的首地址。 p[i]==*(p+i)，两边取地址有： &p[i]==p+i，元素p[i]的地址就是数组首地址p偏移i（p+i） 这个例子里&p应该是没有意义的。为什么你会有 &p 没意义的错觉[/quote] p是数组首地址，&p代表什么呢？[/quote] 一个数组指针啊  [/quote] 好像用处不大吧？一般传递数组首地址，传递数组指针在什么时候呢？

引用 13 楼 u010165006 的回复:[quote=引用 12 楼 lin5161678 的回复:] [quote=引用 3 楼 u010165006 的回复:] p[0]==*(p+0)==*p，两边取地址有： &p[0]==p，p就是数组元素p[0]的地址就是数组的首地址。 p[i]==*(p+i)，两边取地址有： &p[i]==p+i，元素p[i]的地址就是数组首地址p偏移i（p+i） 这个例子里&p应该是没有意义的。为什么你会有 &p 没意义的错觉[/quote] p是数组首地址，&p代表什么呢？[/quote] 一个数组指针啊

type arr[N]; ⒈数组名 arr 作为右值使用，被弱化为指针，等同于 &arr[0]； ⒉取数组的第一个元素地址，同上。 ⒊数组名取地址 &arr 严格来说这种写法不正确，不过大多编译器均视作合法且与 arr 相等； ⒋第一个元素的值 arr[0]，arr 等于 &arr[0]，等于第一个元素的地址。

一段话解决所有指针问题： 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495

标题党

一样就鬼了。

引用 6 楼 jack960330 的回复:楼上+1......大神+++

搞文字游戏呢！

一个是a的一级指针，一个a的二级指针，值能相同？

标题党。。。  p[0]里存的是a的地址啊，自然和p的地址不同啦，呵呵。


Question: Shuffling Machine

帮结帖＋蹭分

问题已解决，所以还是结帖吧

修正一个地方 for(i=0;i<MAX;i++) {  scanf("%d",&order[i]); } 这部分语句因为我图方便声明oder[]的时候就已经初始化了


Question: 这个随机数程序为什么输出结果始终确定，能讲一下原理吗？？？

我来把程序丰富一下，我们来观察一下细节：  #include<stdio.h> #include<stdlib.h> #include<time.h> #define TIMES 6000000   struct T{int key,value;};   void main() {     time_t t;     int i,k1,k2;     struct T a[12]; 	int dice1[6]={0}; 	int dice2[6]={0};      for(i=0;i<12;i++)     {         a[i].key=i+1;         a[i].value=0;     }     srand((unsigned)time(&t));     for(i=0;i<TIMES;i++)     {                   int v=(k1=rand()%6+1)+(k2=rand()%6+1);         a[v-1].value++; 		dice1[k1-1]++; 		dice2[k2-1]++; 	}     for(i=0;i<12;i++)         printf("%2d:%.2f\n",a[i].key,(double)a[i].value/TIMES);      for(i=0;i<6;i++) 		printf("dice1[%d] = %d\n",i+1,dice1[i]);  	for(i=0;i<6;i++) 		printf("dice2[%d] = %d\n",i+1,dice2[i]); }   执行结果：   由此可见，这个程序其实就是个掷骰子的程序，掷两个骰子，掷6000000次，观察骰子值的分布情况。 我的程序新增了对两个骰子单独的值的观察， 可以看到，当次数足够大时，rand函数可以保证每个骰子的值从1到6分布比较均匀， 那么两个骰子的值之和就完全符合正态分布的概率原则了，这是可以用概率的方法算出来的。 不是说随机数程序的结果就一定是随机的，如果是计算概率，那么结果就是确定的。 你可以观察一下，每次执行时a[i].value，每次也都有细微的差别，但是一除以6000000，就被掩盖了。

本来就是大量实验之后结果就趋向某个确定的情况。

引用 2楼user-3 的回复:k的取值为1-11，且每种可能性相同 次数越多，结果就越接近数学概率值它是用的哪个数学公式或模型啊？

k的取值为1-11，且每种可能性相同 次数越多，结果就越接近数学概率值


Question: fseek(fp, 0L, 1) 的疑问

引用 3 楼 u013351484 的回复:[quote=引用 2 楼 ant2012 的回复:] 如果注释掉fwrite函数下面的fseek()函数，程序会死循环  这个问题可能是文件指针有两个，一个写指针，一个读指针，当写数据时，读指针不会动，这样就造成了读一个数据，读指针回到初始位置，而写数据时，读指针不变，这样就死循环了这样讲的话似乎可以解释地通，但读写文件时指向文件的那个fp指针又分为读指针跟写指针这个又不好理解了，还需要在以后查阅更多资料，谢谢啦~[/quote]  文件指针是用来标记当前读写数据在文件中的位置，至于是否存在读写指针，我也不太清楚，我在用fstream(c++中的文件流类)中有两个seek函数，seekg()和 seekp()，一个是定位读位置，一个是定位写位置

引用 2 楼 ant2012 的回复:如果注释掉fwrite函数下面的fseek()函数，程序会死循环  这个问题可能是文件指针有两个，一个写指针，一个读指针，当写数据时，读指针不会动，这样就造成了读一个数据，读指针回到初始位置，而写数据时，读指针不变，这样就死循环了这样讲的话似乎可以解释地通，但读写文件时指向文件的那个fp指针又分为读指针跟写指针这个又不好理解了，还需要在以后查阅更多资料，谢谢啦~

fread((char *)&rec, sizeof(rec), 1, fp) 第一个参数不应该是(record *)&rec吗，为何是(char *)&rec？ 任何指针变量都是一样的，都存放的是内存地址，写成（int*）都行 楼主可以查看fread的函数定义： size_t fread( void *buffer, size_t size, size_t count, FILE *stream );


Question: 指针作为函数返回值所在的内存区域

p3是指针变量，其指向的是"qwer2"字符常量，p1 = getStr1();时，p3把他的值（字符常量的地址）已经传给了p1，函数执行结束，p3变量释放 p4是数组，其保存了字符常量的内容（不是地址），当执行p2 = getStr2();时，p4仅仅是把p4数组的首地址给了p2，函数执行结束，p4数组被释放，所以p2保存的是一个无效的地址  说白了，p1得到的是字符串常量的地址，百p2得到 的是数组p4的地址，字符串常量的生命周期是整个程序的周期

p3是一个指针变量，这个指针变量在栈里，但是他指向的常量字符串不在栈里。


Question: 使用#ifndef跳过程序代码块的问题

我明白了，谢谢七楼。

一定要在main{}里面吗，为什么

你的代码段写到了main函数外面，这样是不行的，兄弟。

这是我的程序和出错提示。 #include<stdio.h> #ifndef _SKIP_  #define _SKIP_ 	int a=3;  	int * p=&a; 	printf("a=%d\tp=%p\n",a,p); 	printf("%d\n",*p); #endif void main(void) {         int a=3;         int * p=&a;         printf("a=%d\tp=%p\n",a,p);         printf("%d\n",*p);  	puts("hello,world!");  }  F:\my c project\c file\even.c(16) : error C2143: syntax error : missing ')' before 'string' F:\my c project\c file\even.c(16) : error C2143: syntax error : missing '{' before 'string' F:\my c project\c file\even.c(16) : error C2059: syntax error : '<Unknown>' F:\my c project\c file\even.c(16) : error C2059: syntax error : ')' F:\my c project\c file\even.c(17) : error C2143: syntax error : missing ')' before 'string' F:\my c project\c file\even.c(17) : error C2143: syntax error : missing '{' before 'string' F:\my c project\c file\even.c(17) : error C2059: syntax error : '<Unknown>' F:\my c project\c file\even.c(17) : error C2059: syntax error : ')' Error executing cl.exe.  even.exe - 8 error(s), 0 warning(s)

二楼，好像是这样的，我的情况跟你描述的差不多，就是在跳过的代码块当中有定义局部变量，在#endif之后有使用到，你跳过了局部变量的定义，就导致变量未定义。可是如果不这样，那它是怎么跳过代码块的呢，或者说，它跳过代码块是什么意思？

把编译错误的信息贴上来吧，也可能是编译器的问题。

我写了个小例子，vs2010运行OK，请参考：   #include <stdio.h>  #define _SKIP_  void main() {  #ifndef _SKIP_ 	printf("Should be skipped!\n"); #endif   	printf("Hello World!\n"); }

编译出错 ， 你要把错误信息贴出来  比如可能是你跳过的代码块当中有定义局部变量，在#endif之后有使用到，你跳过了局部变量的定义，就导致变量未定义

编译什么提示？看起来没错的。 另外， 要绝对跳过可以：  #if 0 //  跳过的代码 #endif


Question: macbook终端上c程序编译后的out文件为何被killed？

引用 1 楼 stupid_boy2007 的回复:gcc -c 只编译,不生成可执行文件，你应该用: gcc helloworld.c -o helloworld.out ./helloworld.out 现在最新的系统都使用clang了。  我按你说的做了，果然成功了，谢谢。 我记得昨天也生成过.out的，还是被killed，也不显示是是exec文件，今天就显示是exec文件了，不管怎么样，成功就好。谢谢了。


Question: C语言求π的值

引用 10 楼 ant2012 的回复:楼主，你应该是理解错了，直到最后一项的值小于给定阈值，那个小于给定阈值的值也加上，应该就对了嗯嗯，我再试一试！

不过，楼主，当精度过小时，注意整形long越界的问题，long在32位机以上的操作系统占4个字节

引用 7 楼 user-2的回复:我是这么认为的：应该是大数吃小数的现象吧，可以考虑用khan's算法，我没验证过，只是想大概是这个原因 没听说过呢！

你的编译运行的结果是什么样子的呢？

那就不清楚了，也有可能是算法的问题，你自己先用计算器算算

0.01   对应的正确数字应该是     3.132157           但是运行得到的却是   3.121501

错了，是测试数据的答案不一样!

怎么会没有输出呢

怎么没有输出了呢？                            —————————————————————你刚才的解答是正确的！惊醒梦中人！

b=b*(b+2);  错了 当b = 3时，b = 3*5没错，可是下一个循环，b = 15了，b = 15 * 17了。 改成 b=b*(i*2+1)


Question: C语言 内存

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

// 这种方式是禁止使用的 // 在自定义函数中 返回一个在函数中开辟空间的地址 // 因为此时的地址已经被系统销毁掉 char *test(void)  {     // char  name[] = "iPhone";      char * name = "iPhone";  //这样是可行的，想想为什么      printf("name = %p\n", name);      return name;  }

你这是什么问题，请说清楚点吧！


Question: C语言结果对齐

printf Width Specification The second optional field of the format specification is the width specification. The width argument is a nonnegative decimal integer controlling the minimum number of characters printed. If the number of characters in the output value is less than the specified width, blanks are added to the left or the right of the values — depending on whether the – flag (for left alignment) is specified — until the minimum width is reached. If width is prefixed with 0, zeros are added until the minimum width is reached (not useful for left-aligned numbers).  The width specification never causes a value to be truncated. If the number of characters in the output value is greater than the specified width, or if width is not given, all characters of the value are printed (subject to the precision specification).  If the width specification is an asterisk (*), an int argument from the argument list supplies the value. The width argument must precede the value being formatted in the argument list. A nonexistent or small field width does not cause the truncation of a field; if the result of a conversion is wider than the field width, the field expands to contain the conversion result.  作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

这个 tab键的宽度问题， 如果在linux 下，可以考虑用这种方式加大tab 宽度 设置为 4个字符宽度： tabs 4   echo 'tabs 4' >> ~/.profile

在没对齐的地方再加\t就行了，请参考：   #include <stdio.h>  void main() { 	printf("Address\t\tType\tLength\tLength(Total)\tHandle\n"); 	printf("%8.8lX\t%2.2X\t%2.2X\t%4.4X\t\t%4.4X\t\n",0xFADB0,0,0x18,0x4c,0); }   在vs2010上的输出结果为：


Question: 通信协议

两个字节的校验码，crc16校验概率比较大

#include <stdio.h> unsigned char b[]={'\x0a','\xaa','\xf0','\x00','\x00','\x01','\x05','\x55'}; unsigned short getus(unsigned char *p) {     unsigned short us;     unsigned char *pus;      pus=(unsigned char *)&us;     pus[0]=p[1];     pus[1]=p[0];     return us; } int main() {     printf("%04hx\n",getus(b));     printf("%04hx\n",getus(b+2));     printf("%04hx\n",getus(b+4));     printf("%04hx\n",getus(b)+getus(b+2)+getus(b+4));     printf("%04hx\n",getus(b+6));     printf("%04hx\n",~getus(b+6)+1);     if ((unsigned short)(getus(b)+getus(b+2)+getus(b+4))==(unsigned short)(~getus(b+6)+1)) {         printf("OK\n");     } else {         printf("ERR\n");     }     return 0; } //0aaa //f000 //0001 //faab //0555 //faab //OK //


Question: c语言中怎样把一个16进制的数直接输出成16进制的结果

用putchar打印出来可以吗？

引用 1 楼 jerry_dqh 的回复:不打印字符，你想怎么打印，要性能的时候也不能使用printf  打印出来的直接是16进制的结果，就不用字符串的方式打印出来

不打印字符，你想怎么打印，要性能的时候也不能使用printf


Question: toupper

void upper(char *a) { while(*a) { *a = toupper(*a); a++; } }  这样应该更好

int toupper( int c );  参数c为输入变量

toupper的返回值是改变之后的值，参数是按值传递，不是引用传递 所以要另一个变量接收其返回的值，而这个变量的值就是变成大写后的值

int toupper(int c); // 将传入字符对应的大写字母作为返回值返回，楼主当然需要接收才能看到效果了 a[i] = toupper[i];

toupper(a[i]);的返回值才是变大写吧。你返回的值又没有保存起来


Question: 递归问题

引用 4 楼 adusuccessfully 的回复:一楼的说的正确，i++，与j--，都是先参与运算，再自增或自减~~~ 从赵四老师的回复学了一招：Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。是这样的,改成++i, --j 可以正确运行. 谢谢各位!

后置的++运算符是先用在加。谭浩强的教学还是有点用的。

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

应该reverse(s, i+1, j-1);，否则会调用函数i,j才会改变，相当于一直用相同的参数调用函数


位域？？？？


Question: qt中怎么组装udp消息呢

引用 1 楼 user-1 的回复:用QByteArray报文有固定的格式，保证QbyteArray中的长度和报文长度相同啊

用QByteArray


Question: 整数、实数编码问题

所以 printf 的参数中，float  不是32 Bits，而是64Bits

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉

输出时，printf  整数： 16Bits,32Bits 系统 32Bits以下整数：   包括 char(8Bits),short int (16Bits),int (32Bits 或者16Bits),long int(32Bits) 32Bits，16 Bits指针 其实也相当于整数 这一类参数 按照 int 长度计算 当 int 为 16 Bits时候， far *,long int 按照 32Bits 传递 否则，一律按照 int （unsigned int）传递   64Bits   超长整数 long long int (64 Bits) 按照64 Bits 传递  而 浮点数，16Bits,32Bits 系统，一般都是先传入浮点寄存器，然后传递到堆栈中（64Bits） 也就是说，其实 float,double 都是先转为 64Bits 浮点数(double)，然后传递

浮点型存储格式和整形不一样，不要在printf中直接用整形格式输出浮点型数据，楼主可看看这个： http://wenku.baidu.com/link?url=L02xDSxpKp2tJSMbxQEvkyb_O_SPlvdwPvbrqULO94MNycea2bnDcpV8gRcDQh78mMTJ1ixYhZc_a84s4VbdPIlJGDwoJBMh-0mK_Vx5Gby


Question: unsigned char i=0x80;  	printf("0x%x\n", ~i>>3+1);//无符号16进制输出 	 char ci=0x80;

楼主，对数据取返前，会将数据转换成整形，再取反

你自己先确定各个操作符的优先级, 然后手动计算, 注意有符号的情况


Question: unsigned char i=0x80;  	printf("0x%x\n", ~i>>3+1);//无符号16进制输出 	 char ci=0x80;

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c

1) 移位操作优先级最低, 所以都是右移4位, 取反优先级最高, 最先做 2) 整形提升, uchar会提升到uint, 而char会提升到int, 所以0x80在uint中还是0x80, 而在int为0xffffff80, 它们取反的结果就不同了

取反操作前，字符型数据会自动转成整形 即 i = 0x00000080 ~i 为 0xffffff7f ~i>>3+1 由于+号运算符优先级比>>位移运算符高，所以~i>>3+1等价于~i>>4，则得到0xfffffff7  ci变量也一样，先转换成整形，为0xffffff80(因为ci为有符号型字符变量，且符号位为1，转成整形时，高位补1) 之后同理


Question: unsigned char i=0x80;  	printf("0x%x\n", ~i>>3+1);//无符号16进制输出 	 char ci=0x80;

小伙 你想说明什么呢？

小伙 你想说明什么呢？


Question: 如何使用windows证书库中加载证书   给openssl  使用。   求指点啊

boost error_code 返回的 错误信息 是 https proxy request

错误代码： 336027803        第一次使用openssl 开发坏境boost vs2013

系统API有无检查返回值和错误值？


Question: C语言编程变量无故自动更改

不是你说没有操作就没有操作的

学会使用数据断点是楼主的当务之急。

越界了，下写断点。

structEFCoord_t             earth                = {}; 定义变量时没有初始化，你打印时取到的值都是内存中的随机值，所以可能有变化，建议定义变量时初始化一下。 如 定义完变量后加上这句 memset（&earth，0，sizeof（structEFCoord_t  ））；应该就行了

看不出, 不过earth是个自动变量, 可能是栈数组操作越界, 修改了它

i<=SECTION_NUM  下标是否越界了


Question: C语言菜鸟求助

最后一个for循环有问题

void fun5() {     int n = 0;     scanf("%d", &n);          for (int i = 1; i <= 2* n - 1; i++) {         int t = i > n ? 2*n - i : i;                  for (int i1 = 1; i1 <= n - t; i1++) {             printf(" ");         }                  for (int i2  = 1; i2 <= 2 * t - 1; i2++) {             printf("*");         }         printf("\n");              } }

高手都是这么晚也在玩程序的吗.?

谢谢各位的帮助！

最后一个for（）循环有问题吧！

你好。 可以参看我的这篇博客。 http://blog.csdn.net/zidane_2014/article/details/39208855

最后一个for循环的循环条件写掉了一个小于号。（再水一贴！）


Question: YModem协议

剩余内容在第二个包里面带过去呗


Question: 如何读取一个文件中的字符串，然后删除它

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。

read file into list iterate on the list, post, remove item post succeeded write file from list

修改文件都是比较复杂的.  最简单的处理办法, 就是读取到内存, 然后再删除掉不需要的, 再写回去.

可以将文件的所有数据都读出来，然后删除指定的数据，再写回去


Question: 无法跳出函数体问题求教!~!

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

void main() {     int n;     menu();     scanf("%d", &n);     while(n)  //循环内部没有提供重新输入n的机会, 一但你第一次输入了一个大于0的数, n就永远为非0, 就死循环了.     {         switch(n)         {         case 0: exit(0);          case 1: in(); break;             //    case 2: search(); break;             //    case 3: del(); break;             //    case 4: modify(); break;             //    case 5: insert(); break;             //    case 6: order(); break;             //    case 7: total(); break;             //    case 8: show(); break;         default : break;         }     }     getch();     menu();     scanf("%d", &n); }

可以考虑使用goto语句

楼上正解。 你的break只是跳出switch。 但是while一直循环。 所以就会出错。

不是无法跳出，是跳出后又进入了in()函数。在你的主函数里一直在while


Question: C文件操作如何使文件指针找到文件末尾

fopen, _wfopen Open a file.  FILE *fopen( const char *filename, const char *mode );  FILE *_wfopen( const wchar_t *filename, const wchar_t *mode );  Function Required Header Compatibility  fopen <stdio.h> ANSI, Win 95, Win NT  _wfopen <stdio.h> or <wchar.h> Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    The c, n, and t mode options are Microsoft extensions for fopen and _fdopen and should not be used where ANSI portability is desired.  Return Value  Each of these functions returns a pointer to the open file. A null pointer value indicates an error.   Parameters  filename  Filename  mode  Type of access permitted  Remarks  The fopen function opens the file specified by filename. _wfopen is a wide-character version of fopen; the arguments to _wfopen are wide-character strings. _wfopen and fopen behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tfopen fopen fopen _wfopen    The character string mode specifies the type of access requested for the file, as follows:  "r"  Opens for reading. If the file does not exist or cannot be found, the fopen call fails.  "w"  Opens an empty file for writing. If the given file exists, its contents are destroyed.  "a"  Opens for writing at the end of the file (appending) without removing the EOF marker before writing new data to the file; creates the file first if it doesn’t exist.  "r+"  Opens for both reading and writing. (The file must exist.)  "w+"  Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed.  "a+"  Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn’t exist.  When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus, existing data cannot be overwritten.  The "a" mode does not remove the EOF marker before appending to the file. After appending has occurred, the MS-DOS TYPE command only shows data up to the original EOF marker and not any data appended to the file. The "a+" mode does remove the EOF marker before appending to the file. After appending, the MS-DOS TYPE command shows all data in the file. The "a+" mode is required for appending to a stream file that is terminated with the CTRL+Z EOF marker.  When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired.  In addition to the above values, the following characters can be included in mode to specify the translation mode for newline characters:  t  Open in text (translated) mode. In this mode, CTRL+Z is interpreted as an end-of-file character on input. In files opened for reading/writing with "a+", fopen checks for a CTRL+Z at the end of the file and removes it, if possible. This is done because using fseek and ftell to move within a file that ends with a CTRL+Z, may cause fseek to behave improperly near the end of the file.   Also, in text mode, carriage return–linefeed combinations are translated into single linefeeds on input, and linefeed characters are translated to carriage return–linefeed combinations on output. When a Unicode stream-I/O function operates in text mode (the default), the source or destination stream is assumed to be a sequence of multibyte characters. Therefore, the Unicode stream-input functions convert multibyte characters to wide characters (as if by a call to the mbtowc function). For the same reason, the Unicode stream-output functions convert wide characters to multibyte characters (as if by a call to the wctomb function).  b  Open in binary (untranslated) mode; translations involving carriage-return and linefeed characters are suppressed.   If t or b is not given in mode, the default translation mode is defined by the global variable _fmode. If t or b is prefixed to the argument, the function fails and returns NULL.   For more information about using text and binary modes in Unicode and multibyte stream-I/O, see Text and Binary Mode File I/O and Unicode Stream I/O in Text and Binary Modes.  c  Enable the commit flag for the associated filename so that the contents of the file buffer are written directly to disk if either fflush or _flushall is called.  n  Reset the commit flag for the associated filename to “no-commit.” This is the default. It also overrides the global commit flag if you link your program with COMMODE.OBJ. The global commit flag default is “no-commit” unless you explicitly link your program with COMMODE.OBJ.  Valid characters for the mode string used in fopen and _fdopen correspond to oflag arguments used in _open and _sopen, as follows.  Characters in mode String Equivalent oflag Value for _open/_sopen   a _O_WRONLY | _O_APPEND (usually _O_WRONLY | _O_CREAT | _O_APPEND)  a+ _O_RDWR | _O_APPEND (usually _O_RDWR | _O_APPEND | _O_CREAT )  r _O_RDONLY  r+ _O_RDWR  w _O_WRONLY (usually _O_WRONLY | _O_CREAT | _O_TRUNC)  w+ _O_RDWR (usually _O_RDWR | _O_CREAT | _O_TRUNC)  b _O_BINARY  t _O_TEXT  c None  n None    Example  /* FOPEN.C: This program opens files named "data"  * and "data2".It  uses fclose to close "data" and  * _fcloseall to close all remaining files.  */  #include <stdio.h>  FILE *stream, *stream2;  void main( void ) {    int numclosed;     /* Open for read (will fail if file "data" does not exist) */    if( (stream  = fopen( "data", "r" )) == NULL )       printf( "The file 'data' was not opened\n" );    else       printf( "The file 'data' was opened\n" );     /* Open for write */    if( (stream2 = fopen( "data2", "w+" )) == NULL )       printf( "The file 'data2' was not opened\n" );    else       printf( "The file 'data2' was opened\n" );     /* Close stream */    if( fclose( stream ) )       printf( "The file 'data' was not closed\n" );     /* All other files are closed: */    numclosed = _fcloseall( );    printf( "Number of files closed by _fcloseall: %u\n", numclosed ); }   Output  The file 'data' was opened The file 'data2' was opened Number of files closed by _fcloseall: 1   Stream I/O Routines  See Also   fclose, _fdopen, ferror, _fileno, freopen, _open, _setmode

引用 3 楼 Saiko_YAMP 的回复:[quote=引用 2 楼 zilaishuichina 的回复:] 直接移动到末尾用 fseek 判断是否移动到末尾用 feof 	int n=1; 	INT_PTR nRes;    	nRes = MessageBox(_T("您确定要进行添加吗？"), _T(""), MB_OKCANCEL | MB_ICONQUESTION); 	Cdata cdata(eat,transport,life,Else,month,day); 	FILE *fp; 	if(n==1){ 		if((fp=fopen("data.txt","wb"))==NULL){ 			exit(0); 		} 		for(;feof(fp);) 		{ 			fseek(fp,1L,1); 		} 		 			fprintf(fp,"%f %f %f %f %f %f\n", 			cdata.eat, 			cdata.transport, 			cdata.life, 			cdata.Else, 			cdata.month, 			cdata.day); 		INT_PTR nRess; 		nRess=MessageBox(_T("文件写入成功！"), _T(""), MB_OK); 		 		fclose(fp); 	} 我的这段代码是怎么了？为什么每次写入文件都会把之前的代码删掉重写[/quote]  fopen的mode有下列几种形态字符串: r 以只读方式打开文件，该文件必须存在。 r+ 以可读写方式打开文件，该文件必须存在。 rb+ 读写打开一个二进制文件，允许读写数据，文件必须存在。 w 打开只写文件，若文件存在则文件长度清为0，即该文件内容会消失。若文件不存在则建立该文件。 w+ 打开可读写文件，若文件存在则文件长度清为零，即该文件内容会消失。若文件不存在则建立该文件。 a 以附加的方式打开只写文件。若文件不存在，则会建立该文件，如果文件存在，写入的数据会被加到文件尾，即文件原先的内容会被保留。（EOF符保留） a+ 以附加方式打开可读写的文件。若文件不存在，则会建立该文件，如果文件存在，写入的数据会被加到文件尾后，即文件原先的内容会被保留。 （原来的EOF符不保留） wb 只写打开或新建一个二进制文件；只允许写数据。 wb+ 读写打开或建立一个二进制文件，允许读和写。 ab+ 读写打开一个二进制文件，允许读或在文件末追加数据。 wx 创建文本文件,只允许写入数据.[C11] wbx 创建一个二进制文件,只允许写入数据.[C11] w+x 创建一个文本文件,允许读写.[C11] wb+x 创建一个二进制文件,允许读写.[C11] w+bx 和"wb+x"相同[C11]

楼上正解， 打开方式不正确

fopen("data.txt","wb") LZ还知道wb表示什么？

fopen("data.txt","wb")   // "wb"参数表示二进制写打开,并且如果文件在, 会被清除.

最好看下 MSDN 上 fopen 和 fseek 的说明：  fopen 函数的说明 fseek 函数的说明

引用 3 楼 Saiko_YAMP 的回复:[quote=引用 2 楼 zilaishuichina 的回复:] 直接移动到末尾用 fseek 判断是否移动到末尾用 feof 	int n=1; 	INT_PTR nRes;    	nRes = MessageBox(_T("您确定要进行添加吗？"), _T(""), MB_OKCANCEL | MB_ICONQUESTION); 	Cdata cdata(eat,transport,life,Else,month,day); 	FILE *fp; 	if(n==1){ 		if((fp=fopen("data.txt","wb"))==NULL){ 			exit(0); 		} 		for(;feof(fp);) 		{ 			fseek(fp,1L,1); 		} 		 			fprintf(fp,"%f %f %f %f %f %f\n", 			cdata.eat, 			cdata.transport, 			cdata.life, 			cdata.Else, 			cdata.month, 			cdata.day); 		INT_PTR nRess; 		nRess=MessageBox(_T("文件写入成功！"), _T(""), MB_OK); 		 		fclose(fp); 	} 我的这段代码是怎么了？为什么每次写入文件都会把之前的代码删掉重写[/quote]  for(;feof(fp);) { 	fseek(fp,1L,1); } 这段是啥意思？  从文件末尾写入的话，直接用 fseek(fp, SEEK_END, 0); 没有 SEEK_END 常数的话就 fseek(fp, 2, 0);  另外如果你是每次都从文件末尾写入的话，打开文件的时候直接指定追加写入就可以： fp=fopen("data.txt","a+b"))

引用 3 楼 Saiko_YAMP 的回复:[quote=引用 2 楼 zilaishuichina 的回复:] 直接移动到末尾用 fseek 判断是否移动到末尾用 feof 	int n=1; 	INT_PTR nRes;    	nRes = MessageBox(_T("您确定要进行添加吗？"), _T(""), MB_OKCANCEL | MB_ICONQUESTION); 	Cdata cdata(eat,transport,life,Else,month,day); 	FILE *fp; 	if(n==1){ 		if((fp=fopen("data.txt","wb"))==NULL){ 			exit(0); 		} 		for(;feof(fp);) 		{ 			fseek(fp,1L,1); 		} 		 			fprintf(fp,"%f %f %f %f %f %f\n", 			cdata.eat, 			cdata.transport, 			cdata.life, 			cdata.Else, 			cdata.month, 			cdata.day); 		INT_PTR nRess; 		nRess=MessageBox(_T("文件写入成功！"), _T(""), MB_OK); 		 		fclose(fp); 	} 我的这段代码是怎么了？为什么每次写入文件都会把之前的数据删掉重写[/quote].

引用 2 楼 zilaishuichina 的回复:直接移动到末尾用 fseek 判断是否移动到末尾用 feof 	int n=1; 	INT_PTR nRes;    	nRes = MessageBox(_T("您确定要进行添加吗？"), _T(""), MB_OKCANCEL | MB_ICONQUESTION); 	Cdata cdata(eat,transport,life,Else,month,day); 	FILE *fp; 	if(n==1){ 		if((fp=fopen("data.txt","wb"))==NULL){ 			exit(0); 		} 		for(;feof(fp);) 		{ 			fseek(fp,1L,1); 		} 		 			fprintf(fp,"%f %f %f %f %f %f\n", 			cdata.eat, 			cdata.transport, 			cdata.life, 			cdata.Else, 			cdata.month, 			cdata.day); 		INT_PTR nRess; 		nRess=MessageBox(_T("文件写入成功！"), _T(""), MB_OK); 		 		fclose(fp); 	} 我的这段代码是怎么了？为什么每次写入文件都会把之前的代码删掉重写

直接移动到末尾用 fseek 判断是否移动到末尾用 feof

fseek()


Question: CPP里的多源代码文件程序的编译，看过以前的贴，但都找不到解决方法

路径中不要有中文，不要有空格。

引用 9 楼 赵4老师的回复:程序员的常识之一：不要将程序源代码或项目或exe放在桌面这种复杂（多半带空格和汉字且在防火墙或杀毒软件严密控制的C盘上）的目录下。 嗯嗯，所以都放在非系统盘上了

引用 3 楼 bsnry 的回复:[quote=引用 2 楼 ant2012 的回复:] 全局变量和全局函数默认情况下的可见性是当前文件，要想跨文件访问，在声明时前加extern.  解决方法： 在hotel.h中的 int menu (void); int getnights (void); void showprice (double, int); 改为 extern int menu (void); extern int getnights (void); extern void showprice (double, int);  函数前面，extern可以默认不写。  估计楼主遭遇的问题，不是这个。  由于楼主是采用ide编译链接，所以不要判断。  但是从编译的输出结果来猜测：  host.c这个文件很可能没有添加到 codeblocks里。  建议楼主用gcc命令进行编译  gcc -o test  -g -Wall host.c main.c 试试这个命令再说。 [/quote] windows下改成这个： gcc -o test.exe   -g -Wall hotel.c main.c

引用 2 楼 ant2012 的回复:全局变量和全局函数默认情况下的可见性是当前文件，要想跨文件访问，在声明时前加extern.  解决方法： 在hotel.h中的 int menu (void); int getnights (void); void showprice (double, int); 改为 extern int menu (void); extern int getnights (void); extern void showprice (double, int);  函数前面，extern可以默认不写。  估计楼主遭遇的问题，不是这个。  由于楼主是采用ide编译链接，所以不要判断。  但是从编译的输出结果来猜测：  host.c这个文件很可能没有添加到 codeblocks里。  建议楼主用gcc命令进行编译  gcc -o test  -g -Wall host.c main.c 试试这个命令再说。

工程所在文件夹名中不要有空格、中文字符

编译日志里面没有编译hotel.c,工程里没这文件吗

引用 5 楼 lin747356460 的回复:[quote=引用 4 楼 bsnry 的回复:] [quote=引用 3 楼 bsnry 的回复:] [quote=引用 2 楼 ant2012 的回复:] 全局变量和全局函数默认情况下的可见性是当前文件，要想跨文件访问，在声明时前加extern.  解决方法： 在hotel.h中的 int menu (void); int getnights (void); void showprice (double, int); 改为 extern int menu (void); extern int getnights (void); extern void showprice (double, int);  函数前面，extern可以默认不写。  估计楼主遭遇的问题，不是这个。  由于楼主是采用ide编译链接，所以不要判断。  但是从编译的输出结果来猜测：  host.c这个文件很可能没有添加到 codeblocks里。  建议楼主用gcc命令进行编译  gcc -o test  -g -Wall host.c main.c 试试这个命令再说。 [/quote] windows下改成这个： gcc -o test.exe   -g -Wall hotel.c main.c  [/quote] 我刚学C不久，这些要敲的指令不知道哪里搞。 不过我把hotel.c main.c都放在一个工程的源文件了， 现在不知道问题在哪里，我把可能出现问题的地方都放上来先。   [/quote]  没用过codeblocks  如果你对命令不熟悉的话，可以无视我的回答。因为我的回答只会误导你。  还有，如果你觉得这个问题依然无法解决的话，我建议你学习如何使用codeblocks. 这恐怕才是解决问题的根本。  代码似乎没有问题。  还有，如果在windows下，由于你的代码并没有涉及到 linux的api 的调用  所以可以暂时用visual studio 2015(微软的最新的开发工具）来编译代码。  2015甩开vc6很多条街，检测代码也是非常严格的。  当然这是权宜之计。

引用 4 楼 bsnry 的回复:[quote=引用 3 楼 bsnry 的回复:] [quote=引用 2 楼 ant2012 的回复:] 全局变量和全局函数默认情况下的可见性是当前文件，要想跨文件访问，在声明时前加extern.  解决方法： 在hotel.h中的 int menu (void); int getnights (void); void showprice (double, int); 改为 extern int menu (void); extern int getnights (void); extern void showprice (double, int);  函数前面，extern可以默认不写。  估计楼主遭遇的问题，不是这个。  由于楼主是采用ide编译链接，所以不要判断。  但是从编译的输出结果来猜测：  host.c这个文件很可能没有添加到 codeblocks里。  建议楼主用gcc命令进行编译  gcc -o test  -g -Wall host.c main.c 试试这个命令再说。 [/quote] windows下改成这个： gcc -o test.exe   -g -Wall hotel.c main.c  [/quote] 我刚学C不久，这些要敲的指令不知道哪里搞。 不过我把hotel.c main.c都放在一个工程的源文件了， 现在不知道问题在哪里，我把可能出现问题的地方都放上来先。


Question: c/c++语言里的errno

除了2L所说的情况外，还有perror函数的存在，即使出错也大多打印一条信息退出完事 Windows想要实现类似效果就必须先GetLastError然后FormatMessage然后输出  Windows API用GetLastError/SetLastError(Ex)而不是errno大概是考虑到兼容性， 而且这样实现线程独立（使用线程静态储存）也比较方便。 C/C++也是在C11/C++11才开始规定errno是线程静态的。

引用 4 楼 caddor9100 的回复:[quote=引用 2 楼 akirya 的回复:] 1 errno是标准C里面的 Win32 还有个 WSAGetLastError 返回值无法表示错误的时候才会用类似这种方法，这种方法很不好  2 一般都尽可能的使用返回值表示错误，或者C++异常 引用 2 楼 akirya 的回复:1 errno是标准C里面的 Win32 还有个 WSAGetLastError 返回值无法表示错误的时候才会用类似这种方法，这种方法很不好  2 一般都尽可能的使用返回值表示错误，或者C++异常   通过每个函数的返回值来获取该函数的错误码，是很不好的，我敢说很有很多错误是有共性的，  所以windows 的getlasterror设计的比较好，可以获取通用性错误。  你想指望通过每个函数返回DOWRD来获取错误码，这样的话，就把api给设计死了。  每个api都是Dword类型，这明显不符合设计思路。  所以windwos在这里做的比较好。  再如有的第三方库，也有提供一个类似的api: 获取该第三方库的错误码。如 libcurl  而linux 则不这样子做，我不清楚linux为什么不提供一个类似getlasterror的api，也更不清楚，为什么linux  大部分api 不对errno设置值。  [/quote] win32 习惯是 非0成功，0失败。 无法根据返回值确定失败原因。 linux 0成功，其他失败，则可以根据返回值知道为啥失败。 个人觉得errno GetLastError之类的设计非常屎。本来一个函数的就能完成的操作，非得再调用个方法才知道为啥。 谁知道GetLastError得到的是前一个函数的错误，还是前前函数的错误。

_doserrno, errno, _sys_errlist, and _sys_nerr These global variables hold error codes used by the perror and strerror functions for printing error messages. Manifest constants for these variables are declared in STDLIB.H as follows:  extern int _doserrno;  extern int errno;  extern char *_sys_errlist[ ];  extern int _sys_nerr;  errno is set on an error in a system-level call. Because errno holds the value for the last call that set it, this value may be changed by succeeding calls. Always check errno immediately before and after a call that may set it. All errno values, defined as manifest constants in ERRNO.H, are UNIX-compatible. The values valid for 32-bit Windows applications are a subset of these UNIX values.   On an error, errno is not necessarily set to the same value as the error code returned by a system call. For I/O operations only, use _doserrno to access the operating-system error-code equivalents of errno codes. For other operations the value of _doserrno is undefined.  Each errno value is associated with an error message that can be printed using perror or stored in a string using strerror. perror and strerror use the _sys_errlist array and _sys_nerr, the number of elements in _sys_errlist, to process error information.  Library math routines set errno by calling _matherr. To handle math errors differently, write your own routine according to the _matherr reference description and name it _matherr.  The following errno values are compatible with 32-bit Windows applications. Only ERANGE and EDOM are specified in the ANSI standard.  Constant System Error Message Value  E2BIG Argument list too long 7  EACCES Permission denied 13  EAGAIN No more processes or not enough memory or maximum nesting level reached 11  EBADF Bad file number 9  ECHILD No spawned processes 10  EDEADLOCK Resource deadlock would occur 36  EDOM Math argument 33  EEXIST File exists 17  EINVAL Invalid argument 22  EMFILE Too many open files 24  ENOENT No such file or directory 2  ENOEXEC Exec format error 8  ENOMEM Not enough memory 12  ENOSPC No space left on device 28  ERANGE Result too large 34  EXDEV Cross-device link 18

引用 2 楼 akirya 的回复:1 errno是标准C里面的 Win32 还有个 WSAGetLastError 返回值无法表示错误的时候才会用类似这种方法，这种方法很不好  2 一般都尽可能的使用返回值表示错误，或者C++异常 引用 2 楼 akirya 的回复:1 errno是标准C里面的 Win32 还有个 WSAGetLastError 返回值无法表示错误的时候才会用类似这种方法，这种方法很不好  2 一般都尽可能的使用返回值表示错误，或者C++异常   通过每个函数的返回值来获取该函数的错误码，是很不好的，我敢说很有很多错误是有共性的，  所以windows 的getlasterror设计的比较好，可以获取通用性错误。  你想指望通过每个函数返回DOWRD来获取错误码，这样的话，就把api给设计死了。  每个api都是Dword类型，这明显不符合设计思路。  所以windwos在这里做的比较好。  再如有的第三方库，也有提供一个类似的api: 获取该第三方库的错误码。如 libcurl  而linux 则不这样子做，我不清楚linux为什么不提供一个类似getlasterror的api，也更不清楚，为什么linux  大部分api 不对errno设置值。

linux中只有某些特定的系统调用在出错时才设置errno，大部分普通函数都是不设置errno的， VC++的实现我们是不可见的，但是肯定也是有errno这种机制的， 你可以把WSAGetLastError理解成取errno的函数，至于为什么这么做，可能跟他的实现机制有关， VC++并不严格遵循C++标准。

大多数情况下不关心调用失败的原因，只关心是否调用成功，所以errno用的不多


Question: 关于指针和字符数组输出的问题，稍微指导一下下

引用 2 楼 dcy652701 的回复:[quote=引用 1 楼 ant2012 的回复:] 楼主，你这句代码是不是有点问题 alGraph->vertices[i].place[i] = mid_place[i][n] ;  place[n]是不是应该为place[i]。  输出字符串，直接把字符串的首地址给输出流不就行了，如输出alGraph->vertices[i]中的字符串内容，cout<<alGraph->vertices[i].place<<endl; 谢谢，place那块我改过来了，刚才我试了，编译时出问题了，cout<<alGraph->vertices[i].place<<endl;是c++里的，我用的是c，还有什么方法呢[/quote]  那就用printf  printf("%s\n", alGraph->vertices[i].place);

引用 1 楼 ant2012 的回复:楼主，你这句代码是不是有点问题 alGraph->vertices[i].place[i] = mid_place[i][n] ;  place[n]是不是应该为place[i]。  输出字符串，直接把字符串的首地址给输出流不就行了，如输出alGraph->vertices[i]中的字符串内容，cout<<alGraph->vertices[i].place<<endl; 谢谢，place那块我改过来了，刚才我试了，编译时出问题了，cout<<alGraph->vertices[i].place<<endl;是c++里的，我用的是c，还有什么方法呢


Question: c编程遇到问题，求大牛解答！

int max_arr(int ar[],int n) { 	int max;     int i=0; 	for(max=ar[0];i<5;i++) 	{ 		if(max<=ar[i]) 			max=ar[i]; 	} 	printf("The biggest number of array is:%d\n",max); 	return max; }     这样就不会有问题，原因是 int i=0,max=ar[0]; 表示声明两个变量i、max并且初始化，而不是声明变量i=0，对max赋值这两个操作。纯语法问题。

引用 5 楼 H_Clong 的回复:就是前面说的那样   。直接在外面给max赋值就好了。在里面定义就是局部变量只在for里面有用。 外面的max没有任何改变； 你的代码和这个一样的； int max_arr(int ar[],int n) {     int max;     for(int i=0,n=ar[0];i<5;i++)     {         if(n<=ar[i])            n=ar[i];     }     printf("The biggest number of array is:%d\n",max);     return max; } 问题解决，真心感谢

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

引用 2 楼 xade 的回复:声明 max 的时候必须给一个初始值。  int max = 0; 或者 int max = ar[0];  因为这是一个函数内变量，是放在栈空间上的，你声明的时候编译器只是把栈空间留出来，并不会清理栈上的内容，很有可能这个地方原本的数据会构成一个比 ar 中所有数据都大的数，这样循环内永远都不会执行 if 后面的操作，所以CRT检测到这个问题才会报错。  大哥您的回复太专业了，可能我 还没到那个层次，所以看不太懂，不过能解决我碰到的问题，谢谢了

声明 max 的时候必须给一个初始值

循环外的max与循环内的max不是同一个变量

对，3L说的是对的，看掉了你在for上又定义了一个max，这个max在退出for之后就没了，用的还是外面没有被赋值的max所以报错了。

楼主，你在for上定义一个max 可是又在for里 int i=0,max=ar[0];  这里又定义一个max，导致之前的max被屏蔽了，等for循环退出后，for里的max结束（有些编译器会将定义在for表达式上的变量的生命周期延长到for外，如vc6.0），之后访问的max就是那个之前没有初始化的max

赶脚你重复定义max了。


Question: 初学者疑问一道题

已经比较了，因为最大的一直放在max，只有一个

这个很好理解啊，一开始让max = a,  当 max = a < b 时，说明b大于a , 则让max = b，再让max 与 c比较，如果c > max，则让max = c。  其设计思想，就是先求两个数的最大值，再将最大值与第三个数比较，求最终的最大值，不跟淘汰赛一样么


Question: 波特率自适应

谢谢!!!!!!!

你的while(1)的退出条件呢？

版块发错了，到“嵌入式/硬件”


Question: Linux下_np 结尾的函数

难道是 not posix 。。。

nonportable（不可移植的）：nonstandard GNU extension

没准


Question: 初始化链栈，为 top 指针申请一节点，申请之后却不用，而将 top 指针指向NULL？？求大神指教这个申请节点的操作的作用何在？

你们老师的意思是创建一个头节点，然后要它的next指向NULL,而不是它本身指向NULL

引用 2 楼 u010815558 的回复:[quote=引用 1 楼 cjqpker 的回复:] S->top = (LinkStackPtr)malloc(sizeof(StackNode));  S->top=NULL;  显然发生了内存泄露，刚申请的内存，令 top = NULL 后就找再也不到了，也就没法释放了。 创建一个top表明是头部，令其next指向NULL表明是空链表。虽然top节点可能不存数据，但是要用到其next指针，所以必须创建这个节点 那这个好多都这样写啊，不申请一个空间行么？[/quote]  怎么会好多这样写的？ 就算某处要赋值为NULL，那也要free()释放内存之后，再赋值为NULL。 这里如果top不作为节点，只记录第一个节点的地址，也是可以的。那就不要有S->top = (LinkStackPtr)malloc(sizeof(StackNode));这一步操作了。

引用 1 楼 cjqpker 的回复:S->top = (LinkStackPtr)malloc(sizeof(StackNode));  S->top=NULL;  显然发生了内存泄露，刚申请的内存，令 top = NULL 后就找再也不到了，也就没法释放了。 创建一个top表明是头部，令其next指向NULL表明是空链表。虽然top节点可能不存数据，但是要用到其next指针，所以必须创建这个节点 那这个好多都这样写啊，不申请一个空间行么？

malloc的对象，不用的时候肯定要free

引用 4 楼 cjqpker 的回复:[quote=引用 2 楼 u010815558 的回复:] [quote=引用 1 楼 cjqpker 的回复:] S->top = (LinkStackPtr)malloc(sizeof(StackNode));  S->top=NULL;  显然发生了内存泄露，刚申请的内存，令 top = NULL 后就找再也不到了，也就没法释放了。 创建一个top表明是头部，令其next指向NULL表明是空链表。虽然top节点可能不存数据，但是要用到其next指针，所以必须创建这个节点 那这个好多都这样写啊，不申请一个空间行么？[/quote]  怎么会好多这样写的？ 就算某处要赋值为NULL，那也要free()释放内存之后，再赋值为NULL。 这里如果top不作为节点，只记录第一个节点的地址，也是可以的。那就不要有S->top = (LinkStackPtr)malloc(sizeof(StackNode));这一步操作了。[/quote]偶偶，谢谢了

引用 3 楼 ForestDB 的回复:可以搜索研究下带header的链表和不带header的链表。 对特定的链表操作，尝试对两种链表都实现一下，可以发现差别。好的，谢谢了


Question: getopt疑问

l: 表示l后面有参数，但是你并没有提供参数。         case 'l':             b_opt_arg = optarg;             printf("Our love is %s\n", optarg);             break; 看到optarg没有？

optstring是选项字母组成的字串。如果该字串里的任一字符后面有冒号，那么这个选项就要求有选项参数 所以 ./hello  -l forever

l后有冒号  冒号-l后面必须跟一个参数，否则报错。  和顺序无关。  http://www.cnblogs.com/pengyingh/articles/2503440.html  http://blog.csdn.net/mr_jj_lian/article/details/6835137


Question: 字符串逆序出现段错误

指针 字符串是常量

char *d="abcd"; => char d[5]="abcd";  百度"字符串常量"


Question: free()出错 DAMAGE:after normal block(#)

多谢楼上的大侠，j<=FileSize真的越界了。

for(j=0;j<FileSize;j++)  你赋值越界了


Question: 一个算法问题, 想不明白

引用 10 楼 zilaishuichina 的回复:同样当元素个数是奇数个的时候， 无法推出证明1  代码写好了 http://www.cnblogs.com/XiangfeiAi/p/4758939.html

引用 10 楼 zilaishuichina 的回复:同样当元素个数是奇数个的时候， 无法推出证明1  如果前N-1个元素有主元, 那么最后一个元素不管是不是主元都对结果没有影响;  而如果前N-1个元素没有主元, 那么加上最后一个元素之后, 就有可能使整个数组存在主元, 所以最后一个元素有可能是主元   所以最后的算法应该是这样的. 如果数组元素的个数是偶数, 就找出候选元, 然后再遍历整个数组, 确定这个候选元是否是主元 如果数组元素的个数是奇数, 那么就先从前N-1个元素中找出候选元,      遍历整个数组, 如果这个候选元就是主元, 那么就结束了,      遍历整个数组, 如果这个候选元不是主元, 那么就把最后一个元素当做候选元, 再遍历数组, 确定这个候选元是否就是主元

同样当元素个数是奇数个的时候， 无法推出证明1

这个算法 我细想一下，觉得还是仅限于偶数个元素的时候，奇数个元素是不对的  3，1，3，1，3，1，3，1，3，1，3 以上排列，落单的元素如果不算的话，是无解的  3，3，3，3，3，3，1，1，1，1，1 以上排列，落单的元素如果算的话，是无解的

引用 7 楼 axf1766567189 的回复:[quote=引用 3 楼 zilaishuichina 的回复:] 算法应该少了一条当出现奇数个元素的时候，落单的那一个不需要比较，直接放入数组B  题目已经说了，“主要元素是一个出现次数超过N/2的元素”，这是一个关键条件  也就是说 比如: N=10， 主要元素是3，则3出现的次数>=6 需要证明的点1：6个3随机分布在大小为10的容器中，必定有至少1次的连续下标的2个元素均为3。 反证：任意2个3都不连续（也就是1次都没有）的极端情况是5个3依次被另一个元素隔开：3，1，3，1，3，1，3，1，3，1 所以用第6个3替换1的任意一个的位置，都会出现至少1次连续的2个3。  需要证明的点2：连续的两个3出现的位置下标，必定是i*2，i*2+1 反证：任意2个连续的3的下标都是i*2+1，(i + 1) * 2的极端情况是：1，3，3，1，1，3，3，1，1，3 所以用第6个3替换1的任意一个的位置，都会出现至少1次连续的两个3出现的位置下标，必定是i*2，i*2+1  据此可以证明B数组中一定包含候选元  需要证明的点3：B数组中候选元的个数出现次数>CountB/2 反证：如果B中候选元的个数出现次数<=CountB/2，举个B的极端情况，3，3，3，1，2，4 根据“比较A1和A2，如果它们相等则取其中之一加到数组B中；否则什么都不做”规则反推A，A必定包含3，3，3，3，3，3，1，1，2，2，4，4(这些元素组成的数组我们定义为A的子数组A`，D后面可能还有其他元素，我们定义为A的子数组A``)，分情况 1：A``的元素个数为0，那么在A中3的个数 = CountA` / 2 + 0 / 2 = CountA/2，A中3的个数不满足>CountA/2的条件 2：A``的元素个数大于0，最好情况有1半都是3，（因为如果A``的3超过一半，根据证明1和证明2，B中必定会在现有元素基础上多出至少1个候选元3），此时A中3的个数 CountA` / 2+ CountA`` / 2 =  CountA/2，A中3的个数不满足>CountA/2的条件 所以B数组中候选元的个数出现次数>CountB/2  你的逻辑好严格呀, 看了之后瞬间明白了, 其实最主要的第3个证明.  另外, 请问一下, 怎样才能达到你这样的思维? [/quote]  逻辑思维是程序员的基本功呀，我也没有专门训练过，这个我就不知道该怎么回答了

引用 3 楼 zilaishuichina 的回复:算法应该少了一条当出现奇数个元素的时候，落单的那一个不需要比较，直接放入数组B  题目已经说了，“主要元素是一个出现次数超过N/2的元素”，这是一个关键条件  也就是说 比如: N=10， 主要元素是3，则3出现的次数>=6 需要证明的点1：6个3随机分布在大小为10的容器中，必定有至少1次的连续下标的2个元素均为3。 反证：任意2个3都不连续（也就是1次都没有）的极端情况是5个3依次被另一个元素隔开：3，1，3，1，3，1，3，1，3，1 所以用第6个3替换1的任意一个的位置，都会出现至少1次连续的2个3。  需要证明的点2：连续的两个3出现的位置下标，必定是i*2，i*2+1 反证：任意2个连续的3的下标都是i*2+1，(i + 1) * 2的极端情况是：1，3，3，1，1，3，3，1，1，3 所以用第6个3替换1的任意一个的位置，都会出现至少1次连续的两个3出现的位置下标，必定是i*2，i*2+1  据此可以证明B数组中一定包含候选元  需要证明的点3：B数组中候选元的个数出现次数>CountB/2 反证：如果B中候选元的个数出现次数<=CountB/2，举个B的极端情况，3，3，3，1，2，4 根据“比较A1和A2，如果它们相等则取其中之一加到数组B中；否则什么都不做”规则反推A，A必定包含3，3，3，3，3，3，1，1，2，2，4，4(这些元素组成的数组我们定义为A的子数组A`，D后面可能还有其他元素，我们定义为A的子数组A``)，分情况 1：A``的元素个数为0，那么在A中3的个数 = CountA` / 2 + 0 / 2 = CountA/2，A中3的个数不满足>CountA/2的条件 2：A``的元素个数大于0，最好情况有1半都是3，（因为如果A``的3超过一半，根据证明1和证明2，B中必定会在现有元素基础上多出至少1个候选元3），此时A中3的个数 CountA` / 2+ CountA`` / 2 =  CountA/2，A中3的个数不满足>CountA/2的条件 所以B数组中候选元的个数出现次数>CountB/2  你的逻辑好严格呀, 看了之后瞬间明白了, 其实最主要的第3个证明.  另外, 请问一下, 怎样才能达到你这样的思维?

(假设有主要元素，也就是候选元，找出后再检验) 设 x：A主要元素，y：B主要元素，z：A中x外任意元素 1)N为偶数, 将A分为N/2对，(A1A2,  A3A4, ...) ，显然y为相同最多的那个(比如 ：11 11 22 12， y = 1). 假设有a对 xx，b对zz，则A中x最多个数为  2a+(N/2 - a - b) >N/2   故 a>b， 所以y = x. 2)N为奇数  若A最后一个元素为x，则a>=b，再加上最后一个，故y=x. 若A最后一个元素不为x，则A中x最多个数为a>b+1, 故y=x 所以B的候选元就是A的候选元

D后面可能还有其他元素  -》 A`后面可能还有其他元素

感觉题目的N应该是偶数, 因为如果是奇数就不好处理了. 如下: N为5, 那么数组可能为 XOXOX

在我的理解中原有数组A中的主要元素超过N/2个, 那么在数组A中一定存在连续3个相连的主要元素 如下:假设N为6, 那么数组可能为 XXXOXO


Question: 输入数组不得使用getchar

#include <iostream> #include <vector> #include <iterator> #include <algorithm>  int main(){    std::istream_iterator<int> start(std::cin), end;	     std::vector<int> v;    std::copy(start,end, std::back_inserter(v));    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, "  "));    std::cout << std::endl;    return 0; }  C:\Users\Administrator\Desktop\demo>echo 10 13 15 14 10 |  demo 10  13  15  14  10

cin>>n; vetor<int> v; istream_iterator<int> beg(cin); copy(beg,istream_iterator<int> (),v.begin()); cin.clear(); 输入  10 1 2 3 4 5 6 7 8 9 10 a

如果用 copy 函数，从 cin 上输入，表面上并没有循环


Question: C++ static_cast int类型转换为char类型

谢谢各位帮忙，第一次发帖求助分不多，学习了~

引用 5 楼 freedemolody 的回复:[quote=引用 4 楼 fly_dragon_fly 的回复:] 加不加static_cast没什么区别, 结果也没错, 你想看到什么, 调试器显示是字符, 不显示整数   请问，难道不是array2的数组中的每个int型数值对应array3数组中的每一个char型数值么？ 可是经过static_cast转换后，为甚么array里只对应这个"霅墹"。另外array2和array3数组中的内容是我添加“监视”时copy的。 拜托解答一下了，非常谢谢[/quote]直接在内存中看一下array3

void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             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]:'.');             }             printf("%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]:'.');         }         printf("%s\n",binstr);     } }

引用 5 楼 freedemolody 的回复:[quote=引用 4 楼 fly_dragon_fly 的回复:] 加不加static_cast没什么区别, 结果也没错, 你想看到什么, 调试器显示是字符, 不显示整数   请问，难道不是array2的数组中的每个int型数值对应array3数组中的每一个char型数值么？ 可是经过static_cast转换后，为甚么array里只对应这个"霅墹"。另外array2和array3数组中的内容是我添加“监视”时copy的。 拜托解答一下了，非常谢谢[/quote] 试试在watch窗口中观察array3,5 这个可以把普通地址转换为数组。

引用 4 楼 fly_dragon_fly 的回复:加不加static_cast没什么区别, 结果也没错, 你想看到什么, 调试器显示是字符, 不显示整数   请问，难道不是array2的数组中的每个int型数值对应array3数组中的每一个char型数值么？ 可是经过static_cast转换后，为甚么array里只对应这个"霅墹"。另外array2和array3数组中的内容是我添加“监视”时copy的。 拜托解答一下了，非常谢谢

整形占四个字节，字符型1个字节，当然是不安全的

一个是整形 一个是char


Question: 如何理解程序的编译、链接、加载等各个过程

参考Tiny C Compiler源代码？

《Windows PE权威指南》 《程序员的自我修养——链接、装载与库》 The Intel 64 and IA-32 Architectures Software Developer's Manual

程序员的自我修养 就是这买本书讲解  同样看不懂的落。  看不懂就先不看。

引用 2 楼 FightForProgrammer 的回复:还有一本：程序员的自我修养这本书很晦涩，看不懂

还有一本：程序员的自我修养

推荐一本书吧：CSAPP Computer System: from A Programmer's Perspective


Question: 字符串

直接使用strstr函数可以了。  char[] a = "abcd0efg00hijkl0mnop00qr"; char* pIndex = null; pIndex = strstr((const char*)a, "00");

strstr现成的。

也可以使用库函数

int find_twozero(const char *s){     for(auto p =s;s[0]&&s[1];s++) if(s[0]=='0'&&s[1]=='0') return s-p;     return -1; }

int i = 0; while(a[i] != 0 || a[i+1] != 0) {     i++; }


Question: posix socket api thread safe

引用 2 楼 zhao4zhong1 的回复:《Windows核心编程》  epoll 是linux 里面才有吧，虽然概念一样但是细节不同。

《Windows核心编程》

这样的读写应该不是一个好的设计，只不过就是想了解一下。是得去追linux 内核才能知道吗？？


Question: 怎么用VC画波形图

直接用C语言图形编程就能解决啊，给你个网站这里面有现成的，自己找去。 http://www.easyx.cn

马克

可以用mschart,或者ntgraph这个，以前用过ntgraph这个挺简单的。

你给的那个网站上的第一和第二步你能和我说说吗？我看不懂呀

http://www.pudn.com/downloads384/sourcecode/windows/bitmap/detail1648955.html 去这里找找 用GDI或GDI+来做。


Question: UDP+线程池处理问题！

看看unix网络编程，上面有你需要的所有消息

引用 29 楼 u014149003 的回复:在做FTP和email 客户端的时候用的也是线程池，线程池不是类似生产者-消费者么 只要锁的力度和区域设计好，一切都会变得很简单~ 嗯，是的，不过现在遇到的问题是要在线程池中进行数据处理，而数据处理用到了别人封装的一个静态库，现在看来这个静态库不是线程安全的，如果锁住了这个静态库提供的函数，那就跟顺序执行没什么两样了，得不到并发执行线程池也就没什么意义了。

引用 16 楼 dooX8086 的回复:相关楼主还要注意  惊群现象   （pthread_cond_signal  惊群）  process 函数中的 iRet = Enc(gtSlot[iSessID].pHandle, &sBuf[0], tSndBuf.ucText);//   这个gtSolt 那里来的？ 看样子就个公共变量，还有 iSessID .... 等公共变量，如果外部没有保证这些变量 这个 函数不是线程安全的  对于 process 函数 process(...);       // 如果它是放在 这行mutex_unlock() 之前,那么这个 多线程的设计10分不好(比单线程还慢得多) pthread_mutex_unlock() <<=========  //  较好的设计它应该放在 mutex_unlock() 这后 高人，不知道能不能跟您继续学习讨论一下呢？

这样吗 我怎么知道不得

关注下,不错

这个规划有点怪怪的

引用 24 楼 qq_30773211 的回复:这样吗 我怎么知道不得 没明白，什么意思？

引用 20 楼 cattpon 的回复:这个规划有点怪怪的 那里比较怪啊？

学习

引用 16 楼 dooX8086 的回复:相关楼主还要注意  惊群现象   （pthread_cond_signal  惊群）  process 函数中的 iRet = Enc(gtSlot[iSessID].pHandle, &sBuf[0], tSndBuf.ucText);//   这个gtSolt 那里来的？ 看样子就个公共变量，还有 iSessID .... 等公共变量，如果外部没有保证这些变量 这个 函数不是线程安全的  对于 process 函数 process(...);       // 如果它是放在 这行mutex_unlock() 之前,那么这个 多线程的设计10分不好(比单线程还慢得多) pthread_mutex_unlock() <<=========  //  较好的设计它应该放在 mutex_unlock() 这后  以下是线程池中每个线程的执行函数：  void *thread_routine(void *arg) { 	T_Worker *worker = NULL; 	 	DEBUG_PRINT("starting thread 0x%x\n",pthread_self());  	while(1) 	{ 		pthread_mutex_lock(&(gpPool->queue_lock));  		while(gpPool->cur_queue_size == 0 && !gpPool->shutdown) 		{ 			DEBUG_PRINT("thread 0x%x is waiting\n",pthread_self()); 			pthread_cond_wait(&(gpPool->queue_ready),&(gpPool->queue_lock)); 		} 		 		if(gpPool->shutdown) 		{ 			pthread_mutex_unlock(&(gpPool->queue_lock)); 			DEBUG_PRINT("thread 0x%x will exit\n",pthread_self()); 			pthread_exit(NULL); 		} 		DEBUG_PRINT("thread 0x%x is starting to work\n",pthread_self());  		assert(gpPool->cur_queue_size !=0); 		assert(gpPool->queue_head != NULL);  		gpPool->cur_queue_size--; 		worker = gpPool->queue_head; 		gpPool->queue_head = worker->next;  		pthread_mutex_unlock(&(gpPool->queue_lock));  		(*(worker->process))(worker->arg);//此处执行pool_add_work()添加进队列的回调函数 		free(worker); 		worker = NULL; 	}	 	pthread_exit(NULL); }  gtSlot[N]是全局数组，N就是程序支持的最大的并发个数，每一路并发（就是在程序里做转换）依托一个处理句柄，这个全局数组就是保存对应的N个句柄，每一路发来的包中包含一个iID，在0~N中，由它直接定位哪一个句柄。  通过实验发现，如果Enc，Dec两个处理函数不加锁，转换出来的数据误差较大，但是加了锁会不会大大降低了效率？这两个函数是库里的，我看不到实现，本以为依托于一个处理句柄应该可重入的。我也知道这个问题问您有点不太合适，因为怎么实现的都不知道。

引用 16 楼 dooX8086 的回复:相关楼主还要注意  惊群现象   （pthread_cond_signal  惊群）  process 函数中的 iRet = Enc(gtSlot[iSessID].pHandle, &sBuf[0], tSndBuf.ucText);//   这个gtSolt 那里来的？ 看样子就个公共变量，还有 iSessID .... 等公共变量，如果外部没有保证这些变量 这个 函数不是线程安全的  对于 process 函数 process(...);       // 如果它是放在 这行mutex_unlock() 之前,那么这个 多线程的设计10分不好(比单线程还慢得多) pthread_mutex_unlock() <<=========  //  较好的设计它应该放在 mutex_unlock() 这后 感谢高人继续指导哈 gtSlot是个全局结构数组，这里的iSessID写错了，其实是上边的iID，一路并发对应一个iID，这个转换函数要基于每一路的pHandle。从这些全局变量的作用来看，我要怎么做才是线程安全的？  process在线程中调用，在链表取数据时加解锁，解锁后调用process这个回调，晚上回去我贴下代码，这样设计是否会好一点？

引用 14 楼 Mrzhen009 的回复:[quote=引用 13 楼 zxh707wk 的回复:] 直接上iocp吧 这个不太了解，搜了下是win下的模型吧，现在要求使用Linux。这个是不是与epool差不多？[/quote]还是继续用epoll吧

初始化的时候gpPool->queue_head = NULL

引用 13 楼 zxh707wk 的回复:直接上iocp吧 这个不太了解，搜了下是win下的模型吧，现在要求使用Linux。这个是不是与epool差不多？

直接上iocp吧

assert的作用是现计算表达式 expression ，如果其值为假（即为0），那么它先向stderr打印一条出错信息，然后通过调用 abort 来终止程序运行。 崩溃的原因在于断言为假了，建议检查gpPool的初始化及其他操作

引用 8 楼 dooX8086 的回复:这一段是向线程池添加任务的函数，现在总是在这里崩溃  int pool_add(void* (*process)(void *arg), void* arg) { T_Worker *newworker = (T_Worker *)malloc(sizeof(T_Worker)); T_Worker *member = gpPool->queue_head;    // 如果同时入这就有问题 ( 因为你的 queue 是不带头结点的单链表) =====>>>>>>  newworker->process = process; memcpy(newworker->arg,(unsigned char *)arg,512); newworker->next = NULL;  pthread_mutex_lock(&(gpPool->queue_lock));                                                                                // 应该放到这下面 .......   ////如果程序的重点是数据转换 ... 而转换函数又不是线程安全,(不能多路同进入)。 //// 这个多线程，跑起来还不如单线程快和高效  高人，我还是不太明白T_Worker *member = gpPool->queue_head;这一句 不加锁出错的原因，能不能指点一下？  下面是process回调函数，不知道有没有可重入的风险：  void *process(void *arg) { 	//arg为recvfrom得到的buffer，包含一个头和要转换的数据 	PT_RcvBuf ptRcvBuf = (PT_RcvBuf)arg;  	T_OutBuf tSndBuf; 	short sBuf[PCM_LEN_PER_PACKET]; 	unsigned char ucBuf[EVRC_LOAD_LEN_PER_PACKET]; 	int iRet,iID; 	int sendbytes = 0;  	memset(&tSndBuf, 0, sizeof(T_OutBuf)); 	memset(&sBuf[0], 0, sizeof(sBuf)); 	memset(&ucBuf[0], 0, sizeof(ucBuf));  	iID = (int)(ptRcvBuf->tOutBuf.tHead.ucID); 		 	switch ( (int)(ptRcvBuf->tOutBuf.tHead.ucDirection) ) 	{ 		case ENCODE: 			memcpy(&sBuf[0],ptRcvBuf->tOutBuf.ucText,ENCODE_LEN); 			//编解码函数基于每一路的pHandle指针做处理，调试过程中这里有过报错，因为在lib库中，无法 			//查看，所以有锁，这里略去没写 			iRet = Enc(gtSlot[iSessID].pHandle, &sBuf[0], tSndBuf.ucText);//编码 			if (iRet != 0) 			{ 				printf("Enc Error!\n"); 				return ; 			} 			break;  		case DECODE: 			memcpy(&ucBuf[0],ptRcvBuf->tOutBuf.ucText,DECODE_LEN); 			//编解码函数基于每一路的pHandle指针做处理 			iRet = Dec(gtSlot[iID].pHandle, &ucBuf[0], tSndBuf.ucText);//解码 			if (iRet != 0) 			{ 				printf("Dec Error!\n"); 				return ; 			} 			break;  		default: 			printf("Unknown convert type: %d !\n",(int)(ptRcvBuf->tOutBuf.tHead.ucDirection)); 			return ; 	}  	memcpy( &(tSndBuf.tHead), &(ptRcvBuf->tOutBuf.tHead), sizeof(T_Head) );  	//通过recvfrom把client的sockaddr结构保存下来，并在此把处理后的数据发送回这个IP及PORT 	sendbytes = sendto(giSocketServer,&tSndBuf,sizeof(T_OutBuf),0,(struct sockaddr *)&(ptRcvBuf->tSocketClientAddr),giAddrLen); 	if (sendbytes !=sizeof(T_OutBuf)) 	{ 		perror("sendto"); 	} }


Question: mvc中json传值

先看清楚版块再问


Question: 用栈实现计算器一个奇怪的问题．．．

表达式 A - B 中A B之间没有明确的求值顺序，编译器可以以任意顺序对其进行求值 也就是说，你的代码和 i++ + ++i没什么区别

在ＶＳ下运行正确了．．好像真是编译器问题啊

我看过了，栈操作没有问题啊．．身边的人说是编译器优化问题．

应该是你栈的操作弄反了，呵呵，不过楼主，写的不错啊，这是后缀表达式

我是在linux下运行的．  完整代码如下： main.cpp  #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include "stack.h"  int IsOperator(char ch) {     char ops[] = "+-*/^";     int i;     for (i = 0; i < 5; i++)     {         if (ch == ops[i])             return 1;     }     return 0; }   int Precedence(char op) {     if (op == '(')     {         return -1;     }     else if(op == '^') 	return 2;     else if(op == '*' || op == '/')         return 1;     else if(op == '+' || op == '-')         return 0; }  void InFixtoPostFix(char *InFix, char *PostFix) {     int length = 0;     int i = 0;     int j = 0;     length = strlen(InFix);     Stack Experssion = CreateStack(length);     MakeEmpty(Experssion);     for(i = 0; i < length;)     {         if(InFix[i] == '(')             Push(InFix[i++],Experssion);         else if(InFix[i] == ')')	         {         	while(Top(Experssion) != '(')             	{	 			PostFix[j++] = TopAndPop(Experssion); 			PostFix[j++] = ' ';			             	}	 		Pop(Experssion); 		++i;         }         else         {             if(!IsOperator(InFix[i]))             {    while(!IsOperator(InFix[i]) && InFix[i] != '(' && InFix[i] != ')' && i < length) 		{ 			PostFix[j++] = InFix[i++]; 		} 		PostFix[j++] = ' '; 	    }             else             {             	while(IsEmpty(Experssion) == 0 && (Precedence(Top(Experssion))>=Precedence(InFix[i])))             	{         			if(InFix[i] == '^') 				break; 			else 			{	 				PostFix[j++] = TopAndPop(Experssion); 				PostFix[j++] = ' '; 			} 		}				                 Push(InFix[i++],Experssion);             }         }      }      while(IsEmpty(Experssion) == 0)     { 	PostFix[j++] = TopAndPop(Experssion); 	PostFix[j++] = ' ';     }     Free_Stack(Experssion);     PostFix[j] = 0;   //end of the string }  int Calcute(char *PostFix) {     int length = strlen(PostFix);     int i = 0;     ElementType tmp_var = 0;     ElementType result_var = 0;     ElementType index = 0;     Stack Calcute_stack = CreateStack(length);     MakeEmpty(Calcute_stack);     for(i = 0; i < length;)     {         if(IsOperator(PostFix[i]))         {             switch(PostFix[i++])             {             case '+':                 tmp_var = TopAndPop(Calcute_stack) + TopAndPop(Calcute_stack);                 break;             case '-':            		 tmp_var = TopAndPop(Calcute_stack) - TopAndPop(Calcute_stack); 		 tmp_var = -tmp_var;                  break;             case '*':                 tmp_var = TopAndPop(Calcute_stack) * TopAndPop(Calcute_stack);                 break;             case '/':                 tmp_var = 1.0 / TopAndPop(Calcute_stack) * TopAndPop(Calcute_stack);                 break; 	    case '^': 		index = TopAndPop(Calcute_stack);		 		tmp_var = pow(TopAndPop(Calcute_stack), index); 		break;             }             Push(tmp_var,Calcute_stack);	             }          else if(PostFix[i]!= ' ') 	{	 		tmp_var = 0; 		while(PostFix[i]!= ' ') 		{     			tmp_var += PostFix[i++] - '0'; 			tmp_var *= 10; 		} 		tmp_var /= 10;  		Push(tmp_var, Calcute_stack); 	}  	else 		++i;           }      result_var = Top(Calcute_stack);     Free_Stack(Calcute_stack);     return result_var; } int main() {     char InFix[100];     char PostFix[100];     ElementType Result = 0;      while(1)     {         printf("please enter an expression: ");         gets(InFix);         printf("Infix is : %s \n",InFix);         InFixtoPostFix(InFix,PostFix);         printf("PostFix is : %s \n",PostFix);         Result = Calcute(PostFix);         printf("calculation is : %d \n",Result);     }     return 0; }   stack.h  #ifndef _STACK_H #define _STACK_H  struct StackRecord; typedef struct StackRecord *Stack; typedef int ElementType;  int IsEmpty(Stack S); int IsFull(Stack S); Stack CreateStack(int MaxElements); void Free_Stack(Stack S); void MakeEmpty(Stack S); void Push(ElementType X, Stack S); ElementType Top(Stack S); void Pop(Stack S); ElementType TopAndPop(Stack S);  #endif // _STACK_H   stack.cpp  #include <stdio.h> #include <stdlib.h> #include "stack.h"  #define EmptyTOS (-1) #define MinStackSize (1) struct StackRecord { 	int Capacity; 	int TopOfStack; 	ElementType *Array; };  Stack CreateStack(int MaxElements) { 	    Stack S;  		if(MaxElements < MinStackSize) 			printf("Stack Size is too small!\n");  		S = (Stack) malloc(sizeof(struct StackRecord)); 		if(S == NULL) 			printf("Out of Space, malloc Stack S failed\n");  		S->Array = (ElementType *) malloc(sizeof(ElementType)*MaxElements); 		if(S->Array == NULL) 			printf("Out of Space, malloc S->Array failed\n");  		S->Capacity = MaxElements;  		return S; }  void Free_Stack(Stack S) { 	    if(S != NULL) 		{ 			free(S->Array); 			free(S); 		} }  int IsEmpty(Stack S) { 	    return S->TopOfStack == EmptyTOS; }  int IsFull(Stack S) { 	    return S->TopOfStack == S->Capacity - 1; }  void MakeEmpty(Stack S) { 	    S->TopOfStack = EmptyTOS; }  void Push(ElementType X, Stack S) { 	    if(IsFull(S)) 			printf("Stack S is full\n"); 		else 			S->Array[++S->TopOfStack] = X; }  ElementType Top(Stack S) { 	    if(IsEmpty(S)) 		{ 			printf("Stack S is Empty\n"); 			return -1; 		} 		else 			return S->Array[S->TopOfStack]; }  void Pop(Stack S) { 	    if(IsEmpty(S)) 			printf("Stack S is Empty\n"); 		else 			S->TopOfStack--; }  ElementType TopAndPop(Stack S) { 	    if(IsEmpty(S)) 		{ 			printf("Stack S is Empty\n"); 			return -1; 		} 		else 		return S->Array[S->TopOfStack--]; }

不好意思．．．我打错了．以上程序除了最后一个的结果是－１以外，结果都是１．郁闷啊．

除了tmp_var = -(TopAndPop(Calcute_stack) - TopAndPop(Calcute_stack));返回1表示有疑问外,其它应该是对的, 2在上面,1在下面,所以第一个pop的是2,

makefile这么写得，这样就关闭编译器优化了吧．．．  infix: main.o stack.o 	g++ -o infix -O0 -g main.o stack.o main.o: main.cpp stack.h 	g++ -c -O0 -g main.cpp stack.o: stack.cpp 	g++ -c -O0 -g stack.cpp clean: 	rm infix main.o stack.o


Question: 十进制字符串转换为16进制

char *p="123456789012345678901234567890" 这个１６进制是0x18ee90ff6c373e0ee4e3f0ad2，１０多个字节，int　或者long long都不能表示，只能自己用数组来模拟了． 这里给个最初的版本，可以改进．  #include <stdio.h> #include <stdlib.h> #include <string.h>  #define  MAXBUF   20  void DecString2HexString( unsigned char *dest, const  unsigned char *src ); void SumArray( unsigned char *dest, const unsigned char *src1, const unsigned char *src2 ); void LeftShift( unsigned char *dat ); unsigned char Num2Char( unsigned char ch );   unsigned char *p="123456789012345678901234567890"; unsigned char result[sizeof(p)];//大小自己定 unsigned char binNum[MAXBUF];  int main() {         DecString2HexString( result, p );     printf( result ); 	getchar();     return 0; }    /* 描述:将１０进制的字符串转换成十六进制的形式 */ void DecString2HexString( unsigned char *dest, const unsigned char *src ) {     unsigned char *pBuf = src;     unsigned char i,j, ch;     unsigned char temp1[MAXBUF];     unsigned char temp2[MAXBUF];     unsigned int len = 0;      	memset( binNum, 0, MAXBUF );      while ( (ch = *pBuf++ ) != 0 )     {         ch = ch - '0';         memcpy( temp1, binNum, MAXBUF ); 		//binNum = binNum * 10;          LeftShift(temp1);         memcpy( temp2, temp1, MAXBUF );         LeftShift(temp1);         LeftShift(temp1);         SumArray( binNum, temp1, temp2  );          binNum[MAXBUF-1] += ch;      }      for ( i=0; i<MAXBUF; i++ )     {         if ( binNum[i] != 0 ) break;     }      if ( (binNum[i] & 0xf0) == 0)     {         dest[len++] = Num2Char(binNum[i]);         i++;     }      for ( j=i; j<MAXBUF; j++ )     {         dest[len++] = Num2Char( binNum[j]>>4 );         dest[len++] = Num2Char( binNum[j]&0xf );     }   }  unsigned char Num2Char( unsigned char ch ) {     return ch <= 9? (ch + '0') : (ch + 'a' - 10); }  //两个数组之和 void SumArray( unsigned char *dest, const unsigned char *src1, const unsigned char *src2 ) {     char i;     unsigned char c;     unsigned short sum;      c = 0;     for ( i=MAXBUF-1; i>=0; i-- )     {         sum = src1[i] + src2[i] + c;          if ( sum > 255 )         {             c = 1;         }         else         {             c = 0;         }          dest[i] = sum & 0xff;      } }   //左移 void LeftShift( unsigned char *dat ) {     unsigned char i, c;      dat[0] = dat[0] << 1;      for ( i=1; i<MAXBUF; i++ )     {         c = dat[i]>>7;          if ( c == 1 )         {             dat[i-1] |= 1;         }         else         {             dat[i-1] &= 0xfe;         }          dat[i] = dat[i] << 1;     } }


Question: 请教各位大神，指针访问指定内存

对啊，就是要查找SMBIOS信息。我再查找下物理地址怎么查找

楼主这是要查找SMBIOS的信息啊, 你所说的内存地址0xf0000到0xfffff, 其实它们是内存的物理地址即实际内存地址. 我们写出来的程序所有使用的内存地址都是虚拟地址, 虚拟地址和物理地址之间是不匹配的. 所以你需要去访问物理内存地址,  因为访问物理内存地址是操作硬件级别的代码, 所以需要ring0权限 你可以使用驱动来进行ring0访问 目前封装好的访问硬件的库有WinRing0, WinIO等, WinRing0默认不能进行物理内存访问, 你需要下载源码自己开启物理内存访问, 然后编译, WinIO我没使用过不太清楚.

在DosBox下 或 使用WinIO.sys

引用 7 楼 MRCRL 的回复:因为要获取SMBIOS必须先获得eps表，而这个表就是存放在0xf0000-0xfffff之间内存 。。。。饿， 首先，你直接赋值 一个常量作为指针，这种方式肯定是不可取的，很容易就崩了。 然后，那里的0xf0000-0xfffff是系统物理内存地址呀。。。 －－－－－－－－－－－－－－－－－－－－－－－－－－－－ 我只大概看了下， 如果你是想获取电脑的硬件信息，建议你可以采用其他方式，具体的忘了可搜索， 如果你非要这么干，建议搜索windows下访问物理内存，

引用 5 楼 MRCRL 的回复:是已知” _SM_ "这串字符是一个表格内容头部，存放在0xf0000-0xfffff这段内存之间，我要找到这个表格。  关于内存范围问题，0xf0000-0xfffff这明显不像是一个可以合法访问的内存地址呢。。。。 你的问题应该是"存放在0xf0000-0xfffff这段内存之间"这句话很不对劲， 你那个表格是哪里来的，你是怎么知道这个表格在0xf0000-0xfffff的,。。。。

解析随机生成的文件是吗

就是“_SM_"存在内存的0xf0000-0xfffff之间，我要找到他。请问可以怎么找到呢

。。。你也是个人才。。。。这么操作内存，这不就个野指针，对野指针的访问，运行结果完全未知 管你是0xf0000还是0xfffff 建议你说清实际情况再讨论吧；


Question: 假如我有4个数组，怎样对外表现为一个数组？

这个无妨的。楼主是将数组做封装了，原则上是不可能用memcpy,memset对数组直接操作的。  引用 7 楼 jiqiang01234 的回复:最好不要模拟成一个数组，因为数组是可以memcpy()memset()操作的，而模拟的是无法做到，而且也无法防止调用端这样使用

永远都不可以的。

直接不行就加个间接好了 int a[11],b[14],c[33],d[443],     *pp[]={ a, b, c, d}; int start[]={0,11,14+11,33+14+11},len[]={11,14+11,33+14+11,443+33+14+11}; int get(int idx){     int which;     for(which=0;which<4;which++) if(idx<len[which]) break;     if(which>=4) {assert(false); return -1;}     return pp[which][idx-start[which]]; }

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

忘了写在代码里了

换个更加灵活的写法： template <typename T>class CombPArr{ int *a,*b,*c,*d; size_t aSZ,bSZ,cSZ,dSZ ; public : CombPArr(T *pa,T* pb,T *pc, T* pd,size_t szA,size_t szB,size_t szC,size_t szD) :a(pa),b(pb),c(pc),d(pd),aSZ(szA),bSZ(szB),cSZ(szC),dSZ(szD) { }; const int & operator [](int n)const { return n<aSZ?a[n] :n<bSZ ? b[n]: n<cSZ?c[n]:d[n];} int& operator[] (int n){ return n<aSZ?a[n] :n<bSZ? b[n]: n<cSZ?c[n]:d[n]; }; };

C++ 可以这么处理 template<int M,int N,int K,int L> class CombArr{ enum {aSZ=M,bSZ =N,cSZ=K,dSZ=L}; int (&a)[aSZ]; int (&b)[bSZ]; int (&c)[cSZ]; int (&d)[dSZ];  public : CombArr(int (&A)[aSZ],int (&B)[bSZ],int (&C)[cSZ],int (&D)[dSZ]):a(A),b(B),c(C),d(D){}; const int & operator [](int n)const { return n<aSZ?a[n] :n<bSZ ? b[n]: n<cSZ?c[n]:d[n];} int& operator[] (int n){ return n<aSZ?a[n] :n<bSZ? b[n]: n<cSZ?c[n]:d[n]; }; }; #define arrsize(x) (sizeof(x)/sizeof(x[0])) //这可以改进为更好的版本   CombArr<arrsize(a),arrsize(b) ,arrsize(c),arrsize(d) > ca(a,b,c,d); 现在  ca 可以当作数组处理了

#define _countof(a)   (sizeof(a)/sizeof(a[0]))   size_t GetCount(){ return _countof(A) + _countof(B) + _countof(B) + _countof(D); }  类型   GetElement(size_t i){ if(i < _countof(A))        return A[i]; else if(i < _countof(B))        return B[i]; else if(i < _countof(C))        return C[i]; else if(i < _countof(D))        return D[i]; }

写一个类，把4个数组做为成员变量，重载类的[]运算符

4个数组都放到一个类里面，类里面给一个getElem的成员函数，对索引值进行判断看在哪个数组里，找到然后再把那个元返回。 建议可以先判断在不在D数组内，因为D比较大，在里面的几率高，总体来说可以略节省点时间。

定义为一个数组


Question: VC6编译报错帮忙看看咋回事儿

说得很清楚了，endif没有对应的ifdefine


Question: 递归在底层是怎么实现的？

引用 10 楼 zilaishuichina 的回复:尾递归可以优化成循环   递归调用 就是 函数调用， 递归调用的函数自己调用自己。 而函数调用的原理就是保存现场，调用另一个函数（递归时这个另一个函数就是自己），恢复现场继续执行 保存现场包括保存函数调用的下一条指令的地址eip，栈帧指针ebp，esp，子函数参数列表  也正因为是自己调用自己， 所以需要一个结束自己调用自己的契机，叫做递归出口。  也正因为保存现场需要保存一系列的参数压栈， 如果没有递归出口，就是死循环在不停的压栈，而栈空间是由限的， 所以如果没有递归出口，就会造成栈溢出详细，

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

引用 2 楼 xiaohuh421 的回复:递归的原理, 你可以想像成不停的函数调用.  比如fun1  ---  funN都是实现Add  fun1() {       fun2() {     fun3()     {       ........     } }   }  递归的核心思想就是保存现场,  也就是需要把传入下一层函数的所有参数保存起来, 实现函数参数栈.这样理解好，很形象

引用 1 楼 kaituozhe163 的回复:老师说，能用递归实现的算法，都能用循环实现，哪位大神能帮我用循环实现一下，汉诺塔问题的算法： 汉诺塔递归： void  haNoTower(int n,char start,char temp,char end) {     int count = 0;     if(n == 1)     {         printf("第%d个盘子从%c->%c\n",n,start,end);     }     else     {         haNoTower(n - 1,start,end,temp);         printf("第%d个盘子从%c->%c\n",n ,start,end);         count++;         haNoTower(n - 1,temp,start,end);//问什么要写n － 1 呢？     }  最笨的办法： 先写递归版本， 用栈(数据结构）来模拟函数调用。

函数调用所做的事情 调用前： 1）函数参数处理-------------//参数存入寄存器，或者压栈 2）函数返回地址处理--------//把地址保存到栈内，以便返回时可以找到返回位置。 调用中： 3）执行函数体 调用后： 4）堆栈平衡和函数返回值处理----------//合理利用堆栈，寄存器，不至于浪费空间。 大约做了这么多事情  1）2）4） 这几步，通常就是某些书中说的簿记管理， 这是每个函数调用都在做的， 可能还包括更加常用的出栈入栈 递归只是利用了这种簿记管理，而不是递归独有的

递归函数，自己直接间接调用自己

递归，和普通函数调用，没有太多不同 不同的是，函数自己调用自己 底层实现，没区别，或者基本没区别  一般CPU 没区别 51 再入函数实现递归，普通函数不行。

递归是自顶向下的思想, 象汉诺塔,看起来就简洁, 用循环就麻烦多了, 还是多理解一下递归吧

引用 1 楼 kaituozhe163 的回复:老师说，能用递归实现的算法，都能用循环实现，哪位大神能帮我用循环实现一下，汉诺塔问题的算法： 汉诺塔递归： void  haNoTower(int n,char start,char temp,char end) {     int count = 0;     if(n == 1)     {         printf("第%d个盘子从%c->%c\n",n,start,end);     }     else     {         haNoTower(n - 1,start,end,temp);         printf("第%d个盘子从%c->%c\n",n ,start,end);         count++;         haNoTower(n - 1,temp,start,end);//问什么要写n － 1 呢？     }  要想将n个盘子从A挪到C，首先得将前n-1个盘子挪到B，接着将最底下的盘子挪到C，然后将B中的盘子挪到C  如程序： haNoTower(n - 1,start,end,temp);   //将前n-1个盘子从start借助end挪到temp printf("第%d个盘子从%c->%c\n",n ,start,end);   //将最后一个盘子从start挪到end  haNoTower(n - 1,temp,start,end);    //将前n-1个盘子从temp借助start挪到end

引用 8 楼 TheOne_jie 的回复:有了栈就有了递归

有了栈就有了递归

簿记管理，没有多少编译器，CPU专门去做， 而是函数调用，自然就有这个管理工作在内

底层，什么也不做，所谓簿记管理，其实只是编译器，硬件底层堆栈实现，等调用函数的正常功能 只有特殊CPU比如51 需要专门类型的再入函数，实现递归  普通CPU 递归函数调用，和普通函数调用，实现方法一致。


Question: getchar()与ch=getchar()

// 1 while((ch = getchar()) != '\n')             putchar(ch); // 2			 while((getchar()) != '\n')             putchar(getchar()); getchar()每调用一次，指针往后移动了一位。第2种调用了2次getchar(),  是错的。每次只输出了第2,4,6,8...个字符，因为中间的，被第一个getchar()消耗掉了，而你又没保存输出。

引用 楼主 Real_Bird 的回复:#include <stdio.h>  int main(void) {     int input;     char ch;      while(scanf("%d", &input) != 1)     {         while((ch = getchar()) != '\n')             putchar(ch);         printf(" isn't a integer.please input again\n");     }     printf("%d\n", input);      return 0; }  图如下。  我不明白这两个区别在哪 我太疏忽了。。多谢


Question: C primer plus 编程答案 有点问题 找不出来 帮忙看一下 谢谢了

好吧  .........

保存、读取应该没有问题

struct pack { struct book book;  bool delete_me; }; 中的delete_me是标志位，必须处理  if (getlet("yn") == 'y') { 		 } 保存、读取应该没有问题 else 	library[count].delete_me = false;


Question: 帮忙看一下   哪里出错了VS2010

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

这类错误，用IDE排下格式应该就能发现

同上，多了个分号！！难道编译器不定位错误么

#include<stdio.h> int main() { int n;     int f1; int f2; int f3; int i;  f1=1; f2=2; printf("请输入你需要的序列："); scanf("%d",&n); if (1 == n) f3=1; else if (2 == n);//此处多了一个双引号，执行的是空语句  f3=2; else   //这个找不到if对应了 { for （i=3;i<=n; ++i） { f3=f1+f2; f1=f2; f2=f3;	     } } printf("%d\n", f3);  return 0; }


Question: 求用C语言编几个程序

直接将题目放在百度搜索框里面搜。

这不是acm的题吗


Question: C语言define可以将字符串定义为空格吗？

VC编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898

求教，为什么不可以呢？不是说在读了两个空格确定宏名称之后，剩下的到末尾都是字符串吗？

，，，，不能

参考记事本的替换功能

那要看你怎么用，#define只是做文本上的替换，也就是后面所有用A的位置都被替换为了‘ ’。 如果是char  a = A； 替换之后变成char  a = ‘ ’； 这倒是可以当空格用。


Question: while(getchar() != '\n')

前一个是空语句，所以效果一样

效果是一样的，continue是结束本次循环，后面不再执行

应该是一样的

效果一样，con 会跳过继续下一轮


Question: xcode使用问题

main重复了吧,直接新建个targets

你main函数重复定义了吧。

什么版本的Xcode？  为何不用obj-c？


Question: 求一组正则表达式实现方法

去linux版块吧

提醒：正则表达式不是万能的；有限状态自动机才是万能的。

否定向前查找试试 s/(set\s+((?!nocount)\w)+\s+on)//g

提供给楼主一个新思路： 分四步： 第一步：确定你文件中没有某个字符串，比如”--==--“ 第二步：将所有set nocount on替换为--==-- 第三步：删除所有set ... on的行 第四步：将所有--==--替换为set nocount on

可以先将 on set 替换成 on \nset ，然后在使用正则表达式处理。

什么正则？ 什么环境？


Question: 想找人一起做操作系统

引用 35 楼 u014444402 的回复:连定时器都不用？线程怎么调度？ 可以循环跑任务，能抢占？我是不是可以认为是一个大循环？ 目前只是一级内核，基本适用于所有硬件，升级内核会根据硬件的能力逐渐实现这些功能，在一级内核中有模拟的定时器，光标就是用它来实现的，一级内核运用了简单的消息机制，纯C语言实现，具体实现方法就不说了，想了解的话请加qq1286671822

引用 34 楼 adlay 的回复:不依赖于硬件就意味着不会针对特定的硬件优化，也无法充分发挥硬件的功能。 而要在各种硬件上都能运行，就只能取硬件功能交集的部分来用，面对一个 64 位多核的 CPU，你也把它当成一个 16 位的单核 CPU 来用么？ 因为对硬件的操作是通过包来实现的，所以在做包时会充分利用硬件，发挥其最大功能，在做包时会对不同的硬件做不同的包，并会分不同的位数（我前面提到的是大部分代码通用）。

是感觉好厉害的样子

不用理会别人的质疑，只有写操作系统的过程才能更进一步把自己的技术融会贯通，编写操作系统时候会遇到许许多多的问题，当问题都解决了，什么都不是问题了。

楼主太牛  楼主加油 ,我们用裁剪的linux，本人感觉就挺伟大的，楼主更伟大。

大神加油, 期待国产, 核心技术

加油。。。。。。。。

引用 27 楼 stupid_boy2007 的回复:不明觉厉。中国的屌丝程序员们都疲于生计和攀比吧？ lz好有闲情，不如先研究透UNIX内核吧，有句话说，“不懂UNIX的人，注定发明个蹩脚的UNIX”。 个人觉得只有研究透现有的技术，才有可能青出于蓝。 好，谢谢

...曾经计划写模拟器都没坚持下来的表示支持

做好通知我有用。

只是换了一种显示的方式而已。。。

我看你似乎写的是一个SHELL?

好厉害的样子

引用 18 楼 jack960330 的回复:[quote=引用 17 楼 jack960330 的回复:] [quote=引用 16 楼 u012430857 的回复:] [quote=引用 15 楼 jack960330 的回复:] [quote=引用 14 楼 u012430857 的回复:] [quote=引用 12 楼 jack960330 的回复:] [quote=引用 10 楼 u012430857 的回复:] [quote=引用 7 楼 jack960330 的回复:] 请问目前楼主主要用的什么语言？目测内核层 汇编、c 、应用层cpp 因为大部分代码不依赖硬件，所以内核大部分功能由外部的包来完成，包由汇编和c实现，主程序为c语言编写[/quote] 不可能完全不依赖硬件，内存管理单元（MMU）、中断管理，你肯定有吧？这些都是硬件[/quote] 比如说中断吧，将中断响应函数设置为包内的某个函数，它对信息进行处理后（比如是键盘中断，会将收到的按键编码进行处理后调用主程序的反向信息输入函数），而在主程序里这一切都是抽象的，主程序不知道什么是键盘，什么是鼠标，只会对收到的信息进行处理，所以我会说，对硬件的控制是由包来实现的，而包就相当于一个库。[/quote]  那你引导程序呢？再说了，什么系统不是把很多汇编组编成函数的形式？还是说你会完完全全用汇编实现？[/quote] 首先，主程序是用C写的，并且主程序也相当于是一个函数被调用的，操作系统由包内的引导程序开始，引导程序将操作系统加载完后，会调用主程序，当主程序收到用户发来的关机命令后，会先完成必要的处理，然后调用包内的Shutdown_S__X86_64()关机，包对主程序来说其内部是未知的，可以用汇编写也可以用汇编和C或者是别的写，只要能完成相应的功能就行。再举个例子，主程序不知道显存是什么，甚至不知道显示器如何运行，包只提供一个设置像素的函数，画线等函数都在主程序内，主程序计算出坐标后对相应坐标通过这个函数设置颜色。 我出去有点事，暂时不回复了[/quote]0  正确的顺序是这样的，首先由bios执行自检，然后进入引导程序，首先会进入MBR（主引导记录），由主引导记录根据用户选择调用操作系统的引导记录（MBR引导区一般0柱面0盘面1扇区），引导程序执行后，进行硬件系统初始化，磁盘初始化，读操作系统引导文件，然后跳转到特定地址执行，这个地址还是汇编，所需要做的就是初始化c执行环境，cpu工作模式由实模式切换保护模式，建立系统内核区，然后才真正跳转到入口函数执行c语言入口点，入口点还不行，还要进行保护模式中断向量表初始化、全局内存段初始化、键盘鼠标初始化、硬件设备缓存区初始化、然后设备初始化，驱动初始化，整个过程完成后，才算初始化完成。[/quote]  而且根据系统规模，完善的系统初始化过程还要更多，比如文件系统初始化，win还要加载注册表，[/quote] 是这样的，我也写了初始化函数，具体怎么实现的要是说的话要说很多，还要看最后是怎么做磁盘映像的，我看您对操作系统很了解，可以加个qq好友么，有问题还要请教您 qq1286671822


Question: 有名管道问题

引用 1 楼 user-1 的回复:在创建进程之前打开管道，说明父子进程都有打开那个管道，然后子进程将当前系统时间写到管道中，而父进程只是用来控制每隔一秒运行一次子进程（Ps：管道中有数据，就读）。 第二个fifo程序，在子进程中打开管道，对父进程是没有任何影响的（Ps：也就是说父进程中的操作对管道没有作用），而在子进程中，一直往管道里面写当前系统时间。不太懂。。。你能不能解释一下第二种写法为什么会导致PID乱和刚开始的那一段时间不变而后面就递增呢？

fork（） 创建的进程，父子进程没有先后的执行顺序。所以觉得你这个程序用进程不好，建议直接顺序直接写下去，如果一定要分两步来的话，用线程。其中一个线程sleep（1），另一个线程将当前的系统时间写到管道里去。


Question: gcc里printf("\n");对指针指向的值有影响怎么回事

引用 6 楼 flymanveryhigh 的回复:distribution()函数定义在这个代码文件外，输出的是一个指针，指向一个int数组的开头，正常的传进来了，若是一开始在此文件内部进行复制int数组，复制出来的一点问题没有，如果在复制前加入类似于for();或printf("\n");就可能出问题了，问题是为什么 distribution()刚刚返回后，其局部变量（int数组）内的内容还没有被破坏；但是调用printf()（调用任何函数结果也类似）时，一般要建立printf函数的局部变量空间（栈帧），新函数的局部变量、包括参数很可能与前一次函数调用时的位置重叠，因此覆盖了原先（已经过时了）的局部变量。原int数组的内容就变了。 如果distribution()函数返回的是malloc()分配的空间地址就没问题了，但是要主调函数负责free()掉。

To set a breakpoint when a variable changes value   From the Edit menu, click Breakpoints.   Click the Data tab of the Breakpoints dialog box.   In the Expression text box, type the name of the variable.   Click OK to set the breakpoint.

最关键的函数distribution没给出

怎么就不正常了

distribution() 这个函数返回的int*   是堆空间的还是栈空间 的？

你倒是把代码上全啊出啥问题了都没说清

distribution()函数定义在这个代码文件外，输出的是一个指针，指向一个int数组的开头，正常的传进来了，若是一开始在此文件内部进行复制int数组，复制出来的一点问题，如果在复制前加入类似于for();或printf("\n");就可能出问题了，问题是为什么


Question: 请教C语言如何调用C#动态链接库。。

引用 4 楼 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不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！无限膜拜中。。。。

3楼正解，得com组件

饿，c调用c#的dll....这不行吧； 参考4楼， 如果非要这么做，那得托管的c++才行呢； 另外，也许你可以用托管c＋＋在封装c#dll，然后提供个标准dll接口，让c来调用，我没这么干过只是提供个思路不知道是否可行

俺一般都是把C#封装成COM组件，供C++调用。

C语言大概可以，C++勉强能用，C++/CLI完全够用 取决于你能不能修改C#部分的代码或者重新封装

C#那个dll貌似不叫动态链接库，叫做程序集什么的。


Question: 面试题请教

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

引用 5 楼 ant2012 的回复:类型转换问题  A在进行取反操作前，会转换成整形，然后再进行取反操作  楼主可以通过typeid测一下~A的类型就知道了 的确是这样的，谢谢你的回答啊

引用 2 楼 lgbxyz 的回复:http://bbs.csdn.net/topics/390994744 明白了，谢谢你啊

引用 1 楼 a1193561652 的回复:也许是%u是unsigned int型输出，所以a就被强制转换为unsigned int了。 刚明白了是因为unsign  char在取反的时候进行了类型的提升，unsign  char会变为int型，所以扩展为32位了。谢谢你的回答

printf的压栈参数不是int,就是double, 给一个ushort,还是按int压栈,

这是因为参数传递的关系  要保证正确： unsingned short，short %hu    //十进制: 按照无符号short格式 %hd   // 十进制:  按照(有符号)short格式 %hx   // 十六进制:  按照short格式  /============  unsingned char，char %hhu    //十进制: 按照无符号short格式 %hhd   // 十进制:  按照(有符号)short格式 %hhx   // 十六进制:  按照short格式

刚刚看了下反汇编，发现是因为函数传递参数是通过压栈来实现的，但是压栈一次要压一个双字节的操作数，所以word型的short就被扩展为doubleword型的了。


Question: 关于数组的问题

zip[1][2]等价于*(*(zip + 1)+2)，由于会分配一个连续的内存区域给数组，所以zip[1][2]的结果应该是1才对(gcc的运行结果是1)。

因为数组是顺序存储的，所以如果超出了界限，那么就是下一个这里zippo[1][2]就是第三行的第一个

这个数组是4行2列 zippo[1][2]表示的意思是：第二行，第三列

zippo[1][2]是第2个元素的第3个，下标是从0起的。


Question: 深度优先搜索的问题，很简单，高手稍微指导一下就好

返回这个结点做什么，在while循环里面还是外面好像都不行，如果在调用DFS前加，会忽略之后的代码，如果在调用DFS之后加，那只能访问到最后一个结点时，才开始由下往上，逐级返回  直接压栈不就行了

你递归dfs的时候就没用到返回值, 这值用来做什么


Question: if ..else if.. 后的else可以省掉不？

还是先看一下基础语法吧

引用 3 楼 jiqiang01234 的回复:return 0是单独的依据，和if else没关系，但if语句如果有多个分支，且else分支为空的话，最好把else写出来，顺便加一个断言，表示永远不会进入else分支。     int val = 1;     if(1== val)     {     }     else if(2 == val)     {     }     else     {        assert(0);//表示如果逻辑正确的话，永远不会进入此分支，如果进入会触发断言，程序停止运行     }   你的意思是说：   c/c++规定，可以只有  1 if   2 只有if ....... else if    2种情况，都可以把else 省去， 同时候后面的代码是单独的。

单独的，if只包含下一个{}的，

单独的，if只包含下一个{}的，


Question: 原始套接字 和vlan的问题   来人啊!!!

引用 2 楼 ForestDB 的回复:有没有设置混杂模式？ 又或者是否和你网卡的VLAN模式相关？  混杂模式试过 不管用

引用 2 楼 ForestDB 的回复:有没有设置混杂模式？ 又或者是否和你网卡的VLAN模式相关？  linux应该不纯在这个问题。 vconfig都能配置

有没有设置混杂模式？ 又或者是否和你网卡的VLAN模式相关？

这种问题看TCP/IP详解