Question: 有没有C语言实现的文件夹打包解包的开源代码（压缩或解压文件夹也行）

zip.c   引用 16 楼 z616913706 的回复:[quote=引用 15 楼 vrace 的回复:] [quote=引用 14 楼 robbi666 的回复:] [quote=引用 13 楼 vrace 的回复:] zlib 简单好用啊  www.zlib.net  zlib也没有文件夹压缩[/quote]  zlib 里面的 contrib 文件夹里有一个 minizip， 现成的代码创建/解压缩 zip 文件。当然如果你懒到搜索文件都不愿意做,那就...[/quote]请问是minizip中的zip.c还是minizip.c啊[/quote]

引用 15 楼 vrace 的回复:[quote=引用 14 楼 robbi666 的回复:] [quote=引用 13 楼 vrace 的回复:] zlib 简单好用啊  www.zlib.net  zlib也没有文件夹压缩[/quote]  zlib 里面的 contrib 文件夹里有一个 minizip， 现成的代码创建/解压缩 zip 文件。当然如果你懒到搜索文件都不愿意做,那就...[/quote]请问是minizip中的zip.c还是minizip.c啊

引用 14 楼 robbi666 的回复:[quote=引用 13 楼 vrace 的回复:] zlib 简单好用啊  www.zlib.net  zlib也没有文件夹压缩[/quote]  zlib 里面的 contrib 文件夹里有一个 minizip， 现成的代码创建/解压缩 zip 文件。当然如果你懒到搜索文件都不愿意做,那就...

引用 13 楼 vrace 的回复:zlib 简单好用啊  www.zlib.net  zlib也没有文件夹压缩

版本控制系统(svn,tfs, git等）

留下你邮箱，可以给楼主发个类文件

tar源代码。 gzip源代码。

在线等。。。。

zlib 简单好用啊  www.zlib.net

system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。

引用 8 楼 robbi666 的回复:[quote=引用 4 楼 mujiok2003 的回复:] 版本控制系统(svn,tfs, git等） 我需要的是C下面的，谢谢[/quote] 无能为力呀，c++的，嵌入式是用不了

引用 9 楼 mujiok2003 的回复:[quote=引用 8 楼 robbi666 的回复:] [quote=引用 4 楼 mujiok2003 的回复:] 版本控制系统(svn,tfs, git等） 我需要的是C下面的，谢谢[/quote] 自己写代码压缩还不如使用system()或者popen直接压缩/解压， 工作量少。 [/quote] 不解。。。

引用 8 楼 robbi666 的回复:[quote=引用 4 楼 mujiok2003 的回复:] 版本控制系统(svn,tfs, git等） 我需要的是C下面的，谢谢[/quote] 自己写代码压缩还不如使用system()或者popen直接压缩/解压， 工作量少。

引用 4 楼 mujiok2003 的回复:版本控制系统(svn,tfs, git等） 我需要的是C下面的，谢谢

我找了tar,7z,gzip,Lzma,quicklz,这些都只到压缩单个文件，或者字符串 没有发现那个源码可以压缩文件夹的 tar的源码文件太多，不适合于嵌入式系统 我的邮箱1045537@qq.com，谢谢了

tar gzip 7z ...

tar源代码


Question: 帮忙看一下代码啊，不知道哪里错了！

int i=0; TElemType str[]={"ABC##DE#G##F###"}; char ch; BiTree CreatBitree(BiTree &T){ //移到上面 int i=0; //移到上面 TElemType str[]={"ABC##DE#G##F###"}; ch=str[i++]; if (ch=='#') { T=NULL; } else{ if (!(T=(BiTNode *)malloc(sizeof(BiTNode)))) return ERROR;  T->data=ch; CreatBitree(T->lchild); CreatBitree(T->rchild); } return T; }

先pass编译再说吧


Question: 帮忙解读下这个程序

实现itoa算法？

s[i++] = '-';

引用 1 楼 u011779875 的回复:s[i++] = '-'; ++

把每一句看懂了不就解读了吗？ 哪句看不懂？ 都是基本语法啊

引用 5 楼 u010334406 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 请大师继续指导下，我是新手，现在只会用vc++6.0的ctrl+f7和ctrl+f5，[/quote] 现在立即学会用F11，F10，Shift+F11.

引用 3 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 请大师继续指导下，我是新手，现在只会用vc++6.0的ctrl+f7和ctrl+f5，


Question: 求 40bit数据分割为10bit数据方法！60分！！

unsigned char buf[5] = {0x12, 0x34, 0x56, 0x78, 0x9a};    unsigned int res[4];    res[0] = ((buf[0] & 0xff) << 2 ) | (buf[1] >> 6);//8bits + 2bits    res[1] = ((buf[1] & 0x3f) << 2) | (buf[2]>> 4); //6bits + 4bits    res[2] = ((buf[2] & 0x0f) << 4) | (buf[3] >> 2); //4bits + 6bits    res[3] = ((buf[3] & 0x03) << 2) |  buf[4];//2bits+8bits

跟着大神走，就是开眼界啊@！

引用 8 楼 yulitingfeng 的回复:[quote=引用 7 楼 u011779875 的回复:] 60分就是管用啊 这么快就有大神来了  还是如果问题想要快速被解决掉 1 问题实在太简单 2 只要你开的起分 重赏之下必有勇夫大神才不在乎分，只是你的问题简单，但不是很无聊[/quote] 我都说了俩种可能 1 || 2 当然这来的人都是1 所以嘛 2就不会判断了 短路 所以为了1的 不代表它不为了2  只是不判断2而已

引用 7 楼 u011779875 的回复:60分就是管用啊 这么快就有大神来了  还是如果问题想要快速被解决掉 1 问题实在太简单 2 只要你开的起分 重赏之下必有勇夫大神才不在乎分，只是你的问题简单，但不是很无聊

给你一个把10位分成两个5位的，你比个葫芦画个瓢吧  #include "stdafx.h" #include<iostream> #include <stdio.h> #include <bitset> using namespace std;  int main() { 	bitset<10> b=0x2ab;     for(int i=0;i<2;i++) 	{ 	  bitset<5> temp; 	  for(int j=0;j<5;j++) 	  { 	    temp[j]=b[5*i+j]; 	  }  	  cout<<temp.to_ulong()<<endl; 	}     return 0; }

引用 4 楼 worldy 的回复:long long x=....; n1=x1 & 1024； x=x>>10; n2=x1 & 1024 .... 引用 2 楼 max_min_ 的回复:取首地址，偏移获取需要的字节数据，保存起来！OK  大神

引用 1 楼 u012565501 的回复:共同体问题吧 可是共同体都是8位啊 怎么分割出10位出来？

取首地址，偏移获取需要的字节数据，保存起来！OK

共同体问题吧

谢谢楼上各位了，问题解决！！结贴发分了@！

飘过。

仅供参考：（有显摆之嫌！）//有一个二进制文件，要求每隔50bits，删除后面的12bits。 #include <stdio.h> #include <stdlib.h> #include <string.h> FILE *fi,*fo; char buf[31]; char obf[31]; int bn,n; void filter() {//对buf中前n个字节中的位，每隔50bits，忽略12bits，结果放在obf中,且将bn设置为obf中的字节数。     char bit[249];     char obt[249];     char b8[33];     char b88[33];     int i,j;     char *e;      for (i=0;i<n;i++) {         _itoa(buf[i],b8,2);         sprintf(b88,"%032s",b8);         sprintf(bit+i*8,"%s",b88+24);     }      j=0;     for (i=0;i<n*8;i++) {         if (i%62<50) {             obt[j]=bit[i];             j++;         }     }     if (j%8) {         bn=(j/8+1)*8;     } else {         bn=j;     }     for (i=j;i<bn;i++) obt[i]='0';     obt[bn]=0;     bn=bn/8;     for (i=0;i<bn;i++) {         strncpy(b8,obt+i*8,8);b8[8]=0;         obf[i]=(char)strtol(b8,&e,2);     } } int main() {     fi=fopen("in.bin","rb");     if (NULL==fi) {         printf("Can not open file in.bin!\n");         return 1;     }     fo=fopen("out.bin","wb");     if (NULL==fo) {         fclose(fi);         printf("Can not open file out.bin!\n");         return 2;     }     while (1) {         n=fread(buf,1,31,fi);         if (0==n) break;         filter();         fwrite(obf,1,bn,fo);     }     fclose(fo);     fclose(fi);     return 0; }


Question: linux进程通信，我使用信号灯和共享内存方式通信不上求解答。

《Linux C编程一站式学习》


Question: 求解决问题的代码，数据结构最小生成树问题

英语不好 没怎么看！ 但一般数据结构的教材上都会介绍 prime算法和kruskal算法吧！

没权重的话就用了个深度优先搜索，有哪座城被占需要修的路条数多就要终点保护了，有权重了蛋疼了

没有权重的时候 你是根据什么来生成最小生成树的

这个你可以看看http://blog.csdn.net/realxuejin/article/details/10522383

同求……看过一些C++的思路，大概意思是应该先用kruskal算法获得最小生成树，然后就不知道了……求C语言算法啊！


Question: Window关于关掉窗口后，程序仍运行

引用 2 楼 worldy 的回复:送入当前线程的消息队列  当前的消息队列它的唯一标识是句柄吗？

GetMessage拿出来死掉吗 啥意思？  GetMessage如果发现消息是WM_QUIT，则返回0值，循环结束，WinMain函数结束，程序终止

送入当前线程的消息队列

如果hWnd为NULL，则GetMessage接收属于调用线程的窗口的消息，线程消息由函数PostThreadMessage寄送给调用线程。  PostQuitMessage寄送一个WM_QUIT消息给线程的消息队列并立即返回；此函数向系统表明有个线程请求在随后的某一时间终止。  这个不是PostQuitMessage发送到线程消息队列  GetMessage拿出来死掉吗


Question: 谁帮个忙，改下程序

引用 3 楼 max_min_ 的回复: arr = (struct el**)calloc(10,sizeof(struct el ));         for(i=0;i<10;i++){                 arr[i] = malloc(sizeof(struct el) * 10);  //因为是两重循环所以这样赋值错的，应该两重循环赋值打印！试试！具体可参考int类型，                    两重循环赋值,再加一个循环？没想到怎么用！！

#include<stdio.h> #include<malloc.h> struct el{         int a; }; int main(int argc, char **argv) {         struct el ***arr;         int i,j;         arr = (struct el***)calloc(10,sizeof(struct el **));         for(i=0; i<10; ++i)         {             arr[i] = (struct el**)calloc(10,sizeof(struct el *));             for(j=0;j<10;++j)             {                 arr[i][j] = (struct el*)malloc(sizeof(el));                 arr[i][j]->a=i;             }         }         for(i=0;i<10;i++){                 for(j=0;j<10;++j)                 {                     printf("arr[%d][%d]:%d\n",i,j,arr[i][j]->a);                 }          }         return 0; }

在学libevent，其中上边的测试struct el其实是struct event_list，libevent处理优先级就用到了struct event_list **activequeues;  曾经也看过lighttp，就用到了三级指针。

下面这个程序就是实现用一个三级指针来指向一个二维数组的方法.如果是4维,5维,那么指针级数也随着增加.  #include <stdio.h> #include <stdlib.h>  struct test {                 int a; };   int main( int argc, char **argv ) {         if( argc != 3 )         {                 printf( "Usage: proram first_arry_size second_arry_size\n" );                 return -1;         }         struct test ***tmp;         int i, j, first_arry_size, second_arry_size;         first_arry_size = atoi(argv[1]);         second_arry_size = atoi(argv[2]);         tmp = (struct test ***)malloc(first_arry_size*sizeof(struct test **));         for( i=0; i<first_arry_size; i++ )         {                 tmp[i] = (struct test **)malloc(second_arry_size*sizeof(struct test *));                 for( j=0; j<second_arry_size; j++ )                 {                         tmp[i][j] = (struct test *)malloc(sizeof(struct test));                         tmp[i][j]->a = i*10+j;                 }         }         for( i=0; i<first_arry_size; i++ )   {     for( j=0; j<second_arry_size; j++ )                 {                         printf( "arry[%d][%d]: %d\n", i, j, tmp[i][j]->a );                         free(tmp[i][j]);                 }                 free(tmp[i]);   }   free(tmp); }

三级指针 是大神才用得起的 至少我从来未敢涉足 我在想 什么事情是必须得用三级指针的 你要做什么 实验还是 说有特殊需求

在你的基础上修改了一下，不知合你意不？申请二维数组的话不必用三级指针！  #include<stdio.h> #include<malloc.h> struct el{         int a; }; int main(int argc, char **argv){         struct el **arr;         int i,j,num = 0;         arr = (struct el**)calloc(10,sizeof(struct el *));         for(i=0;i<10;i++){                 arr[i] = malloc(sizeof(struct el) * 5);                 for(j = 0;j < 5;j++)                 {                 	arr[i][j].a = num++;                 }         }         for(i=0;i<10;i++){              for(j = 0;j < 5;j++)                 {                 	printf("%d\n",arr[i][j].a);                 }            }         return 0; }

仅供参考//在堆中开辟一个3×4×5的3维int数组 #include <stdio.h> #include <malloc.h> int ***p; int i,j,k; void main() {     p=(int ***)malloc(3*sizeof(int **));     if (NULL==p) return;     for (i=0;i<3;i++) {         p[i]=(int **)malloc(4*sizeof(int *));         if (NULL==p[i]) return;         for (j=0;j<4;j++) {             p[i][j]=(int *)malloc(5*sizeof(int));             if (NULL==p[i][j]) return;         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 p[i][j][k]=i*20+j*5+k;             }         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 printf(" %2d",p[i][j][k]);             }             printf("\n");         }         printf("---------------\n");     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             free(p[i][j]);         }         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //--------------- // 20 21 22 23 24 // 25 26 27 28 29 // 30 31 32 33 34 // 35 36 37 38 39 //--------------- // 40 41 42 43 44 // 45 46 47 48 49 // 50 51 52 53 54 // 55 56 57 58 59 //---------------  //在堆中开辟一个2×3×4×5的4维int数组 #include <stdio.h> #include <malloc.h> int ****p; int h,i,j,k; void main() {     p=(int ****)malloc(2*sizeof(int ***));     if (NULL==p) return;     for (h=0;h<2;h++) {         p[h]=(int ***)malloc(3*sizeof(int **));         if (NULL==p[h]) return;         for (i=0;i<3;i++) {             p[h][i]=(int **)malloc(4*sizeof(int *));             if (NULL==p[h][i]) return;             for (j=0;j<4;j++) {                 p[h][i][j]=(int *)malloc(5*sizeof(int));                 if (NULL==p[h][i][j]) return;             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     p[h][i][j][k]=h*60+i*20+j*5+k;                 }             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     printf(" %3d",p[h][i][j][k]);                 }                 printf("\n");             }             printf("--------------------\n");         }         printf("=======================\n");     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 free(p[h][i][j]);             }             free(p[h][i]);         }         free(p[h]);     }     free(p); } //   0   1   2   3   4 //   5   6   7   8   9 //  10  11  12  13  14 //  15  16  17  18  19 //-------------------- //  20  21  22  23  24 //  25  26  27  28  29 //  30  31  32  33  34 //  35  36  37  38  39 //-------------------- //  40  41  42  43  44 //  45  46  47  48  49 //  50  51  52  53  54 //  55  56  57  58  59 //-------------------- //======================= //  60  61  62  63  64 //  65  66  67  68  69 //  70  71  72  73  74 //  75  76  77  78  79 //-------------------- //  80  81  82  83  84 //  85  86  87  88  89 //  90  91  92  93  94 //  95  96  97  98  99 //-------------------- // 100 101 102 103 104 // 105 106 107 108 109 // 110 111 112 113 114 // 115 116 117 118 119 //-------------------- //======================= //


Question: 定点类型

引用 1 楼 user-1 的回复: printf("%d", 3 * k);  不支持直接的 这我知道，关键是啥是定点类型？

printf("%d", 3 * k);  不支持直接的


Question: 关于二维数组传参的问题

void fun(char(*a)[2])  编译器认为你是要传递一个函数指针的数组

引用 6 楼 z1179675084 的回复:把后缀名改为。c才行，你第二种写法是gcc的扩展语法，不是标准C里面的，出错没有什么奇怪的！VS没有实现C99标准，不代表这种写法就不是标准写法吧...这不是gcc的扩展语法，只是一些编译器厂商不肯按标准实现罢了。如果是C，这绝对是正确的写法，C++就算了...

C++还不支持直接的变长数组，不过C++11可以利用constexpr这个关键字，将值转换成编译器常量。老的作法是用指针new...或者封装成类，然后重载[]（其实还是new）。听说C++14可能会允许变长数组，具体还要等新标准

貌似gcc才行，g++不能传变长数组出去...至今还不没用过变长的说...

目前绝大多数的编译器只编译元素数量为 常量的 数组

错在这里   int n = 2;      char a[n][n];

引用 楼主 jmy5945hh 的回复:void fun(char(*a)[2]) { }    int main()  {     char a[2][2];     fun(a); }   以上代码可以正常编译。  void fun(char(*a)[2]) { }    int main()  {     int n = 2;     char a[n][n];     fun(a); }   以上代码编译报错。  GCC环境。  test.cpp:19:10: error: cannot convert ‘char (*)[(((unsigned int)(((int)n) + -0x00000000000000001)) + 1)]’ to ‘char (*)[2]’ for argument ‘1’ to ‘void fun(char (*)[2])’   WHAT THE HELL！   int n = 2;    char a[n][n];  这个是什么标准啊  我怎么没见过这么用的 这个n必须得在编译之前知道n的值 才能知道 要开辟多大的空间 你这个n也是编译时候才知道的


Question: 求问如何定义长度为1000000的结构体数组？

其实不大，1M个对象而已。楼主做科学计算？

引用 5 楼 u012090902 的回复:我直接写struct定义这个结构没问题吧？不用换typedef struct吧？没问题。。。

定义成全局数组或者静态数组，存放的位置不一样

如果真需要这么大的数组，可以先缓存到硬盘上，再分段读取处理。

好奇楼主的需求啊，  struct path *test=(struct path*)malloc(sizeof(struct path) * 1000000);

用内存映射吧，数据多的话这样不效率~~

Windows ~ 调用 win32 api - CreateFileMapping , OpenFileMapping ...  Linux ~ 调用  mmap ....  开 MemoryMapped file 出来用   几百MB 都没问题

引用 5 楼 u012090902 的回复:我直接写struct定义这个结构没问题吧？不用换typedef struct吧？  问个鸡巴问,自己上机试不就知道了吗? 不动手,光鸡巴问有逑用 是试出来的结果可靠,还是别人告诉你的结果可靠?

a=new xxx[1000000];

struct path *x=(struct path*)malloc(sizeof(path)*1000000);  x[0].a=250; x[999999].a=250;

struct path *pArray = malloc(10000000*sizeof(struct path))使用malloc申请吧。

结构体是这么 struct path { int a; int b; int c; int d; }; 要建一个大小1000000的这种结构体数组

http://baike.baidu.com/link?url=nCMZ_56CMJFvvJdLXH4PtrsEuG3r2Pi_9TVBJgECMiMjVS2Juicpv-y23CmmYrHOufO2vqgfOnBF9zE_gMblR_  你的结构体多大？你的意思是你要在heap上申请？


Question: int max(int a,int b)默认返回值的问题

引用 8 楼 u011779875 的回复:c=max(a,b);   00A1403  mov         eax,dword ptr [b]    000A1406  push        eax    000A1407  mov         ecx,dword ptr [a]    000A140A  push        ecx    000A140B  call        max (0A1109h)    000A1410  add         esp,8    000A1413  mov         dword ptr [c],eax  看到了吗 用俩个参数的时候压栈分别用了eax ecx 你是这样调用的 c=max(2,3); c默认调用从右向左 这样的话 eax保存的是2 所以你换成 c=max(3,2); 返回值就是3了 专业吧 20分都给我吧 他们 都不专业 哈哈  汇编确实是一个好东西啊！！

引用 12 楼 u011779875 的回复:又没说好  最后指行得是这句话   if(a>b)   00A313AE  mov         eax,dword ptr [a]   00A313B1  cmp         eax,dword ptr [b] 因为不成立 return没执行  最后留下的是   00A313AE  mov         eax,dword ptr [a] ++ 有返回值的函数的返回值，不是随机的。 而是运算的结果（程序返回一个值）； 或者计算残留的值（程序没有返回一个值）。  X86,32Bits, 有些类型(如int)，是eax 寄存器的残留值，有些是（如 long long) edx:eax, 浮点数类型，是寄存器 ST，即寄存器堆栈的栈顶。  其他时候， eax 可能是个指针，指向返回值的地址。  X86，X64 64 Bits ,int 可能是rax(r0) 寄存器的残留值

引用 8 楼 u011779875 的回复:c=max(a,b);   00A1403  mov         eax,dword ptr [b]    000A1406  push        eax    000A1407  mov         ecx,dword ptr [a]    000A140A  push        ecx    000A140B  call        max (0A1109h)    000A1410  add         esp,8    000A1413  mov         dword ptr [c],eax  看到了吗 用俩个参数的时候压栈分别用了eax ecx 你是这样调用的 c=max(2,3); c默认调用从右向左 这样的话 eax保存的是2 所以你换成 c=max(3,2); 返回值就是3了 专业吧 20分都给我吧 他们 都不专业 哈哈 高手

引用 楼主 lubyam 的回复:  使用的是vs2012 test.c int max(int a,int b) {     if(a>b)     {         return a;     } }  -----------  int main(int argc,char *argv[]) {     int a=2;     int b=3;     int c=0;     c=max(a,b);     printf("%d",c); }   为什么输出来的是2而不是0； a = b或a < b怎么办？

引用 10 楼 Adol1111 的回复:[quote=引用 5 楼 lubyam 的回复:] 恩恩，，，但是    以前 我记得这样 就不会返回一个值 的 不是不返回，是返回一个随机结果（看系统，看编译器什么的）。C/C++只要求至少返回一次，没有要求所有路径都要有返回，但不代表不写就是不返回。建议每次写函数都检查是否所有路径都有返回值，C/C++编译器不能提示，只能看程序员自己了。[/quote] 有一点没说明白继续看 int max(int a,int b) { 00A31390  push        ebp   00A31391  mov         ebp,esp   00A31393  sub         esp,0C0h   00A31399  push        ebx   00A3139A  push        esi   00A3139B  push        edi   00A3139C  lea         edi,[ebp-0C0h]   00A313A2  mov         ecx,30h   00A313A7  mov         eax,0CCCCCCCCh   00A313AC  rep stos    dword ptr es:[edi]       if(a>b) 00A313AE  mov         eax,dword ptr [a]   00A313B1  cmp         eax,dword ptr [b]   00A313B4  jle         max+29h (0A313B9h)       {         return a; 00A313B6  mov         eax,dword ptr [a]       } }没说全  你里面比较的时候是这样的 eax,dword ptr [a]   所以eax最后留下的是a的值 因为ax被汇编成最后的return a; 所以最后的值是a的值

引用 5 楼 lubyam 的回复:恩恩，，，但是    以前 我记得这样 就不会返回一个值 的 不是不返回，是返回一个随机结果（看系统，看编译器什么的）。C/C++只要求至少返回一次，没有要求所有路径都要有返回，但不代表不写就是不返回。建议每次写函数都检查是否所有路径都有返回值，C/C++编译器不能提示，只能看程序员自己了。

汇编很重要 这个也是区分菜鸟和高手的 分水岭  首先呢 我也是菜鸟 我从来没思考过你的这个问题 其次呢 我面对问题的解决方法 明显就比你厉害 所以呢 做什么都厉害的 哈哈

引用 6 楼 lubyam 的回复:[quote=引用 4 楼 u011779875 的回复:] max都返回最小值2了啊  它返回的时候把值复制给c 之后就销毁了函数里面的变量了  打印2那是自然的 要是打出的是0 那你就见鬼了 赶紧拨打110   函数里面的 a>b不成立的啊[/quote] 是啊  哦这样啊  返回值存在于eax 寄存器  既然你没有返回的话 那就默认返回eax中上次的值 00A1403  mov         eax,dword ptr [b]   000A1406  push        eax   000A1407  mov         ecx,dword ptr [a]   000A140A  push        ecx   000A140B  call        max (0A1109h)   000A1410  add         esp,8   000A1413  mov         dword ptr [c],eax

引用 4 楼 u011779875 的回复:max都返回最小值2了啊  它返回的时候把值复制给c 之后就销毁了函数里面的变量了  打印2那是自然的 要是打出的是0 那你就见鬼了 赶紧拨打110   函数里面的 a>b不成立的啊

恩  引用 3 楼 wangdahu888 的回复:int max(int a,int b) {     if(a>b) 如果a<b是不是就没返回值了     {         return a;     } } 编译器应该给你个“并不是所有的执行路径都有返回值”的警告吧  恩恩，，，但是    以前 我记得这样 就不会返回一个值 的

引用 1 楼 user-7 的回复:这个东西就是看编译器了, 这种不确定的东西, 你应该自己处理掉, 在函数结束的地方返回一个默认值. 而不是认编译器去给你指定默认返回值. 只是  在无意的时候发现的，   我想问以下，，是不是  编译器在 知道函数有返回值的时候   ，如果函数会返回一个 默认的值， 那么对于这个默认的值，是怎么确定的呢？


Question: TCP問題

请检查每个函数调用的返回值！确认每步的正确性！

server的程序     m_RecvLen = m_SocketServer.Receive(m_SendBuffer, m_RecvBuffer.Length, SocketFlags.None); m_SendBuffer 这个应该使用错了，缓冲溢出问题。


Question: 有关C语言从文件读取字符串存入到数组中，急求解答！！！

楼主 你用16进制看一下你的文件最后是什么数据

用0初始化 准确的说 应该是最后一个char name[50]没有用\0来结束 就把之后的0XCC都输出了

其实： while（2==fscanf(file, "%d%s", &bench[i][j].count, bench[i][j].name)） { 。。。 } 就完了。

请判断fscanf函数的返回值！

你用的那个嵌套循环把次数翻了一倍，再往后读就越界了。 试试这样看看。 	if(file == NULL) 	{ 		printf("该文件不存在！"); 	} 	else 	{ 		for(int i = 0; i < ROW ; ++i)   			fscanf(file, "%d%s", &bench[i].count, bench[i].name); 		fclose(file); 	} 	for(int i = 0 ; i < ROW ; ++i) 		printf("%d    %s \n",bench[i].count, bench[i].name); 	system("pause");

引用 20 楼 schlafenhamster 的回复:if（2==fscanf(file, "%d%s", &bench[i][j].count, bench[i][j].name)） {  }判断下数据是否成功读入。 你的数组是固定的长度，而文件里是否有足够的数据来填充数组呢？ 如果读入中途出错或者数据已经结束，读入是否应该终止？ 打印时应该以读入后的数组大小来做边界。如果数组并没有那么多数据呢？数组打印的值后面肯定是不正确的吗？

memset(bench,0,sizeof(bench));   可以处理掉后面的烫字

没有初始化造成的 打开文件之前加一句  memset(bench,0,sizeof(bench));   便可解决问题

很明显是读文件读出错了!  fscanf(file, "%d%s", &bench[i][j].count, bench[i][j].name); 上面加两句 bench[i][j].count = 0; bench[i][j].name[0] = '\0';

引用 3 楼 wangdahu888 的回复:很明显访问了栈访问越界了。栈的内容通常以0CCCCCCCCh来初始化，就那个 烫 字 三楼神人啊，这都被你发现了，应该得分！

注意，fscanf函数在遇到文件EOF时会返回-1；因此可以将程序的原fscanf行改成:        int res = fscanf(file, "%d%s", &bench[i][j].count, bench[i][j].name);         if(res == -1) { break; } 搞定了的话 把分给我

引用 14 楼 u011779875 的回复:[quote=引用 12 楼 maspacious 的回复:] [quote=引用 11 楼 u011779875 的回复:] [quote=引用 10 楼 maspacious 的回复:] [quote=引用 9 楼 u011779875 的回复:] 文件 有问题 txt 里面有非法字符可能 你删除出错那行 把前面的复制到下面  继续调试 没有出错的行啊。3312全部输出了都正确 只是后面多余了[/quote] #define ROW 3312  你看我的帖子了吗  你文件就3312行  你定义的是3312 我开始你就和你说了 你输出的时候 还是输出的3312  for(int i = 0 ; i < ROW ; ++i)         for(int j = 0; j < COL ; ++j)  你有那么多吗 读到那么多了吗 就输出[/quote] 你看我程序了么  是 二维的 3312行2列。正常输出不就是这样么[/quote]   fscanf(file, "%d%s", &bench[i][j].count, bench[i][j].name);   这个函数读取文本的时候开始的时候都是没一行有1个\n 但是读取到最后一行的时候直接就是-1了 所以 你要在读最后一行做一个处理[/quote]   问题已经解决了。不是这个问题。 我只需要一个一维数组 里面包含两个内容。二我申请了一个二维的。

引用 12 楼 maspacious 的回复:[quote=引用 11 楼 u011779875 的回复:] [quote=引用 10 楼 maspacious 的回复:] [quote=引用 9 楼 u011779875 的回复:] 文件 有问题 txt 里面有非法字符可能 你删除出错那行 把前面的复制到下面  继续调试 没有出错的行啊。3312全部输出了都正确 只是后面多余了[/quote] #define ROW 3312  你看我的帖子了吗  你文件就3312行  你定义的是3312 我开始你就和你说了 你输出的时候 还是输出的3312  for(int i = 0 ; i < ROW ; ++i)         for(int j = 0; j < COL ; ++j)  你有那么多吗 读到那么多了吗 就输出[/quote] 你看我程序了么  是 二维的 3312行2列。正常输出不就是这样么[/quote]   fscanf(file, "%d%s", &bench[i][j].count, bench[i][j].name);   这个函数读取文本的时候开始的时候都是没一行有1个\n 但是读取到最后一行的时候直接就是-1了 所以 你要在读最后一行做一个处理

最后一次读 没有/0 你要做特殊的处理  】我才看出问题所在

引用 11 楼 u011779875 的回复:[quote=引用 10 楼 maspacious 的回复:] [quote=引用 9 楼 u011779875 的回复:] 文件 有问题 txt 里面有非法字符可能 你删除出错那行 把前面的复制到下面  继续调试 没有出错的行啊。3312全部输出了都正确 只是后面多余了[/quote] #define ROW 3312  你看我的帖子了吗  你文件就3312行  你定义的是3312 我开始你就和你说了 你输出的时候 还是输出的3312  for(int i = 0 ; i < ROW ; ++i)         for(int j = 0; j < COL ; ++j)  你有那么多吗 读到那么多了吗 就输出[/quote] 你看我程序了么  是 二维的 3312行2列。正常输出不就是这样么

引用 10 楼 maspacious 的回复:[quote=引用 9 楼 u011779875 的回复:] 文件 有问题 txt 里面有非法字符可能 你删除出错那行 把前面的复制到下面  继续调试 没有出错的行啊。3312全部输出了都正确 只是后面多余了[/quote] #define ROW 3312  你看我的帖子了吗  你文件就3312行  你定义的是3312 我开始你就和你说了 你输出的时候 还是输出的3312  for(int i = 0 ; i < ROW ; ++i)         for(int j = 0; j < COL ; ++j)  你有那么多吗 读到那么多了吗 就输出

引用 9 楼 u011779875 的回复:文件 有问题 txt 里面有非法字符可能 你删除出错那行 把前面的复制到下面  继续调试 没有出错的行啊。3312全部输出了都正确 只是后面多余了

引用 7 楼 maspacious 的回复:[quote=引用 6 楼 wangdahu888 的回复:] [quote=引用 3 楼 wangdahu888 的回复:] 很明显访问了栈访问越界了。栈的内容通常以0CCCCCCCCh来初始化，就那个 烫 字 我说错了，应该是访问了未被写入内容的栈空间，栈的内容通常以0CCCCCCCCh来初始化，就那个 烫 字[/quote]  如何修改。。。。找不到地方啊[/quote] 我以前真的遇到过这个问题 只是脑袋忘记了 是哪了


sprintf_s 后缀 s 是safe的缩写，代表这个函数是sprintf的安全版本。 改正一下  下面这个，不管能不能编译通过，都是错误的。  sprintf_s(filename,"%s %s %s %s",path1,path2,path3,path4);  "%s %s %s %s"，这个指针（常量字符串，字符串字面值），强制转换成size_t 整型数，path1被看作，格式化串。 居然能编译通过？？？？？，不过运行时就错得离谱了。 只能得到path1，因为path1里无格式符号 ，即无 %。  输出结果可能是这样的， "D:\Program\Tesseract-OCR\tesseract.exe";  这种用法， sprintf_s是不能保证安全的，地址的值至少Windows 上32Bits 是个很大的数字。 这样一来，就没有安全可言了。 size_t sizeOfBuffer,这个参数，是控制结果的。 保证sprintf_s 结果的串长，不超过sizeOfBuffer。

sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4); 这是正确的。 下面这个，不管能不能编译通过，都是错误的。  sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4);  "%s %s %s %s"，这个指针（常量字符串，字符串字面值），强制转换成size_t 整型数，path1被看作，格式化串。 居然能编译通过？？？？？，不过运行时就错得离谱了。 只能得到path1，因为path1里无格式符号 ，即无 %。  输出结果可能是这样的， "D:\Program\Tesseract-OCR\tesseract.exe";

引用 21 楼 jiaoyun007 的回复:[quote=引用 18 楼 mujiok2003 的回复:] 有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only 这位仁兄，你是从哪找到的？发个链接可好 [/quote] 这是链接

warning C4047: “函数”:“size_t”与“char [12]”的间接级别不同 warning C4024: “sprintf_s”: 形参和实参 2 的类型不同 VS2012只会warning不会error 我的结论是即使参数类型不同，假如两者可以强制转换，编译器只会警告不会报错。  楼主代码报错的原因其实跟sprintf_s一点关系也没，原因只有一个： error C2065: “new”: 未声明的标识符。 C语言里是没有new关键字的，你换用malloc就不报错了。以及，代码只能这么写，不能省略中间参数。 sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4);

引用 18 楼 mujiok2003 的回复:有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only 这位仁兄，你是从哪找到的？发个链接可好

int sprintf_s(    char *buffer,    size_t sizeOfBuffer,    const char *format [,    argument] ...  ); template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only   MSDN给出了答案。

引用 18 楼 mujiok2003 的回复:有重载版本template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,    argument] ...  ); // C++ only  这个答案靠谱！

Collapse AllExpand All      Code: All Code: Multiple Code: Visual Basic Code: C# Code: Visual C++ Code: J# Code: JScript   Visual Basic C# Visual C++ J# JScript Run-Time Library Reference  sprintf_s, _sprintf_s_l, swprintf_s, _swprintf_s_l  Example  See Also  Send Feedback     Write formatted data to a string. These are versions of sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l with security enhancements as described in Security Enhancements in the CRT.    int sprintf_s(    char *buffer,    size_t sizeOfBuffer,    const char *format [,       argument] ...  ); int _sprintf_s_l(    char *buffer,    size_t sizeOfBuffer,    const char *format,    locale_t locale [,       argument] ...  ); int swprintf_s(    wchar_t *buffer,    size_t sizeOfBuffer,    const wchar_t *format [,       argument]... ); int _swprintf_s_l(    wchar_t *buffer,    size_t sizeOfBuffer,    const wchar_t *format,    locale_t locale [,       argument]… ); template <size_t size> int sprintf_s(    char (&buffer)[size],    const char *format [,       argument] ...  ); // C++ only template <size_t size> int swprintf_s(    wchar_t (&buffer)[size],    const wchar_t *format [,       argument]... ); // C++ only    Parameters buffer Storage location for output  sizeOfBuffer Maximum number of characters to store.  format Format-control string  argument Optional arguments  locale The locale to use.  For more information, see Format Specifications.  Return Value The number of characters written, or –1 if an error occurred. If buffer or format is a null pointer, sprintf_s and swprintf_s return -1 and set errno to EINVAL.  sprintf_s returns the number of bytes stored in buffer, not counting the terminating null character. swprintf_s returns the number of wide characters stored in buffer, not counting the terminating null wide character.  Remarks The sprintf_s function formats and stores a series of characters and values in buffer. Each argument (if any) is converted and output according to the corresponding format specification in format. The format consists of ordinary characters and has the same form and function as the format argument for printf. A null character is appended after the last character written. If copying occurs between strings that overlap, the behavior is undefined.  One main difference between sprintf_s and sprintf is that sprintf_s checks the format string for valid formatting characters, whereas sprintf only checks if the format string or buffer are NULL pointers. If either check fails, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, the function returns -1 and sets errno to EINVAL.  The other main difference between sprintf_s and sprintf is that sprintf_s takes a length parameter specifying the size of the output buffer in characters. If the buffer is too small for the text being printed then the buffer is set to an empty string and the invalid parameter handler is invoked. Unlike snprintf, sprintf_s guarantees that the buffer will be null-terminated (unless the buffer size is zero).  swprintf_s is a wide-character version of sprintf_s; the pointer arguments to swprintf_s are wide-character strings. Detection of encoding errors in swprintf_s may differ from that in sprintf_s. The versions of these functions with the _l suffix are identical except that they use the locale parameter passed in instead of the current thread locale.  In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure Template Overloads.  There are versions of sprintf_s that offer additional control over what happens if the buffer is too small. For more information, see _snprintf_s, _snprintf_s_l, _snwprintf_s, _snwprintf_s_l.  TCHAR.H routine   _UNICODE & _MBCS not defined  _MBCS defined  _UNICODE defined   _stprintf_s  sprintf_s  sprintf_s  swprintf_s   _stprintf_s_l  _sprintf_s_l  _sprintf_s_l  _swprintf_s_l    Requirements Routine  Required header   sprintf_s, _sprintf_s_l  <stdio.h>   swprintf_s, _swprintf_s_l  <stdio.h> or <wchar.h>    For additional compatibility information, see Compatibility in the Introduction.  Example   Copy Code  // crt_sprintf_s.c // This program uses sprintf_s to format various // data and place them in the string named buffer. //  #include <stdio.h>  int main( void ) {    char  buffer[200], s[] = "computer", c = 'l';    int   i = 35, j;    float fp = 1.7320534f;     // Format and print various data:     j  = sprintf_s( buffer, 200,     "   String:    %s\n", s );    j += sprintf_s( buffer + j, 200 - j, "   Character: %c\n", c );    j += sprintf_s( buffer + j, 200 - j, "   Integer:   %d\n", i );    j += sprintf_s( buffer + j, 200 - j, "   Real:      %f\n", fp );     printf_s( "Output:\n%s\ncharacter count = %d\n", buffer, j ); }     Copy Code  Output:    String:    computer    Character: l    Integer:   35    Real:      1.732053  character count = 79     Copy Code  // crt_swprintf_s.c // wide character example // also demonstrates swprintf_s returning error code #include <stdio.h>  int main( void ) {    wchar_t buf[100];    int len = swprintf_s( buf, 100, L"%s", L"Hello world" );    printf( "wrote %d characters\n", len );    len = swprintf_s( buf, 100, L"%s", L"Hello\xffff world" );    // swprintf_s fails because string contains WEOF (\xffff)    printf( "wrote %d characters\n", len ); }     Copy Code  wrote 11 characters wrote -1 characters    .NET Framework Equivalent System::String::Format  See Also Concepts Stream I/O fprintf, _fprintf_l, fwprintf, _fwprintf_l printf, _printf_l, wprintf, _wprintf_l scanf, _scanf_l, wscanf, _wscanf_l sscanf, _sscanf_l, swscanf, _swscanf_l vprintf Functions Send feedback on this topic to Microsoft.

纳闷了，代码这样写：  int _tmain(int argc, _TCHAR* argv[]) { 	char filename[1024];//预先分配缓冲区 	char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe"; 	char path2[128] = "D:\\Program\\Tesseract-OCR\\"; 	char path3[128] = "D:\\Program\\Tesseract-OCR\\txt"; 	char path4[128] = "-l chi_sim"; 	sprintf_s(filename,1024, "%s %s %s %s",path1,path2,path3,path4); //无论这里是否有1024这个参数，都可以编译通过 	 	return 0; 	 }  在VS2010下测试，有疑问啊

真的有点纳闷了，代码如下：      ... ...     char* filename = new char[1024]; //这样就会报出编译错误     char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe";     char path2[128] = "D:\\Program\\Tesseract-OCR\\";     char path3[128] = "D:\\Program\\Tesseract-OCR\\txt";     char path4[128] = "-l chi_sim";     sprintf_s(filename,1024，"%s %s %s %s",path1,path2,path3,path4);     delete []filename;     return 0; ... ...  就可以，改成下面：  char filename[1024];//这个可以     char* filename = new char[1024]; //这样就会报出编译错误     char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe";     char path2[128] = "D:\\Program\\Tesseract-OCR\\";     char path3[128] = "D:\\Program\\Tesseract-OCR\\txt";     char path4[128] = "-l chi_sim";     sprintf_s(filename,"%s %s %s %s",path1,path2,path3,path4);     delete []filename;

在VS2010下试了下，代码如下：   #include "stdafx.h" #include "stdio.h"   int _tmain(int argc, _TCHAR* argv[]) { 	//char filename[1024];//这个可以 	char* filename = new char[1024]; //这样就会报出编译错误 	char path1[128] = "D:\\Program\\Tesseract-OCR\\tesseract.exe"; 	char path2[128] = "D:\\Program\\Tesseract-OCR\\"; 	char path3[128] = "D:\\Program\\Tesseract-OCR\\txt"; 	char path4[128] = "-l chi_sim"; 	sprintf_s(filename,"%s %s %s %s",path1,path2,path3,path4); 	delete []filename; 	return 0; }  使用 char* filename = new char[1024];  就会报出如下错误：  error C2664: 'int sprintf_s(char *,size_t,const char *,...)' : cannot convert parameter 2 from 'const char [12]' to 'size_t'

2.1)应该是 格式里只包含一个简单格式 ,即 %s,%2d,这种，不包含  %*.*f ， %*d 这种一个格式多个数据的格式。 2.2)应该是 格式里包含若干个格式,或者包含 %*.*f 这种一个格式多个数据的格式。

引用 8 楼 jiaoyun007 的回复:我是在VS2005下 ++  楼上给你答案了。 error：the second paramater can't covert from char[74] to size_t 错误，第二个参数，不能从 74元素的char类型数组,转换成size_t 类型 ---size_t 类型是标准库定义的数据类型，一般实现为无符号长整型unsigned long, 或者无符号整型unsigned int; VC8,VC9 可能是 unsigned long long 或者 unsigned __int64。//为了用于表示 64 Bits 文件长度。   int sprintf_s( char *buffer, size_t sizeOfBuffer,  //这个参数size_t 类型，你传递了一个74元素的char类型数组 const char *format [,//这个[,argument] 表示可选参数，实际函数原型，参数表里没有他                       //只有,... 四个符号 argument] ... );   使用方式 1) format 不包含任何格式 int ret = sprintf_s(     buffer,          //保存结果的字符串缓冲。       sizeOfBuffer,    //最长保留的字符数量，多余的截断。至多比 buffer的容量少一个，要放结束符。     format);         //格式串，可以没有任何格式，没有的话，后面不必有参数了。 sprintf_s(buffer,sizeOfBuffer, format);  2) format包含格式 2.1）格式里只包含一个格式 int ret = sprintf_s(buffer,sizeOfBuffer, format,a); sprintf_s(buffer,sizeOfBuffer, format,a); 2.2）格式里只包含一个格式 int ret = sprintf_s(buffer,sizeOfBuffer, format,a,b,c); sprintf_s(buffer,sizeOfBuffer, format,a,b,c);  你需要的是楼上那种用法，format 就是 "%s" 即： char msg[100]; char src[74]="You are Wellcome"; sprintf_s(msg,min(99,strlen(src)),"%s",src); 这种。

引用 5 楼 xyzinfernity 的回复:  VS2012下测试没问题,楼主出的问题在其他方面吧，error：the second paramater can't covert from char[74] to size_t,说明你的sprintf_s第二个参数是char[74]类型的  我是在VS2005下

引用 6 楼 lm_whales 的回复:函数调用时，有名名参数一个都不能缺少，一个一个对应匹配。 无名参数（。。。），根据需要，匹配，实参不能用省略号。  实际当然不是省略号了

google 个例子看看

下面用法也报同样的错，不知道为何：   void func2(char **pMsg) {     ......     sprintf_s(*pMsg, ...);      ...... }  void func1() {     char msg[100];      func2(&msg); }


Question: 请教：结构体数组的元素可以排序吗？

既然定义了结构体数组 我的想法是这样的 对stu_info这个结构体内的元素 data[i].marks比较大小 然后根据下标来改变整个数组的顺序 其他的就和一般的排序算法没区别了 注意 marks是float型的

使用qsort系统函数即可。 首先定义自己的比较函数，例如： int cmp(void* a ,void *b) {     return (((stu_info* )a)->marks - ((stu_info *)b)->marks); } 然后调用qsort，调用过后数组data中的数组元素已经排好序了。 qsort(data ,MAX ,sizeof(stu_info) ,cmp);  // data:要处理的数组首地址；MAX:要处理的数组元素个数;sizeof(stu_info):数组单个元素大小;cmp:比较函数

你只需要定义规则  不申请额外空间的原地排序就是交换位置而已

利用库函数qsort，对指针排序： int comparefloat(float a,float b) {     if(a == b)return 0;     if(a > b )return 1;     return -1;      }  int cmpByPtr(const void* arg1,const void *arg2) {         return comparefloat( (*( struct stu_info **)arg1)->marks,                     (*( struct stu_info **)arg2)->marks); } // 比较指针 int main(){ struct stu_info *pInfo[MAX]; for(int i=0;i<MAX;i++)pInfo[i] =data +i; ........ qsort(pInfo,MAX,sizeof(struct stu_info *),cmpByPtr); .......    for(i = 0; i < cnt; i++)           printf("%s: %d\n", pInfo[i]->name, pInfo[i]->marks);    rturn 0; } 利用库函数qsort，对数据排序：  ..... int comparefloat(float a,float b) {     if(a == b)return 0;     if(a > b )return 1;     return -1;      }  int cmpByData(const void* arg1,const void *arg2) {         return comparefloat( (( struct stu_info *)arg1)->marks,                     (( struct stu_info *)arg2))->marks ); }  // 比较数据 int main(){  ........ qsort(data,MAX,sizeof(struct stu_info *),cmpByData); .......    for(i = 0; i < cnt; i++)           printf("%s: %d\n", data[i]->name, data[i]->marks);    rturn 0; }   PS： 如果需要自己学排序，仿此。

引用 楼主 mcmay 的回复:请问可以将结构体数组的元素加以排序？例如，我想将学生信息按照期末考试卷面成绩进行排序。先定义以下结构体并声明该结构体的数组，  #include <stdio.h>  #define LEN 21 #define MAX 10  struct stu_info {     char name[LEN];     float marks; };  int main(void) {     struct stu_info data[MAX];     int cnt = 0,i,j;     //假如学生的信息已经都输入好了，接下来应该如何根据学生的分数对数组元素进行从大到小的排序呢？     puts("\nInput students' names (press Enter at the beginning of a line to stop)");     while(cnt < MAX && gets(data[cnt].name) != NULL && data[cnt].name[0] != '\0')    {        printf("Enter students' marks: ");        scanf("%d", &data[i].marks);        cnt++;    }      // 请告知如何排序     // ......     //排序之后打印结果      if(cnt != 0)      {        puts("\nStudents' info in the order of their marks:");        for(i = 0; i < cnt; i++)           printf("%s: %d\n", data[i].name, data[i].marks);      }      else         puts("\nNo data input.");      puts("\nBye!");          return 0;  }  我自己试过用指针，但达不到效果。请问应该如何实现？谢谢！ 当然可以了 参考我写的程序 不懂再问  #include <stdio.h> #include <stdlib.h>  //【样例输入】 //4 //3 22 21 //3 21 22 //3 22 22 //3 21 21 //【样例输出】 //3 21 21 //3 21 22 //3 22 21 //3 22 22 #define MAX_SIZE 1024 struct get_time{     int  Hour;     int  Minute;     int  Second; };  void deal(struct get_time  *elem,int size) {   struct get_time tmp;       int i, j;     for (i = 0; i < size; i++) {     for (j = size - 1; j > i; j--) {          if (elem[j].Hour < elem[j-1].Hour ||elem[j].Minute < elem[j-1].Minute||elem[j].Second < elem[j-1].Second ) {             tmp = elem[j-1];                 elem[j-1] =  elem[j];                 elem[j] = tmp;                         }             }         } }  int main() {     struct get_time answer[MAX_SIZE];     int i;     int num;     scanf("%d",&num);     for(i = 0 ; i < num ; i++)     {      scanf("%d %d %d",&answer[i].Hour,&answer[i].Minute,&answer[i].Second);     }     printf("\n");     deal(answer,num);      for(i = 0 ; i < num ; i++)      printf("%d %d %d\n",answer[i].Hour,answer[i].Minute,answer[i].Second);     return 0; }


Question: C语言如何判断 // 后面的字符串是注释， 而#后面的是命令

请LZ自行学习“有限状态自动机”。

#goto *black001  //跳转到black001这个标签   如果一行中有命令也有注释呢

引用 12 楼 ForestDB 的回复:}  忘了strtok吧  打好基础  不用strtok的话就不好拆分单词了

参考《编译原理》中的词法分析和有限状态自动机。

# include <stdio.h> # include <ctype.h>  void ltrim(char * line) {     char * p = line;     char * start = line;     while (*p != '\0' && isblank(*p))         p++;     while (*p != '\0')     {         *start++ = *p++;     }     *start = '\0'; }  int is_comment_line(char * line) {     if (line[0] == '/' && line[1] == '/')         return 1;     else         return 0; }  int main() {     char line[BUFSIZ] = "  // this is a comment line";     ltrim(line);     if (is_comment_line(line))         printf("it is comment line\n");      return 0; }  忘了strtok吧  打好基础

引用 10 楼 adeng1919 的回复:可以看看编译原理一类的书，词法分析和语法分析 那书我看过，不过说了一大堆奇怪的东西，比如IR还有什么的，我完全看不懂

可以看看编译原理一类的书，词法分析和语法分析

引用 8 楼 ForestDB 的回复:LZ是不是不知道该如何写“移除行首空白”的代码？ LZ是不是不知道该如何写“判断以//开头”的代码？  移除空格我知道用strtok，但是详细判断的代码不会

引用 4 楼 ForestDB 的回复:简单的分析即可：  读一行 移除行首空白 如果行以//开头，则该行是注释 如果行以#开头，则该行是命令  我知道要把空格去掉，而且是否注释和命令我已经在1楼说过了， 我现在求的是写法

逐行扫描，每行以"\n"或者"\\"结尾  以"#"拆分每行，则除了下标为0的元素，其它都是命令。

这个就是 所谓的语法分析器了词法分析器  Yacc 百度学学 中心思想是状态机思想 这个状态机可是个好东西 成为大神的必须课

引用 1 楼 user-7 的回复:你是想自己写编译器还是脚本解释器?  这是普通的字符串处理 遇到第一个字符是"#"就判断是命令 遇到现从个连续的//就认为是注释.  只是一个规则罢了.  所以就是想定这样的规则啊，就是不知道写法

编译器就是知道


Question: 求纠错：恕我眼拙，实在看不出哪里有问题

同意3楼 另外你fp3没关

调试程序，是必须掌握的基本技能！也是最基础的！  总要在接收新东西的时候学会新东西的，

if(sscanf(names_1[i], "%s%f%d",nms_1[i],&mks_1[i],&wds_1[i]) != 3)  //抽取信息  后面俩个是 int型的 这地方传的是地址 你直接把值传进去了

学debug，没你想得那么难。

sscanf(names_1[i], "%s%f%d",nms_1[i],mks_1[i],wds_1[i]); 这句话是错的 你怎么能这么写


Question: 套接字问题，很急

我没分下载资源了，楼主多给我点分吧，晕了

混点分，简单点说， 你accept连接后，没有保存创建的链接。 然后你遍历所有的套接字，一个一个接受数据，套接字，实际是文件编号 0，1，2， 分别是标准输入输出 什么的 。 然后你的套接字一般是3.4.5， 但，可能同时系统有其他socket程序，她们的套接字id为9 ，10 ，11 。 那么，你每次遍历的时候，有可能把其他进程的套接字也拿来recv，就会异常   所以，你要保证你每次遍历的套接字都是你自己accept的，同时是有数据的， 同时， 即便你套接字有数据，你接收的时候，也要判断一下是否接收被中断，如eintr  另外，即便你以上所有问题都解决，还存在你总是没有释放套接字资源的问题，你连续的连几个小时，估计系统会崩掉

引用 3 楼 max_min_ 的回复:[quote=引用 1 楼 u012563253 的回复:] 感觉是这段有问题啊else                     {                         char szText[256];                         int nRecv =recv(fdSocket.fd_array[i], szText, strlen(szText), 0);                         if(nRecv > 0)                        // （2）可读                         {                             printf("接收到数据：%s \n", szText);                         }                         else                                // （3）连接关闭、重启或者中断                         {                             closesocket(fdSocket.fd_array[i]);                             FD_CLR(fdSocket.fd_array[i], &fdSocket);                         }                     }  这里开启新的线程来处理接收消息，让主线程accept动作！  估计都没进这里来！额外开一个线程处理recv看看！[/quote]书上的意思是用select模型，单线程做这个程序额，怎么改，楼上的方法试过了没用

引用 1 楼 u012563253 的回复:感觉是这段有问题啊else                     {                         char szText[256];                         int nRecv =recv(fdSocket.fd_array[i], szText, strlen(szText), 0);                         if(nRecv > 0)                        // （2）可读                         {                             printf("接收到数据：%s \n", szText);                         }                         else                                // （3）连接关闭、重启或者中断                         {                             closesocket(fdSocket.fd_array[i]);                             FD_CLR(fdSocket.fd_array[i], &fdSocket);                         }                     }  这里开启新的线程来处理接收消息，让主线程accept动作！  估计都没进这里来！额外开一个线程处理recv看看！

是不是客户端少了一个   WSACleanup();       //释放套接字资源

引用 6 楼 zhao4zhong1 的回复:请检查所有函数的返回值！  不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://topic.csdn.net/u/20120210/09/51109ed0-07b9-41f2-b487-a51597f2ca01.html 请问是客户端程序的问题吗？

引用 6 楼 zhao4zhong1 的回复:请检查所有函数的返回值！  不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://topic.csdn.net/u/20120210/09/51109ed0-07b9-41f2-b487-a51597f2ca01.html 不好意思阿，我是初学套接字编程，实在不懂，不知道能不能稍微具体点

引用 4 楼 u012563253 的回复:[quote=引用 3 楼 max_min_ 的回复:] [quote=引用 1 楼 u012563253 的回复:] 感觉是这段有问题啊else                     {                         char szText[256];                         int nRecv =recv(fdSocket.fd_array[i], szText, strlen(szText), 0);                         if(nRecv > 0)                        // （2）可读                         {                             printf("接收到数据：%s \n", szText);                         }                         else                                // （3）连接关闭、重启或者中断                         {                             closesocket(fdSocket.fd_array[i]);                             FD_CLR(fdSocket.fd_array[i], &fdSocket);                         }                     }  这里开启新的线程来处理接收消息，让主线程accept动作！  估计都没进这里来！额外开一个线程处理recv看看！[/quote]书上的意思是用select模型，单线程做这个程序额，怎么改，楼上的方法试过了没用[/quote]  看你的写逻辑，如果在循环体内如果一直有准备好的监听的队列的话，accept就会一直去取套接字来 进行accept这个动作的！不会进行下面的接受数据的这个动作，所以我怀疑这里出了问题的！ 而且这两个动作根本没有if else的关系在里面，不明白你的需求为什么要这样写，  建议;在accept函数调用成功后，直接处理接收消息，直接recv 然后打印看看！      或者再accept成功调用后，开启新的线程处理接受消息，


Question: main 函数入参 特殊符号问题

只有C，C++原生字符串，需要双引号，即只有代码里，明确写的字符串字面值，需要双引号。  命令行参数格式，由操作系统和编译器（编译器的库代码中的启动代码）确定。 并不是，一定会，当作字符串字面值处理。

虽然 '\'' 是不可以的，但是"\""是可以的，这就行了，需要什么字符都可以表示出来

引用 1 楼 max_min_ 的回复: ./test  "dd\'dd"   用双引号引起来的单引号是不需要转义的，"dd\'dd"打印出来的是dd\'dd，那我还是用双引号引吧

C:\Users\lfyang>echo 'abc'def' 'abc'def'  C:\Users\lfyang>

'abc'efg'  命令行不识别转义吧，   直接按空格分隔，  穿字符串表面值。

"dd\'dd"这样不对吗

./test  "dd\'dd"

这主要看命令解释程序（如MS的command.exe,linux下的各种shell）的处理

google 转义字符


Question: memset函数疑惑

“memset函数是以字节为单位进行赋值的操作的”楼上说的对，所以他理论上是应该跟任何对象进行初始化的。但是对于一些包含STL变量，指针等数据成员的对象不该这么干

引用 5 楼 u010286751 的回复:#include<stdio.h> #include <string.h> int main() {  int a[10],i;  memset(a,1,sizeof(a));  for(i=0;i<10;i++)    printf("%d ",a[i]);    return 0; }  初始为1不行了？？？输不出来 memset函数是以字节为单位进行赋值的操作的 看看你的数组类型 数组中所有元素都是 0x01010101h

引用 2 楼 max_min_ 的回复:memset函数是以字节为单位进行赋值的操作的 看看你的数组类型 ++ 初始为零,符合常理呀...

不超过0xFF都可以

memset函数是以字节为单位进行赋值的操作的 看看你的数组类型

其实是可以的..但一个数组你要置为其他数,是不是得用个for循环呢?或者用memcpy也行..其实你不置为0也无所谓,撑死了也就留下点堆栈信息,除非特别是牛x的黑客..要不然那丁点堆栈信息真没啥用


Question: 括号匹配，无法实现

谢谢各位大神

我只懂c语言，

楼主，把分给了三楼结贴吧，没必要看太多，人家的就很好了

楼主，首先，你的数组边界弄错了，int c[10];那么数组的最多到c[9],没有c[10],你的循环里就到了c[10].其次：这个问题用栈的数据结构来做是最好的，因为《数据结构》教材上就有这个例子。   希望能够纠正你的方向。

其实grammar的可以简单一点   template<typename Iterator> struct recursiveBraces : qi::grammar<Iterator, qi::ascii::space_type> {     recursiveBraces() : recursiveBraces::base_type(finalRules)     {         braces = "(" >> *expression >> ")";         expression = +braces;         finalRules = +expression;     }      qi::rule<Iterator, qi::ascii::space_type> braces;     qi::rule<Iterator, qi::ascii::space_type> expression;     qi::rule<Iterator, qi::ascii::space_type> finalRules; };   Iterator == iterator的type qi::ascii::space_type == 忽略 " "  braces = "(" >> *expression >> ")"; 以EBNF来表达就是 "\(expression*\)"  expression = +braces; 以EBNF来表达就是 braces+  所以上述rules的意思是 braces = 第一个必须是 "(",中间可以有0～多个expression,最后必须是")" expression = 一个或多个braces  而braces会呼叫expression,expression会呼叫braces 所以这就形成了recursive

引用 10 楼 ForestDB 的回复:#include<stdio.h> int main() { int i,j,m; char a[10],b[10],c[10]; for(i=0;i<11;i++) scanf("%c",c[i]); // c只能存10个char，但是i却是从0到10（有效的是到9为止） // 运行完for之后，i的值为11， if(c[i]='(') // 这里i的值为11，直接拿来用了？ a[j]=c[i]; // j的初值是多少？ if(c[i]=')') b[m]=c[i]; // m又是多少？ else printf("输入出错\n"); printf("%d\n",j); printf("%d\n",m);  if(j=m) printf("(等于)\n"); printf("%d\n",j); printf("%d\n",m);  return 0; }   打好基础。  恩 是的。

仅供参考#include<stdio.h> #include<malloc.h> #include<string.h> #define STACK_INIT_SIZE 10 #define STACK_GROW_SIZE 5 #define ELEMTYPE char #define OK 1 #define ERROR 0 typedef struct { /*建立一个栈的首结点*/     ELEMTYPE * base;     ELEMTYPE * top;     int stacksize; } SpStack; int InitStack(SpStack *s) { /*建立空的栈并返回首地址*/     s->base=((ELEMTYPE*)malloc(STACK_INIT_SIZE*sizeof(ELEMTYPE)));     if (!s->base) return ERROR;     s->top=s->base;     s->stacksize=STACK_INIT_SIZE;     return OK; } int StackEmpty(SpStack *s) { /*判断栈是否为空*/     if (s->top==s->base) return OK;     else                 return ERROR; } int Push(SpStack *s,ELEMTYPE e) { /*往栈顶插入元素即进栈*/     if (s->top-s->base>=s->stacksize) { /*判断是否栈满*/         s->base=((ELEMTYPE*)realloc(s->base,(s->stacksize+STACK_GROW_SIZE)*sizeof(ELEMTYPE)));         if (!s->base) return ERROR;         s->stacksize+=STACK_GROW_SIZE;         s->top=s->base+s->stacksize;     }     *s->top++=e;     return OK; } int Pop(SpStack *s,ELEMTYPE *e) { /*让栈顶元素依次输出即出栈*/     if (StackEmpty(s)) return ERROR;     *e=*(--s->top);     return OK; } int Comp(ELEMTYPE a,ELEMTYPE b) {     if ((a=='('&&b!=')')       ||(a=='['&&b!=']')       ||(a=='{'&&b!='}')) {         return ERROR;     } else return OK; } int Count(SpStack *s) {     ELEMTYPE e[STACK_INIT_SIZE*2];     ELEMTYPE e1;     int i;      InitStack(s);     fgets(e,STACK_INIT_SIZE*2,stdin);     if ('\n'==e[strlen(e)-1]) e[strlen(e)-1]=0;     printf("%s\n",e);     for (i=0;e[i]!='\0';i++) {         switch (e[i]) {         case '(':         case '[':         case '{':             Push(s,e[i]);             break;         case ')':         case ']':         case '}':             if (StackEmpty(s)) {                 printf("%*s↖右括号多余\n",i+1,"");                 return(ERROR);             } else Pop(s,&e1);             if (!Comp(e1,e[i])) {                 printf("%*s↖左右匹配出错\n",i+1,"");                 return(ERROR);             }         }     }     if (!StackEmpty(s)) {         printf("%*s↖左括号多余\n",i,"");         return(ERROR);     } else {         printf("匹配正确\n");         return(OK);     } } void main() {     SpStack s;     Count(&s);     free(s.base); }

#include <iostream> #include <string>  #include <boost/spirit/include/qi.hpp>  namespace qi = boost::spirit::qi;  template<typename Iterator> struct recursiveBraces : qi::grammar<Iterator, std::string(), qi::ascii::space_type> {     recursiveBraces() : recursiveBraces::base_type(expression)     {         braces = qi::lit("(") >> *expression >> ")";         expression = +braces;         finalRules = +expression;     }      qi::rule<Iterator, std::string(), qi::ascii::space_type> braces;     qi::rule<Iterator, std::string(), qi::ascii::space_type> expression;     qi::rule<Iterator, std::string(), qi::ascii::space_type> finalRules; };  void parse_recursive_braces() {     std::string const braces[] =     {         {"( () )"}, {"("}, {"(() ())"}, {"(  ( ( ( () ) ) ) )"},         {"(((( ( ))))"}, {"(() ()) ((())) (())"}, {"(() ()) ((( ( ))) (())"}     };     recursiveBraces<std::string::const_iterator> grammar;      for(auto const &data : braces){          auto begin = std::begin(data), end = std::end(data);         bool r = qi::phrase_parse(begin, end, grammar, qi::ascii::space);          if(r && begin == end){             std::cout<<"match"<<std::endl;         }else{             std::cout<<"wrong"<<std::endl;         }     } }  int main() {     parse_recursive_braces(); }   稍微扩充一下就可以做更复杂的匹配

#include <iostream> #include <string>  #include <boost/spirit/include/qi.hpp>  namespace qi = boost::spirit::qi;  template<typename Iterator> struct recursiveBraces : qi::grammar<Iterator, std::string(), qi::ascii::space_type> {     recursiveBraces() : recursiveBraces::base_type(expression)     {         braces = qi::lit("(") >> *expression >> ")";         expression = +braces;     }      qi::rule<Iterator, std::string(), qi::ascii::space_type> braces;     qi::rule<Iterator, std::string(), qi::ascii::space_type> expression; };  inline void parse_recursive_braces() {     std::string const braces[] =     {         {"( () )"}, {"("}, {"(() ())"}, {"(  ( ( ( () ) ) ) )"}     };     recursiveBraces<std::string::const_iterator> grammar;      for(auto const &data : braces){          auto begin = std::begin(data), end = std::end(data);         bool r = qi::phrase_parse(begin, end, grammar, qi::ascii::space);          if(r && begin == end){             std::cout<<"match"<<std::endl;         }else{             std::cout<<"wrong"<<std::endl;         }     } }  int main() {    parse_recursive_braces(); }  重点其实就是recursive,问问你自己该如何把EBNF的语法转换成程式？

引用 4 楼 u010286751 的回复:[quote=引用 2 楼 xb1198023575 的回复:] 这代码....呵呵.... 确实有点乱，我改了一下看看合不合你的意思 代码：#include<stdio.h> int main() {  int i,j=0,m=0,k;  char a[10],b[10],c[10];   for(i=0;i<10;i++)     scanf("%c",&c[i]);  for(k=0;k<10;k++){    if(c[k]=='(')     {            a[j]=c[k];            ++j;      }    if(c[k]==')')    {     b[m]=c[k];     ++m;    }     if(c[k]!='(' && c[k]!=')')         printf("error\n"); }   printf("%d\n",j);   printf("%d\n",m);     if(j==m)      printf("(等于)\n");   printf("%d\n",j);   printf("%d\n",m);    return 0; }[/quote]  你不用另外弄两个数组保存'(',')',没用，弄个整形保存计数就得了，用保存输入那个数组也没啥用，直接用getchar读单个字母就行啊，还不用限制输入的个数，然后判断是不是括号，是左括号还是右括号....，另外三楼那个不是挺好的答案吗，

引用 2 楼 xb1198023575 的回复:这代码....呵呵.... 确实有点乱，我改了一下看看合不合你的意思 代码：#include<stdio.h> int main() {  int i,j=0,m=0,k;  char a[10],b[10],c[10];   for(i=0;i<10;i++)     scanf("%c",&c[i]);  for(k=0;k<10;k++){    if(c[k]=='(')     {            a[j]=c[k];            ++j;      }    if(c[k]==')')    {     b[m]=c[k];     ++m;    }     if(c[k]!='(' && c[k]!=')')         printf("error\n"); }   printf("%d\n",j);   printf("%d\n",m);     if(j==m)      printf("(等于)\n");   printf("%d\n",j);   printf("%d\n",m);    return 0; }

可以用到栈来处理，给个C++的实现： #include <iostream> #define MAXSIZE 50 using namespace std; typedef char ElemType;  struct SqStack { 	ElemType Data[MAXSIZE]; 	int top; };  //初始化栈 void InitStack(SqStack* &stack) { 	stack = new SqStack; 	stack->top = -1; }  //销毁栈 void DestroyStack(SqStack* &stack) { 	delete stack; }  //判断栈是否为空 bool Empty(SqStack* stack) { 	return stack->top == -1; }  //入栈 bool Push(SqStack* &stack, ElemType e) { 	if (stack->top == MAXSIZE - 1) 		return false;  	stack->top++; 	stack->Data[stack->top] = e; 	return true; }  //出栈 bool Pop(SqStack* &stack, ElemType &e) { 	if (stack->top == -1) 		return false;  	e = stack->Data[stack->top]; 	stack->top--; 	return true; }  //取栈顶元素 bool GetTop(SqStack* stack, ElemType &e) { 	if (stack->top == -1) 		return false;  	e = stack->Data[stack->top]; 	return true; }   //判断表达式中的小括号（）是对匹配 bool Match(char * Expresion) { 	SqStack* Stack = NULL;	//初始化栈 	InitStack(Stack);  	int Length = strlen(Expresion);  	int i = 0; 	while (Expresion[i] != '\0') 	{ 		ElemType Elem; 		if (Expresion[i] == '(')		//如果是左括号，则将其入栈 		{ 			Push(Stack, '('); 		} 		else if (Expresion[i] == ')')	//如果是右括号，则从栈中弹出一个左括号 		{ 			if (Stack->top == -1) 				return false; 			Pop(Stack, Elem); 		} 		i++; 	}  	if (Empty(Stack))		//栈空则匹配 		return true; 	else 		return false; }  int main() { 	char Expresion[] = "()(()()())"; 	if (Match(Expresion)) 	{ 		cout << "匹配！" << endl; 	} 	else 	{ 		cout << "不匹配！" << endl; 	}  	system("pause"); 	return 0; }   重点看下 Match()这个函数。

这代码....呵呵....

首先不知道code想实现什么意图 第二j和m都没有初始化，跑飞是大概率事件


Question: 大型程序中函数名或类型名冲突的问题！

引用 8 楼 zhao4zhong1 的回复:[quote=引用 3 楼 u011779875 的回复:] 还有你去大公司 都有严格编码风格的手册 你进公司第一件事是学一星期编码风格  你还怕这个 除非你去小公司  就你一个程序员 你想咋写就咋写 你就是神 就是上帝 哦？原来我就是神 就是上帝！以前咋没觉味呢？[/quote] 我也是上帝 我们公司也就我一个人 哈哈 真是奇闻  当上帝当久了 突然有一天 掉下去当普通人 还是会很痛苦的一件事 但是普通人变成上帝 确实很快乐的一件事 当一个人不知道上帝和普通人之分的时候  那么 同等概率

引用 3 楼 u011779875 的回复:还有你去大公司 都有严格编码风格的手册 你进公司第一件事是学一星期编码风格  你还怕这个 除非你去小公司  就你一个程序员 你想咋写就咋写 你就是神 就是上帝 哦？原来我就是神 就是上帝！以前咋没觉味呢？

引用 楼主 skyliuxu 的回复:请教一下列位，一个大型程序中如何避免函数名或类型名冲突呢？ 所有extern的或者global的都加上前缀，像abc123_DoJob,abc123_GoTo之类的

1.使用命名空间 2.少用using namespace,尽量用全名.

一般用 ModuleName + FunctionName的形式

选择一种自己习惯的命名规则@

引用 1 楼 u011779875 的回复:很简单啊  规定一个规则就好了 比如 我类型名  必须这样定义 int i_elem; int 型加一个_ char c_elem; 我函数名定义的时候不我不用_这样 你肯定就不可能冲突了  还有就是C++中有命名空间 这个东西  可以减少吧 反正我也没用过 C也存在命名空间的感念吧  命名规则


Question: 求各路大牛帮我看看为什么会出现debug error

引用 14 楼 wuxiaodi250 的回复:[quote=引用 13 楼 u011779875 的回复:] [quote=引用 12 楼 wuxiaodi250 的回复:] [quote=引用 9 楼 wangdahu888 的回复:] [quote=引用 3 楼 wuxiaodi250 的回复:] [quote=引用 2 楼 wangdahu888 的回复:] FILE* fp1=fopen("ecb2.txt","rb");  FILE* fp2=fopen("key.txt","rb"); 上述两个文件是否存在 都存在呢！它出现的错误是这样的 [/quote] vs2010不会报这错误[/quote] ……那是怎么回事啊？VS2010编译是正确的？[/quote]  你注释掉 int main()  {        Cecb();     // Decb();         return 0;  } int main()  {       // Cecb();     // Decb();         return 0;  } 你在测试下能通过吗 如果依然出现刚才的错误  拷贝代码  重新建立个工程 重新编译[/quote] 我都进行过调试了……也重新建立了工程……还是有错……[/quote] 我的意思是说 你注释掉 int main()  {       // Cecb();     // Decb();         return 0;  }  之后你运行了吗 还是报错吗 如果这种事情发生 说明扔掉你那个破VC 如果不报错 那么继续注释掉 int main()  {       Cecb();     // Decb();         return 0;  } 如果不报错 仔细看Decb 既然调试不好使 那就只能手动了 如果在不好使 就应该是你那些打开的文件哪地方有问题 继续检查  如果还是不行 爱莫能助 了真是  天亡你啊

引用 13 楼 u011779875 的回复:[quote=引用 12 楼 wuxiaodi250 的回复:] [quote=引用 9 楼 wangdahu888 的回复:] [quote=引用 3 楼 wuxiaodi250 的回复:] [quote=引用 2 楼 wangdahu888 的回复:] FILE* fp1=fopen("ecb2.txt","rb");  FILE* fp2=fopen("key.txt","rb"); 上述两个文件是否存在 都存在呢！它出现的错误是这样的 [/quote] vs2010不会报这错误[/quote] ……那是怎么回事啊？VS2010编译是正确的？[/quote]  你注释掉 int main()  {        Cecb();     // Decb();         return 0;  } int main()  {       // Cecb();     // Decb();         return 0;  } 你在测试下能通过吗 如果依然出现刚才的错误  拷贝代码  重新建立个工程 重新编译[/quote] 我都进行过调试了……也重新建立了工程……还是有错……

引用 12 楼 wuxiaodi250 的回复:[quote=引用 9 楼 wangdahu888 的回复:] [quote=引用 3 楼 wuxiaodi250 的回复:] [quote=引用 2 楼 wangdahu888 的回复:] FILE* fp1=fopen("ecb2.txt","rb");  FILE* fp2=fopen("key.txt","rb"); 上述两个文件是否存在 都存在呢！它出现的错误是这样的 [/quote] vs2010不会报这错误[/quote] ……那是怎么回事啊？VS2010编译是正确的？[/quote]  你注释掉 int main()  {        Cecb();     // Decb();         return 0;  } int main()  {       // Cecb();     // Decb();         return 0;  } 你在测试下能通过吗 如果依然出现刚才的错误  拷贝代码  重新建立个工程 重新编译

引用 9 楼 wangdahu888 的回复:[quote=引用 3 楼 wuxiaodi250 的回复:] [quote=引用 2 楼 wangdahu888 的回复:] FILE* fp1=fopen("ecb2.txt","rb");  FILE* fp2=fopen("key.txt","rb"); 上述两个文件是否存在 都存在呢！它出现的错误是这样的 [/quote] vs2010不会报这错误[/quote] ……那是怎么回事啊？VS2010编译是正确的？

问题说明：  主模块在调用Dll的导出函数时会保存返回地址在堆栈中（ESP+xxx）。函数调用返回时，会弹栈取得返回地址（ESP-xxx），从而返回到主模块。   vaule of ESP was not properly saved across a function call.   上面出现的错误是系统提示主模块调用前堆栈的指针（ESP），与调用导出函数后的指针不符。   一般有两种情况会出现类似错误。  1. Dll导出函数声明导出方法，与主模块中声明的导入方法不一致。使得调用时参数的传递中，破坏了调用堆栈，出现错误。   2. Dll导出函数本身破坏了调用堆栈。编码中最一般的错误比如：对象（如CString）等。   解决方法：  针对第1种情况，请确定导出方（Dll等）与导入方（Exe等）的声明保持一致。  对于第2种情况，请保证产生的对象都被安全的释放。   备注：  可以试试下面的方法可以简单的测试方法  将Dll的导出函数定义成空处理（直接返回），如还出现错误，则是调用错误。

引用 8 楼 u011779875 的回复:[quote=引用 7 楼 wuxiaodi250 的回复:] [quote=引用 6 楼 u011779875 的回复:] [quote=引用 4 楼 wuxiaodi250 的回复:] 各位大神们都来帮看啊！！！本菜鸟感激不尽啊！！！ 你用的什么编译器 怎么还用这种写法 for(int i = 0 ; i < 9; i++) 这是什么标准了啊 你不是用的C++编译器写的C吧  第二 这种情况最简单的方式 是先注释掉 第二个函数 看是否报错 排除 第二个 调试第一个  在检查是否是环境所造成的  你这个不像是逻辑错误 应该是环境有问题  仅供参考[/quote]  我用的是VC6.0…… 我已经调试过了，过程中没有错误，到最后一步就会跳出刚刚的那个框……[/quote] 不要用VC6.0来写C语言 VC6.0就是个bug  那个东西我看着就头疼 什么VC 垃圾 你要是写C 你就用别的 不要用C++来试图写C  除非你C已经很厉害了 且懂得俩个编译器的区别  我用别的gcc 编译器 没出错  我不知道你文件里面都是什么 你完成的是什么  你仔细看看 有警告之类吗 编译的时候[/quote] 编译的时候没有警告……学生一小枚，学校课程里编程都用那个……

引用 3 楼 wuxiaodi250 的回复:[quote=引用 2 楼 wangdahu888 的回复:] FILE* fp1=fopen("ecb2.txt","rb");  FILE* fp2=fopen("key.txt","rb"); 上述两个文件是否存在 都存在呢！它出现的错误是这样的 [/quote] vs2010不会报这错误

引用 7 楼 wuxiaodi250 的回复:[quote=引用 6 楼 u011779875 的回复:] [quote=引用 4 楼 wuxiaodi250 的回复:] 各位大神们都来帮看啊！！！本菜鸟感激不尽啊！！！ 你用的什么编译器 怎么还用这种写法 for(int i = 0 ; i < 9; i++) 这是什么标准了啊 你不是用的C++编译器写的C吧  第二 这种情况最简单的方式 是先注释掉 第二个函数 看是否报错 排除 第二个 调试第一个  在检查是否是环境所造成的  你这个不像是逻辑错误 应该是环境有问题  仅供参考[/quote]  我用的是VC6.0…… 我已经调试过了，过程中没有错误，到最后一步就会跳出刚刚的那个框……[/quote] 不要用VC6.0来写C语言 VC6.0就是个bug  那个东西我看着就头疼 什么VC 垃圾 你要是写C 你就用别的 不要用C++来试图写C  除非你C已经很厉害了 且懂得俩个编译器的区别  我用别的gcc 编译器 没出错  我不知道你文件里面都是什么 你完成的是什么  你仔细看看 有警告之类吗 编译的时候

引用 6 楼 u011779875 的回复:[quote=引用 4 楼 wuxiaodi250 的回复:] 各位大神们都来帮看啊！！！本菜鸟感激不尽啊！！！ 你用的什么编译器 怎么还用这种写法 for(int i = 0 ; i < 9; i++) 这是什么标准了啊 你不是用的C++编译器写的C吧  第二 这种情况最简单的方式 是先注释掉 第二个函数 看是否报错 排除 第二个 调试第一个  在检查是否是环境所造成的  你这个不像是逻辑错误 应该是环境有问题  仅供参考[/quote]  我用的是VC6.0…… 我已经调试过了，过程中没有错误，到最后一步就会跳出刚刚的那个框……

引用 4 楼 wuxiaodi250 的回复:各位大神们都来帮看啊！！！本菜鸟感激不尽啊！！！ 你用的什么编译器 怎么还用这种写法 for(int i = 0 ; i < 9; i++) 这是什么标准了啊 你不是用的C++编译器写的C吧  第二 这种情况最简单的方式 是先注释掉 第二个函数 看是否报错 排除 第二个 调试第一个  在检查是否是环境所造成的  你这个不像是逻辑错误 应该是环境有问题  仅供参考

代码没看懂，期待解决方案，学习下

各位大神们都来帮看啊！！！本菜鸟感激不尽啊！！！

引用 2 楼 wangdahu888 的回复:FILE* fp1=fopen("ecb2.txt","rb");  FILE* fp2=fopen("key.txt","rb"); 上述两个文件是否存在 都存在呢！它出现的错误是这样的

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

出错原因是在函数Cecb和Decb的以下2行定义的数组不够长: char keychar[8]; 在执行fscanf(fp2,"%s",keychar)时越界了(读入8个字符并在keychar[8]置字符串结尾0),破坏了栈. 改为: char keychar[8+1]; 可解决问题.

排个版先。。。  #include <stdio.h> #include <string.h> #include <stdlib.h>  int key[16][48]; char str[10000]; int str1[10000]; int len,num;  int IP1[64]={ 58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6, 64,56,48,40,32,24,16,8, 57,49,41,33,25,17, 9,1, 59,51,43,35,27,19,11,3, 61,53,45,37,29,21,13,5, 63,55,47,39,31,23,15,7};  int IP2[64]={ 40,8,48,16,56,24,64,32, 39,7,47,15,55,23,63,31, 38,6,46,14,54,22,62,30, 37,5,45,13,53,21,61,29, 36,4,44,12,52,20,60,28, 35,3,43,11,51,19,59,27, 34,2,42,10,50,18,58,26, 33,1,41,9,49,17,57,25};  //生成k函数 int PC1[56]={ 57,49,41,33,25,17, 9,1, 58,50,42,34,26,18,10,2, 59,51,43,35,27,19,11,3, 60,52,44,36,63,55,47,39, 31,33,15, 7,62,54,46,38, 30,22,14, 6,61,53,45,37, 29,21,13, 5,28,20,12,4 };  int PC2[48]={ 14,17,11,24, 1, 5, 3,28, 15, 6,21,10,23,19,12,4, 26, 8,16, 7,27,20,13,2, 41,52,31,37,47,55,30,40, 51,45,33,48,44,49,39,56,  34,53,46,42,50,36,29,32};  void K(int *keychar){     int movebit[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};     int midkey[64];     int midkey2[56];     int i,j,n;     int o=0;      n=0;     for(i=0;i<8;i++)         for(j=0;j<8;j++){             o=keychar[i];             midkey[n++]=(o>>(7-j))&1;         }      for(i=0;i<56;i++)         midkey2[i]=midkey[PC1[i]-1];      for(i=0;i<16;i++){         int t[4];         t[0]=midkey2[0];         t[1]=midkey2[1];         t[2]=midkey2[28];         t[3]=midkey2[29];         if(movebit[i]==1){//循环左移             for(i=0;i<27;i++){                 midkey2[i]=midkey2[i+1];                 midkey2[i+28]=midkey2[i+29];             }             midkey2[27]=t[0];             midkey2[55]=t[2];         }         else{             for(i=0;i<26;i++){                 midkey2[i]=midkey2[i+2];                 midkey2[i+28]=midkey2[i+30];             }             midkey2[26]=t[0];             midkey2[27]=t[1];             midkey2[54]=t[2];             midkey2[55]=t[3];         }         for(i=0;i<48;i++)             key[n][i]=midkey2[PC2[i]-1];      } }  //生成F函数 int Ex[48]={ 32,1,2,3,4,5,4,5,6,7,8,9, 8,9,10,11,12,13,12,13,14,15,16,17, 16,17,18,19,20,21,20,21,22,23,24,25, 24,25,26,27,28,29,28,29,30,31,32,1};  int P[32]={ 16,7,20,21,29,12,28,17, 1,15,23,26,5,18,31,10, 2,8,24,14,32,27,3,9, 19,13,30,6,22,11,4,25};  int S[8][4][16]={     {         {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},         {0,15,7,54,14,2,13,1,10,6,12,11,9,5,3,8},         {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},         {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}     },     {         {15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},         {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},         {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},         {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}     },     {         {10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},         {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},         {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},         {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}     },     {         {7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},         {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},         {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},         {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}     },     {         {2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},         {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},         {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},         {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}     },     {         {12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},         {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},         {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},         {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}     },     {         {4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},         {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},         {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},         {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}     },     {         {13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},         {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},         {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},         {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}     } };  void f(int *rp,int n,int S){     int t[4],i;     for(i=0;i<4;i++){         t[i]=S%2;         S=S/2;     }     for(i=0;i<4;i++)         rp[4*n+i]=t[3-i]; }  void F(int *r,int *key){     int rp[48]={0};     int i;     for(i=0;i<48;i++)         rp[i]=r[Ex[i]-1];      for(i=0;i<48;i++)         rp[i]=rp[i]^key[i];      int n,x,y;     x=y=0;     for(i=0;i<48;i+=6){         n=i/6;         x=(rp[i]<<1)+rp[i+5];         y=(rp[i+1]<<3)+(rp[i+2]<<2)+(rp[i+3]<<1)+rp[i+4];         f(rp,n,S[n][x][y]);     }      int t[32];     for(i=0;i<32;i++)         t[i]=r[i];     for(i=0;i<32;i++)         r[i]=t[P[i]-1]; }  void Encode(int *str,int *keychar){     int l[32],r[32],t[32];     int i,j,n;     K(keychar);      int data[64];     n=0;     int o=0;     for(i=0;i<8;i++)         for(j=0;j<8;j++){             o=str[i];             data[n++]=(o>>(7-j))&1;           }      for(i=0;i<32;i++){         l[i]=data[IP1[i]-1];          r[i]=data[IP1[i+32]-1];     }     for(i=0;i<16;i++){         for(j=0;j<32;j++)             t[j]=r[j];         F(r,key[i]);         for(j=0;j<32;j++){             r[j]=r[j]^l[j];             l[j]=t[j];         }     }      int a,b;     a=b=0;     for(i=0;i<32;i++){         data[i]=r[i];         data[i+32]=l[i];     }      for(i=0;i<32;i++){ //逆初始值换         l[i]=data[IP2[i]-1];         r[i]=data[IP2[i+32]-1];     }      for(i=0;i<32;i++){         a=(l[i]&0x1)+(a<<1);         b=(r[i]&0x1)+(b<<1);          if((i+1)%8==0){             str[i/8]=a;             a=0;             str[i/8+4]=b;             b=0;         }     } }  void Decode(int *str,int *keychar){     int l[32],r[32],t[32];     int i,j,n;     K(keychar);      int data[64];     n=0;      int o=0;     for(i=0;i<8;i++)         for(j=0;j<8;j++){             o=str[i];             data[n++]=(o>>(7-j))&1;           }      for(i=0;i<32;i++){         l[i]=data[IP1[i]-1];              r[i]=data[IP1[i+32]-1];      }      for(i=0;i<16;i++){         for(j=0;j<32;j++)             t[j]=r[j];         F(r,key[15-i]);         for(j=0;j<32;j++){             r[j]=r[j]^l[j];             l[j]=t[j];         }     }      int a,b;     a=b=0;     for(i=0;i<32;i++){         data[i]=r[i];         data[i+32]=l[i];     }      for(i=0;i<32;i++){//逆初始值换         l[i]=data[IP2[i]-1];             r[i]=data[IP2[i+32]-1];     }      for(i=0;i<32;i++){         a=(l[i]&0x1)+(a<<1);         b=(r[i]&0x1)+(b<<1);         if((i+1)%8==0){             str[i/8]=a;             a=0;             str[i/8+4]=b;             b=0;         }     } }  void Cecb(){     char keychar[8];     int key2[8];     int in[8];            int len;      FILE* fp1=fopen("ecb1.txt","rb");      fseek(fp1, 0, SEEK_END);     len=ftell(fp1);       fseek(fp1, 0,SEEK_SET);      for(int c=0;c<len;c++){         fscanf(fp1,"%c",&str[c]);         str1[c]=str[c];     }     fclose(fp1);      FILE* fp2=fopen("key.txt","rb");     fscanf(fp2,"%s",keychar);     fclose(fp2);      for(int d=0;d<8;d++)         key2[d]=keychar[d];      int m=len/8+1;     printf("请选择填充方式：1:PKCS 7\t2:ISO 9797M2\t3:ANSI X9.23\n");     scanf("%d",&num);     if(num==1){         for(int o=0;o<8-len%8;o++){             str1[len+o]=8-len%8;         }     }     if(num==2){         for(int p=0;p<8-len%8;p++){             str1[len+p]=80;         }     }     if(num==3){         for(int q=0;q<8-len%8;q++){             str1[len+q]=0x00;             if(q==8-len%8-1)                 str1[len+q]=8-len%8;         }     }      FILE* fp3=fopen("ecb2.txt","w");     for(int z=0;z<m;z++){         for(int g=0;g<8;g++){             in[g]=str1[z*8+g];         }         Encode(in,key2);         for(int h=0;h<8;h++){             str1[z*8+h]=in[h];             fprintf(fp3,"%c",in[h]);         }     }     fclose(fp3); }  void Decb(){     char keychar[8];     int key2[8];     int in[8];            int len;      FILE* fp1=fopen("ecb2.txt","rb");      fseek(fp1, 0, SEEK_END);     len=ftell(fp1);       fseek(fp1, 0,SEEK_SET);     fclose(fp1);      FILE* fp2=fopen("key.txt","rb");     fscanf(fp2,"%s",keychar);     fclose(fp2);      for(int d=0;d<8;d++)         key2[d]=keychar[d];      int m=len/8;      FILE* fp3=fopen("ecb3.txt","w");     int x;     for(int z=0;z<m;z++){         for(int g=0;g<8;g++){             in[g]=str1[z*8+g];         }         Decode(in,key2);         if(z==m-1){             if(num==1){                 for(x=0;x<8-in[7];x++)                     fprintf(fp3,"%c",in[x]);             }             if(num==2){                 for(x=0;in[x]!=80&&x<8;x++)                     fprintf(fp3,"%c",in[x]);             }             if(num==3){                 for(x=0;x<8-in[7];x++)                     fprintf(fp3,"%c",in[x]);             }         }         else{             for(x=0;x<8;x++)                 fprintf(fp3,"%c",in[x]);         }     }     fclose(fp3); }  int main() {     Cecb();     Decb();      return 0; }


Question: 关于unsiged int和int相加的一个面试提

引用 4 楼 qq283802332 的回复:假设是32位数据  a的32位模式是00000000 00000000 00000000 00000110 (6) b的32位模式是11111111 11111111 11111111 11110110 (-20)  a + b 后的位模式是11111111 11111111 11111111 11111100  printf("a + b =%d\n",a + b);  因为printf()中格式要求是%d, 即要用十进制有符号， 所以很明显这里的a+b的位模式就将被解释成有符号数 即-14   a + b > 6 ? puts("1"):puts("2"); 因为a是一个无符号， 而b是有符号, 所以a+b将被强制转换成无符号 所以这里a+b的位模式将被解释成无符号数， 所以这里a+b将是一个很大的数， 所以输出1  个人见解， 请指教谢谢,算是懂了,大半夜起来发这个问题,还真怕得不到及时回答,大伙早点休息吧

引用 3 楼 A328240784 的回复:[quote=引用 1 楼 max_min_ 的回复:] 无符号的  printf("%u")那a和b相加的时候b是否向unsigned转型了呢?[/quote]  这样说更准确：  当表达式中存在有符号类型和无符号类型时，默认情况下计算的结果将转化为无符号类型

引用 1 楼 max_min_ 的回复:无符号的  printf("%u")那a和b相加的时候b是否向unsigned转型了呢?

按%d输出是负的

无符号的  printf("%u")


Question: memcpy 的不解

正解++， ps：是我那个博客的代码？ 引用 5 楼 zhao4zhong1 的回复:因为+后面表达式计算的数是以多少个char为单位；而不是以多少个int或多少个double为单位。

引用 楼主 daxiaoyuyu 的回复:我看了一篇博文： C语言实现 vector( 动态数组) 改进版  地址：http://blog.csdn.net/dengxu11/article/details/7311820  有一点不明白，在下面代码中 int cvector_pushback(const cvector cv, void *memb)   {   	if (cv->cv_len >= cv->cv_tot_len)    	{   		void *pd_sav = cv->cv_pdata;   		cv->cv_tot_len <<= EXPANED_VAL;   		cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);    		if (!cv->cv_pdata)    		{   			cv->cv_pdata = pd_sav;   			cv->cv_tot_len >>= EXPANED_VAL;   			return CVEPUSHBACK;   		}   	}     //把memeb中的数据复制到cv_pdata的后面。从memeb拷贝cv_size个字节到cv_pdata的最后。 	memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size);   	cv->cv_len++;   	return CVESUCCESS;   }  对于memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size);   为什么(char*)不能够换成(int *)或（double *）或其它类型？  你换成 int*, double*也是完全可以的, 前面的楼已经说过, memcpy中参数是void*类型的. 最重要的是后面的参数, 要复制的长度, 单位是字节. 由于char刚好是占一个字节, 所以使用这个指针, 可以增强程序的可读性.

今后要在C论坛混了。。。

引用 4 楼 starytx 的回复:举了例子，假如原指针p的值为1(指向地址为1的空间)，现在要向它后边3个位置的地方赋值内容，那么需要把指针位置后移3位，那就是(char*)p+3,也就是memcpy(p+3 , xxx ,xxx);如果使用了int*或者其他来代替char*,那么就是(int*)p+3,此时指针指向的不是p后移3位的位置而是3*4=12的位置，因为一个int通常占4个字节，而char是1 ++    就是指针的加减法

引用 5 楼 zhao4zhong1 的回复:因为+后面表达式计算的数是以多少个char为单位；而不是以多少个int或多少个double为单位。  ++

因为char是 1 byte, 指针+1时向后偏移的是1 byte, 可以一个一个字节拷贝 如果转换成int*指针, 这样在计算大小的时候指针向后偏移是4byte, 算出来的大小如果是byte的话,需要除以4以对应指针的步长, 拷贝的时候是按照4byte为单位.  拷贝内存时肯定是按照byte为单位最合适, 而不是4byte或者多个byte

引用 楼主 daxiaoyuyu 的回复:我看了一篇博文： C语言实现 vector( 动态数组) 改进版  地址：http://blog.csdn.net/dengxu11/article/details/7311820  有一点不明白，在下面代码中 int cvector_pushback(const cvector cv, void *memb)   {   	if (cv->cv_len >= cv->cv_tot_len)    	{   		void *pd_sav = cv->cv_pdata;   		cv->cv_tot_len <<= EXPANED_VAL;   		cv->cv_pdata = realloc(cv->cv_pdata, cv->cv_tot_len * cv->cv_size);    		if (!cv->cv_pdata)    		{   			cv->cv_pdata = pd_sav;   			cv->cv_tot_len >>= EXPANED_VAL;   			return CVEPUSHBACK;   		}   	}     //把memeb中的数据复制到cv_pdata的后面。从memeb拷贝cv_size个字节到cv_pdata的最后。 	memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size);   	cv->cv_len++;   	return CVESUCCESS;   }  对于memcpy((char *)cv->cv_pdata + cv->cv_len * cv->cv_size, memb, cv->cv_size);   为什么(char*)不能够换成(int *)或（double *）或其它类型？  memcpy的实现是 void *memcpy(void *s1,const void *s2,size_t n) 你在C++的环境中的编译器 会严格检查函数的参数类型吧  当然就不行了 之所以memcpy为什么会选void* 因为这个是万能指针 可以实现泛型

cv_pdata 是怎么定义的？


你知道声码话这方面的只是么

太专业了吧！


Question: 帮忙看个数据结构的题目，谢谢啦

是变量p消失 但是你new出来的还在那 但是你却找不到在哪了 到底

char Pop(LinkStack &S,char e)//出栈 { LinkStack p; p=new StackNode;   //这行没有用。  if(S==NULL) { printf("栈为空！"); return ERROR; } else{  e=S->data; p=S; S=S->next; return e;} } 你这是要逆天啊  你这个p是局部变量 你定义了p 你new出来 你就给p赋值S啊 之后你也没用到p啊 你这样会new出来后 你都delete 不了 局部变量函数结束后 就消失了 还有我没看你程序逻辑 问题肯定很多 你这个p你回答我 你要用来做什么 还是你有地方写错了

大哥，就是帮我看下问题出在哪里，咋运行不了呢？麻烦帮忙改下，谢谢了！

char Pop(LinkStack &S,char e)//出栈 { LinkStack p; p=new StackNode;   //这行没有用。  if(S==NULL) { printf("栈为空！"); return ERROR; } else{  e=S->data; p=S; S=S->next; return e;} } int StackEmpty(LinkStack S) { if(S->next=NULL){ return ERROR;} else{ return OK; }  } int StackLength(LinkStack &S){ int len=0; while(S->next!=NULL){ len++; S=S->next; } return len; }   StackEmpty首先判断的是S是否为空。

你是要我帮你写一个 这个功能还是做什么 没看懂你要问的是什么 说关键 帮忙看 我也不能盯着看就帮到你了吧


Question: strlen()和sizeof()有什么区别

引用 18 楼 wjc19910312 的回复:[quote=引用 17 楼 wangdahu888 的回复:] [quote=引用 16 楼 wjc19910312 的回复:] [quote=引用 2 楼 wangdahu888 的回复:] char m[]={1,2,3,4,5}不会自动加上'\0'的,它是个数组呀,里面存放的什么就是什么 测试了一下如果在数组m中再加一个0到最后面就是5不是8了.如果在2后面加0，就变成2了.这是不是说遇到0就停止了，后面的被忽略了，那如果真这样元素里刚好有个0怎么办？[/quote] 数组就是数组呀，如果你想用字符串的功能可以考虑std::string类[/quote] 我的意思是说如果数组里有个0，那么用strlen时得到的值是0之前的元素的个数，而0后面的不被计入元素个数[/quote] 是的

引用 17 楼 wangdahu888 的回复:[quote=引用 16 楼 wjc19910312 的回复:] [quote=引用 2 楼 wangdahu888 的回复:] char m[]={1,2,3,4,5}不会自动加上'\0'的,它是个数组呀,里面存放的什么就是什么 测试了一下如果在数组m中再加一个0到最后面就是5不是8了.如果在2后面加0，就变成2了.这是不是说遇到0就停止了，后面的被忽略了，那如果真这样元素里刚好有个0怎么办？[/quote] 数组就是数组呀，如果你想用字符串的功能可以考虑std::string类[/quote] 我的意思是说如果数组里有个0，那么用strlen时得到的值是0之前的元素的个数，而0后面的不被计入元素个数

引用 16 楼 wjc19910312 的回复:[quote=引用 2 楼 wangdahu888 的回复:] char m[]={1,2,3,4,5}不会自动加上'\0'的,它是个数组呀,里面存放的什么就是什么 测试了一下如果在数组m中再加一个0到最后面就是5不是8了.如果在2后面加0，就变成2了.这是不是说遇到0就停止了，后面的被忽略了，那如果真这样元素里刚好有个0怎么办？[/quote] 数组就是数组呀，如果你想用字符串的功能可以考虑std::string类

引用 2 楼 wangdahu888 的回复:char m[]={1,2,3,4,5}不会自动加上'\0'的,它是个数组呀,里面存放的什么就是什么 测试了一下如果在数组m中再加一个0到最后面就是5不是8了.如果在2后面加0，就变成2了.这是不是说遇到0就停止了，后面的被忽略了，那如果真这样元素里刚好有个0怎么办？

引用 13 楼 wjc19910312 的回复:[quote=引用 1 楼 wangdahu888 的回复:] strlen(m)的长度是随机的吧,把m当成了一个字符串指针,其长度为遇到后第一个内容为0的内存处. 我的机器上长度还是19呢. 不会吧，会是19.我每次测试结果都是s的长度与m的元素个数之和，就像这个例子是3+5=8[/quote] 千真万确，出家人不打诳语。。。。。。

引用 7 楼 AnYidan 的回复:sizeof 是操作符，用于计算类型或对象所占用的空间，以 byte 为单位，在编译期完成  strlen 是函数，计算字符串的长度，遇到 '\0'结束，返回值以 byte 为单位，不含'\0'；在运行期完成  ++

引用 1 楼 wangdahu888 的回复:strlen(m)的长度是随机的吧,把m当成了一个字符串指针,其长度为遇到后第一个内容为0的内存处. 我的机器上长度还是19呢. 不会吧，会是19.我每次测试结果都是s的长度与m的元素个数之和，就像这个例子是3+5=8

strlen()是求实际长度， sizeof()是分配的存储空间

骚年还是要多看书啊。。

strlen()是求实际长度，遇到\0结束，sizeof()是分配的存储空间. 没有\0,长度是随机的。

两个层面的概念： 字符数组 字符串（以'\0'结尾的字符数组）

参考Linux中strlen()的源代码和gcc中sizeof()的源代码。

引用 楼主 wjc19910312 的回复:#include <stdio.h> #include <string.h> int main() {     char *s="abc";     char m[]={1,2,3,4,5};     printf("%d %d %d %d\n",strlen(s),sizeof(s),strlen(m),sizeof(m));     return 0; }  为什么strlen(m)是8，不是5.还有是不是strlen（）不计'\0',sizeof()计上'\0'.char m[]={1,2,3,4,5}不会自动加上'\0',就是不以'\0'结尾吗？  sizeof测量的是占了多少内存，strlen测试的是从一个开始位置到'\0'的字节数，你说的不是5是8和内存布局有关了， 看看这个 http://blog.csdn.net/koches/article/details/7526377

说错了。不是静态变量，是类型明确的变量

引用 3 楼 turingo 的回复:1、strlen会一直计数，直到遇到'\0'才停止； 2、sizeof是计算数组的字节数。  [quote=引用 楼主 wjc19910312 的回复:] #include <stdio.h> #include <string.h> int main() {     char *s="abc";     char m[]={1,2,3,4,5};     printf("%d %d %d %d\n",strlen(s),sizeof(s),strlen(m),sizeof(m));     return 0; }  为什么strlen(m)是8，不是5.还有是不是strlen（）不计'\0',sizeof()计上'\0'.char m[]={1,2,3,4,5}不会自动加上'\0',就是不以'\0'结尾吗？[/quote]  sizeof应该是编译时计算静态变量的占的空间

sizeof()在编译期就由编译器计算出数值了。这也是个差别。


Question: 循环终止问题

引用 7 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！   恩，我就是怕我自己写出不可预测的代码，所以问一下这个代码的操作流程。现在知道了。

引用 5 楼 u011594571 的回复:好吧，可能是我太弱。 我只是想知道，if语句判断的是ch的获取值，但是我总觉得ch每次获得是'\n'，所以当输入E或者e时，应该是x的值是E或者e啊，而ch = '\n',怎么循环也会终止。  你可以加个测试啊，scanf的返回值是成功读取的个数，当你输入‘e‘或者‘E'时你看看返回值是什么，scanf没有读入你的‘e‘或者‘E'，字母还在输入缓冲里放着呢，接着getchar就读入就....你懂的

break; 如果用于循环，跳出最内层的循环 如果用于switch，跳出最内层的switch

linux环境下验证了下，没有啥问题啊，lz有啥疑问

可能又是回车符的问题。。。。

不知楼主要问什么


Question: 请教一个编程的问题！

引用 6 楼 zhao4zhong1 的回复:重建所有 这是什么原因导致成的啊？

重建所有

rebuild all

看 编译器手册或google

清理项目，重新编译  抬头看你的帖子标题处,即有结贴二字

Debug目录删除了！重建所有吧。

怎样解决啊？


Question: 什么是原生代码？

楼主说的这个词语，应该是一个方言。

1.高级语言编译，链接，其实是实现以下过程：  源代码---->汇编----->机器指令  对否？ 不一定， 汇编语言－汇编－机器指令 C/C++语言－编译－机器指令 VB6、Java、.NET－编译－对应的P代码 2.可以把机器指令，变成汇编指令么？ 不应叫“变成”，应该叫“以汇编助记符的形式呈现”

引用 12 楼 zhao4zhong1 的回复:引用 11 楼 u012561056 的回复: [quote=引用 10 楼 zhao4zhong1 的回复:] 个人理解：不需要通过虚拟机，能直接让CPU执行的机器指令代码。  1.什么是机器指令代码？汇编？ 汇编是将二进制的机器指令代码翻译为人能看懂的助记符。 2.机器指令代码，可以反编译为源代码？ 不能。 3.javascript语言编写的程序，可以变成机器指令代码？ 不能，只能变成java虚拟机指令。[/quote]  1.高级语言编译，链接，其实是实现以下过程： 源代码---->汇编----->机器指令 对否？  2.可以把机器指令，变成汇编指令么？

e ,虽不明，但觉历

引用 12 楼 zhao4zhong1 的回复:引用 11 楼 u012561056 的回复: [quote=引用 10 楼 zhao4zhong1 的回复:] 个人理解：不需要通过虚拟机，能直接让CPU执行的机器指令代码。  1.什么是机器指令代码？汇编？ 汇编是将二进制的机器指令代码翻译为人能看懂的助记符。 2.机器指令代码，可以反编译为源代码？ 不能。 3.javascript语言编写的程序，可以变成机器指令代码？ 不能，只能变成java虚拟机指令。[/quote]  机器指令，可以反编译成汇编指令？

3楼，对！

引用 11 楼 u012561056 的回复: 引用 10 楼 zhao4zhong1 的回复:个人理解：不需要通过虚拟机，能直接让CPU执行的机器指令代码。  1.什么是机器指令代码？汇编？ 汇编是将二进制的机器指令代码翻译为人能看懂的助记符。 2.机器指令代码，可以反编译为源代码？ 不能。 3.javascript语言编写的程序，可以变成机器指令代码？ 不能，只能变成java虚拟机指令。

引用 10 楼 zhao4zhong1 的回复:个人理解：不需要通过虚拟机，能直接让CPU执行的机器指令代码。  1.什么是机器指令代码？汇编？  2.机器指令代码，可以反编译为源代码？  3.javascript语言编写的程序，可以变成机器指令代码？

个人理解：不需要通过虚拟机，能直接让CPU执行的机器指令代码。

引用 7 楼 u012561056 的回复:[quote=引用 1 楼 wangdahu888 的回复:] 就是Native Code，编译后可直接依附操作系统运行，不需要经过虚拟机之类的东西。  javascript可以转化为原生代码么？[/quote] 不可以吧,运行时需要解释器

引用 1 楼 wangdahu888 的回复:就是Native Code，编译后可直接依附操作系统运行，不需要经过虚拟机之类的东西。  javascript可以转化为原生代码么？

没听过，路过

引用 4 楼 u012561056 的回复:[quote=引用 3 楼 wangdahu888 的回复:] [quote=引用 2 楼 u012561056 的回复:] [quote=引用 1 楼 wangdahu888 的回复:] 就是Native Code，编译后可直接依附操作系统运行，不需要经过虚拟机之类的东西。   1.原生代码：是指一些高级语言，编译，链接后的代码？  2.C， objective-c，都可以产生原生代码？    javascript，也可以产生原生代码么？[/quote] javascript要通过一个解释器来执行,并不是直接依附操作系统运行[/quote]   C， objective-c ？[/quote]可以产生原生代码

引用 3 楼 wangdahu888 的回复:[quote=引用 2 楼 u012561056 的回复:] [quote=引用 1 楼 wangdahu888 的回复:] 就是Native Code，编译后可直接依附操作系统运行，不需要经过虚拟机之类的东西。   1.原生代码：是指一些高级语言，编译，链接后的代码？  2.C， objective-c，都可以产生原生代码？    javascript，也可以产生原生代码么？[/quote] javascript要通过一个解释器来执行,并不是直接依附操作系统运行[/quote]   C， objective-c ？

引用 2 楼 u012561056 的回复:[quote=引用 1 楼 wangdahu888 的回复:] 就是Native Code，编译后可直接依附操作系统运行，不需要经过虚拟机之类的东西。   1.原生代码：是指一些高级语言，编译，链接后的代码？  2.C， objective-c，都可以产生原生代码？    javascript，也可以产生原生代码么？[/quote] javascript要通过一个解释器来执行,并不是直接依附操作系统运行

引用 1 楼 wangdahu888 的回复:就是Native Code，编译后可直接依附操作系统运行，不需要经过虚拟机之类的东西。   1.原生代码：是指一些高级语言，编译，链接后的代码？  2.C， objective-c，都可以产生原生代码？    javascript，也可以产生原生代码么？


Question: static定义变量

引用 4 楼 abc594986308 的回复:[quote=引用 2 楼 wangdahu888 的回复:] static修饰的变量是静态的,在第一次进入fac时,被初始化为1,以后每次进入fac函数,static修饰的变量都为上次的值.  建议楼主先加强基础知识吧 懂了懂了，突然就懂了，我懂了[/quote] 结合一下阶乘的公式呗

引用 2 楼 wangdahu888 的回复:static修饰的变量是静态的,在第一次进入fac时,被初始化为1,以后每次进入fac函数,static修饰的变量都为上次的值.  建议楼主先加强基础知识吧 懂了懂了，突然就懂了，我懂了

引用 2 楼 wangdahu888 的回复:static修饰的变量是静态的,在第一次进入fac时,被初始化为1,以后每次进入fac函数,static修饰的变量都为上次的值.  建议楼主先加强基础知识吧 这个我知道，但是问题在于我不知道它怎么就把阶乘给算出来了，求阶乘的那个函数真心没搞明白啊，求助

static修饰的变量是静态的，也就是只要进程没有结束，它的值一直是有效的！


Question: 新手提问：函数调用，参数个数不对应。

可以使用联合体, 函数指针的联合体. 并且函数调用指定stdcall, 这样堆栈平衡就由调用者保证, 函数自已就不用管堆栈平衡了.

引用 5 楼 Caynne_s 的回复:[quote=引用 2 楼 wangdahu888 的回复:] and $0xfffffff0,%esp  ;把esp中的低位的位置零,相当于把esp变小,在栈上分配一下内存空间  剩下的那三条指令,就是依次压栈呗,没什么好说的 请问，在c中，如果遇到像参数个数不匹配的情况，是怎么做处理的呢？[/quote] 参数个数不匹配，直接报编译错误了呀

引用 2 楼 wangdahu888 的回复:and $0xfffffff0,%esp  ;把esp中的低位的位置零,相当于把esp变小,在栈上分配一下内存空间  剩下的那三条指令,就是依次压栈呗,没什么好说的 请问，在c中，如果遇到像参数个数不匹配的情况，是怎么做处理的呢？

与0xFFFFFFF0想与应该和内存对齐有关吧，取4的整数倍位置存放东西

原因是调用函数时不知道函数原型

mov %esp, %ebp    //先把%esp保存在寄存器%ebp（应该是4字节的） and $0xfffffff0,%esp //%esp &= 0xfffffff0 我理解的应该是这样


多半指点窗口左上角时，shou系统菜单的消息。

这是哪个UI框架


Question: 阿里巴巴笔试题，大家来看看

不同线程生成的数据可能会互相覆盖，但不影响结果  #define ARRMAX 255 volatile char g_out[ARRMAX]; volatile int g_idx = 0; void *threadfunc(void *p) {   char c = (char *)p;   for(;;){     int idx = g_idx++;     if (idx >= ARRMAX) return NULL;     g_out[idx] = c;     sleep(0);   } }  int main(){   pthread_t th;   char in[] = "abcd";   int i = 0;   for(; i < 4; i++){     if (pthread_create(&th, NULL, threadfunc, (void *)in[i]) < 0) return -1;   }   sleep(10); }

LZ首先得纠正个观点，“只利用线程的随机调度特性”也是首先要你能够创建线程，才能利用此特性，如果连线程都不用，怎么利用此特性？ 不要太纠结于“不提供任何相关库函数和工具包”

再顶  引用 6 楼 qq120848369 的回复:1, 首先你明白洗牌法，我们的工作就是封装一个rand方法，用题目的条件。 2, 启动一个线程,让其sleep(1), 主线程保持死循环++i如下: static volatile unsigned int n = 0;  unsigned int rand_function() {  pthread_create(); // 启动一个线程, 线程里sleep(1)后标记n=1并退出 unsigned int i = 0; while (true) {     n++;     if (n) { pthread_join(); return i} } } 这样还是要用到pthread库啊

不知道，帮顶，撸主知道答案后记得通知一下

引用 6 楼 qq120848369 的回复:1, 首先你明白洗牌法，我们的工作就是封装一个rand方法，用题目的条件。 2, 启动一个线程,让其sleep(1), 主线程保持死循环++i如下: static volatile unsigned int n = 0;  unsigned int rand_function() {  pthread_create(); // 启动一个线程, 线程里sleep(1)后标记n=1并退出 unsigned int i = 0; while (true) {     n++;     if (n) { pthread_join(); return i} } }  写错了哈, 是i++

看题目的意思应该就是只使用标准C语言和sleep函数实现，没说可以创建线程

你真实在，，，，，，都说了让你利用线程调度的随机性，，，难道你自己实现一个线程？？  再说了。 线程库是c的一部分，线程不能用，是不是c的库文件lib都不能用呢？？？？？

题目说不可以用任何库啊，所以应该是不能创建线程的

可不可以一个数对应一个线程呢？然后通过sleep控制顺序？

木有人回答啊，自己顶


Question: 线程问题

引用 1 楼 ml0719787 的回复:不要用sleep  #include <stdlib.h> #include <stdio.h> #include <pthread.h>  pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; void* func(void *arg) {     printf("%d\n", *(int *)arg);     pthread_mutex_unlock(&mymutex);     return NULL; }  int main() {      int i;     pthread_t p[10] = {0};     pthread_mutex_lock(&mymutex);     for(i = 0; i < 10; i++)     {            pthread_create(&p[i],NULL,func,&i);         pthread_mutex_lock(&mymutex);     }                 pthread_mutex_unlock(&mymutex);              for(i = 0; i < 10; i++)     {            pthread_join(p[i],NULL);     }        return 0; }   在你代码基础上，加了一点，但是感觉还有没必要！

不要用sleep


Question: 关于IP访问的函数实现

用hash+lru哈，不懂可以百度这个名词。

引用 1 楼 u011779875 的回复:这样呢 数组的第二维如果不够用怎么办 第一 你第二维大一点不就得了   第二 动态试探申请 先malloc一部分 可以满足基本条件 每次用到时进行判断 是否足够维数 realloc   一些维数 已定义增加维数宏 这个问题暂时不管了，可以给出统计IP访问次数还有老化的算法吗，尽量节约时间，遍历数组次数尽量少些


Question: 帮忙解释下递归调用的压栈过程！

关于递归我说两点，领悟了，便算掌握递归了。 1.把递归当成普通函数，然后理解整个函数的语义，这个函数的每个调用要从逻辑上讲得通。 2.递归得有个”出口“，否则就无限调用了。

引用 11 楼 zhang5476499 的回复:[quote=引用 10 楼 zhao4zhong1 的回复:] “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出赵老师，你的这个回复貌似以前看过。[/quote] 估计我的所有回复中，算全新内容的占总数5%不到吧。

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

引用 16 楼 ForestDB 的回复:题目的意思，与其说是地址，不如说是行数，即运行到哪一行。  计算机系统的栈，不是具体语言写出来的，而是一个运行的程序，它的内存分布的一个客观存在的一片区域，这片内存的使用，遵循“后进先出”的栈的行为，所以被称为“栈”。  顺序表是“概念”，除了首尾，每一个元素只有一个“前”一个“后”，这样的东西就是“顺序表”；反观数组，它只是一种“实现”，链表也是“顺序表”的一种实现。  另外常见的顺序表的实现，数组也好，链表也好，元素的类型都是相同的，但是就顺序表这个概念来说，根本就没有这个要求，元素可以是不同类型的，扩展了这个概念的，其实就是广义表了。  学计算机的东西，分清楚“概念”和“实现”。嗯，此楼讲解的很通俗易懂。

估计至少得两、三年吧。

引用 12 楼 zhao4zhong1 的回复:[quote=引用 11 楼 zhang5476499 的回复:] [quote=引用 10 楼 zhao4zhong1 的回复:] “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出赵老师，你的这个回复貌似以前看过。[/quote] 估计我的所有回复中，算全新内容的占总数5%不到吧。[/quote]不过我最感兴趣的是学多久才能学到你的这种程度？本人计算机专业大二学生，我接触C语言（第一门语言，现在还有c++）到现在已经10个月啦。   不知按这种速度，什么时候才能可以拿出技术去用！

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

就当成普通函数调用那样来分析就行了

如果还不懂 就得画图了最清楚了 我描述能力不好  这也不是很厉害 晚上回去 有空帮你画一张图  全懂了就  但是最后你自己找出答案 你自己画画

引用 5 楼 zhang5476499 的回复:[quote=引用 3 楼 u011779875 的回复:] 这个在延伸 就会讲到 虚拟进程地址空间 这个概念  高手和菜鸟之分 我认为就在这个分水岭 犹如北方与南方 的淮河为界限那个返回地址具体指的是哪一句的地址啊？[/quote] 递归调用 最后一次的返回地址 返回的是上一次的调用 只有递归到最后才会依次返回到第一层调用

引用 4 楼 zhang5476499 的回复:[quote=引用 2 楼 u011779875 的回复:] 计算机系统中，用的是什么语言写的栈？这个栈是顺序栈还是链栈？  计算机系统的栈 分为用户栈 和内核栈之分 这种栈和数据结构的栈 不是俩回事 你不要混了  这种栈是带栈顶指针 和基址指针的   此栈非比栈 内存中连续的任何地方 只要是想作为压栈出栈 只是个思想 具体实现是 特定的寄存器来搞定的还有我一直不明白顺序表与静态数组的关系。我一直认为顺序表就是静态数组的别名。 [/quote] 我的理解啊  仅供参考 顺序表 就是静态数组的别名 这样理解是有偏差的  这个顺序表的意思应该是 连续存储的别称  就是你有东西连续存储的 这样才成为顺序  顺序表概念来源于数据结构 基础数据 无非 增删改查  所以它代表的是一种思想 连续的概念  例如 内存区域的连续 链表 内存区域也可以是连续的啊 但是这样没多大意义  把零散的内存集中起来 这才是它的意义

引用 3 楼 u011779875 的回复:这个在延伸 就会讲到 虚拟进程地址空间 这个概念  高手和菜鸟之分 我认为就在这个分水岭 犹如北方与南方 的淮河为界限那个返回地址具体指的是哪一句的地址啊？

引用 2 楼 u011779875 的回复:计算机系统中，用的是什么语言写的栈？这个栈是顺序栈还是链栈？  计算机系统的栈 分为用户栈 和内核栈之分 这种栈和数据结构的栈 不是俩回事 你不要混了  这种栈是带栈顶指针 和基址指针的   此栈非比栈 内存中连续的任何地方 只要是想作为压栈出栈 只是个思想 具体实现是 特定的寄存器来搞定的还有我一直不明白顺序表与静态数组的关系。我一直认为顺序表就是静态数组的别名。

哦，忘了写题目了，题目是这样的。


Question: int a = 'abc';  结果是多少？如何理解？

#include <stdio.h>  int main(void) { 	 	int   a = 'a'; //type promotion 	printf("a = %d\n", a);  	 	a = 'abc'; 	//printf("a = %d\n", a);         printf("a = %x\n", a); //616263, 0x61 == 97 == 'a' 		 	//it's okay to convert char const* to int in C 	a = "a"; 	printf("a = %d\n", a);  	a = "abc"; 	printf("a = %d\n", a);	 	return 0; }

在c++中， 仅 int a = 'a';有效。

zhege??

a = 'abc'; 这个定义很别扭，如果学了C语言基础，应该不会出现这样的定义； 首先字符和字符串在存储器中的区别是：字符串最后一位是结束符：'\0'，而字符没有结束符； 字符型和INT型是一样的； 你这样定义，即使编译通过，但是别人看到这个变量的定义，感觉很别扭；

a = 'abc'; mov         dword ptr [a],616263h

将代码改为： #include <stdio.h> union un { 	int i; 	char c[4]; }; int main(void) { 	/* 将单个字符赋值给整形变量，结果为字符的ASCII值 */ 	int   a = 'a'; 	printf("a = %d\n", a); 	/* ?这里如何解释 */ 	union un b; 	b.i = 'abc'; 	printf("b.i = %d\n", b.i); 	printf("b.c = %c %c %c %c\n", b.c[0], b.c[1],b.c[2],b.c[3]);  	/* 将字符串赋值给整形变量，结果为字符串的地址值 */ 	a = "a"; 	printf("a = %d\n", a);  	a = "abc"; 	printf("a = %d\n", a); 	return 0; }   运行结果： a = 97 b.i = 6382179 b.c = c b a （非Ascii符号） a = 4206665 a = 4206667 这个输出就清楚了。

a = 'abc';  就是一个宽字符

'abc' 这种常量一般很少用， 只有VC开发驱动时，偶尔见过 是这样写的  L'DCBA'     //L'DCBA' 即 ABCD 定义一个常量，顺序是 ABCD， 是这4个字母的ASCII码的顺序排列。 用来做驱动程序的标志。

#include <stdio.h>  int main(void) {     int   a = 'a';     printf("a = %d\n", a);     printf("a = %x\n", a); // 顺便也看看%x的输出      a = 'abc'; // 这个叫multi-character character constant     printf("a = %d\n", a);     printf("a = %x\n", a); // 顺便也看看%x的输出      a = "a"; // 这个和下个都是把一个地址赋给a了     printf("a = %d\n", a);      a = "abc";     printf("a = %d\n", a);        return 0; }

#include <stdio.h>  int main(void) {     printf("%x\n", 'aabc');     return 0; }  打印了61616263，应该是当成个数字对待的吧.....

VC++6.0 这样写 a="a"与a="abc"会报错 那个 a='abc' 我也觉得是这么来的，一个a在VC中占一个字节 0110 0001 同理b为0110 0010 c为0110 0011 然后再合并就成了6382179

那第四个字节呢？我说的是第四个字节！

引用 16 楼 worldy 的回复:[quote=引用 7 楼 u011779875 的回复:]  6382179 代表的16进制是 616263 代表的是 abc  这个是正确的 我刚才只是猜测 我又没遇到过 后面没随机  第四个字节应该是个随机数 [/quote] 说法错误,第四个字节根本就不是个随机数,编译器直接用616263h来替换了'abc'了呀,你反汇编看一下就知道了

学习了，提示我们数据的异常判断很重要。

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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对应的汇编并单步执行观察相应内存和寄存器变化。）   有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！

引用 16 楼 worldy 的回复:[quote=引用 7 楼 u011779875 的回复:]  6382179 代表的16进制是 616263 代表的是 abc  这个是正确的 我刚才只是猜测 我又没遇到过 后面没随机  第四个字节应该是个随机数 [/quote]不是随机数 是00000000

引用 7 楼 u011779875 的回复:6382179 代表的16进制是 616263 代表的是 abc  这个是正确的 我刚才只是猜测 我又没遇到过 后面没随机  第四个字节应该是个随机数

经过试验得出结论：     a = 'abc';      VC、GCC里处理实际就是将三个字符的ASCII码二进制合并起来     0110 0001    0110 0010   0110 0011     合并后转换为十进制，结果就是6382179     'abc'是int，不是地址     用char ch = 'abc'，输出结果是'c'

请问'abc'，里面的值到底是a、b还是c呢？  不同的编译器，处理不一样，ANSIC对此的结果是未定义。。。。

引用 6 楼 lin5161678 的回复:[quote=引用 2 楼 u011779875 的回复:] a = 'abc'; printf("a = %d\n", a); 'abc'代表的是一段内存地址  存的是979899xx的二进制 xx是随机的意思 而a是int型的 所以取四个字节吧 就会取到6382179 我没有具体算 但是应该是这样 别闹 'abc' 不是"abc" 'abc'只是一个int  表示的值依赖实现  这里是想为 0x979899 没有后面随机二进制 [/quote]  觉得你说的是对的，'abc'不是一个地址值 我用三种编译器编译运行这个程序，结果都是6382179 而下面字符串地址则会发生变化


Question: 请问以下代码框架有问题吗?

引用 4 楼 huabinsir 的回复:在 case 语句后， 有的用break, 有的用return 0, 这会有问题吗? case 里面 最后放break 不要随便在case中用 return 0 貌似我学这么久 没这么用过 这种用法是不提倡的

swtich语句的后面，函数的结束部分，没有return。

如果各个case之间没有别的代码操作的话，可以代码重用下！ 如果有的话，就这样也行！框架问题，片面代码也是看不出来是否存在问题！

感觉就是有的部分可以归纳一下。


Question: 只会C语言能考什么证么？是不是费点劲

好好学习c语言吧！

15考时间也紧张啊,别吓搞,专心准备考研吧

软考可以选C语言阿

证有什么用？？？

个人意见： 计算机科学与技术专业的本科学生考计算机相关的证 就和 外语大学英语专业的本科学生考英语四、六级 一样可笑（无用）！

《Linux C编程一站式学习》

国内的证就是浪费时间浪费生命 有时间的话可以考着玩

大二飘过。。。c++数据结构研究中，安卓开始入门

引用 4 楼 u011779875 的回复:不是考那个注册工程师 计算机方面的那个证 你就可以回家数钱去了 第二 证有没有都行 就像你有女朋友 但是从来不想领结婚证的人一样 不代表什么 第三我连大学毕业证刚发下来我就扔家里了 证没用 关键是你有分析问题的能力 谢了，我还是专心准备考研

引用 3 楼 max_min_ 的回复:好好学习c语言吧！ 现在发现语言真挺有意思，整天在寝室敲啊敲，大一就这样我也不用现在这么着急了


引用 2 楼 u011779875 的回复:#define time_after_eq(a,b)    \      (typecheck(unsigned long, a) && \     typecheck(unsigned long, b) && \     ((long)(a) - (long)(b) >= 0))  在宏中，参数 a 是 jiffies 在某个时刻的快照,如果 a 所代表的时间比 b 靠后或者相等，那么返回真 是被包含在库里可以直接引用，还是要自己定义 jiffies可以直接向变量赋值吗

用法 术语应该叫 准确计算间隔时间

这种的东西的用法 例如 windows中 因为Sleep这个东西可以被信号穿透  也和机器的好坏有关 运行不准确 所以就与了如下用法 	  long tickbeign=GetTickCount(); 	  long tickend=GetTickCount();  		  while(tickend - tickbeign <= time_5) // 60 		{ 			tickend=GetTickCount(); 		}

木有文档吗？？？应该有例子吧

windows中的取得系统启动到现在运行的时间是 GetTickCount返回（retrieve）从操作系统启动到现在所经过（elapsed）的毫秒数，

http://www.cnblogs.com/leaven/archive/2010/08/30/1812338.html 看这个     硬件给内核提供一个系统定时器用以计算和管理时间，内核通过编程预设系统定时器的频率，即节拍率（tick rate),每一个周期称作一个tick(节拍）。Linux内核从2.5版内核开始把频率从100调高到1000（当然带来了很多优点，也有一些缺点）.    jiffies是内核中的一个全局变量，用来记录自系统启动一来产生的节拍数。譬如，如果计算系统运行了多长时间，可以用 jiffies/tick rate 来计算。jiffies定义在文件<linux/jiffies.h>中：

求大神指点。

引用 9 楼 ml0719787 的回复:time_after_eq和time_after有哪些不同 没什么不同吧 不是eq吗 equal  就是相等的意思 比如> 和>=的区别  <linux/jiffies.h> 这个不是解释了吗 jiffies是内核中的一个全局变量，用来记录自系统启动一来产生的节拍数。 直接头文件引用 直接去可以用   它和errno比较类似吧


Question: 串口中断接收问题

仔细看 manual mcu 的官网看看source code

引用 2 楼 JiMoKuangXiangQu 的回复:51单片机吧？使用Keil IDE(MDK)？建议发到 硬件/嵌入开发 板块。 这个得看芯片的规格书。是不是芯片在进入中断的时候会自动禁用中断？但是我还有接收啊，接收也在中断里，它能接收，应该是能进中断吧！

推荐使用portmon软件辅助串口通讯程序调试。


Question: 在线求助：C中结构体碰到的怪问题，求分析解释，附源码和结果，谢谢

摒弃cin，cout； 使用scanf，printf！

引用 5 楼 z1179675084 的回复:确实如你所说，越界了，这个问题你先这样做一下  	printf("%0x\n",ds.num1); 	printf("%0x\n",ds.num2); 	printf("%0x\n",&ds.num3);  通过打印的地址，手动画你输入的东西在内存中的分布，当然这里ds.num2和&ds.num3中间隔了一个字节是由于内存对齐的问题。最后输出3224115转化为16进制31 32 33对应于字符‘0’，‘1’，‘2’。到这里估计你这个问题就解决了。多动手动脑！ 另外好像你这个C语言和C++分的不是很清楚啊，在C++里面struct本身就是定义一个类了。你这个写法是C的   typedef struct student { 	char num1[5]; 	char num2[6]; 	int num3; }stu;  stu ds;  C++这样就可以   struct stu { 	char num1[5]; 	char num2[6]; 	int num3; };  stu ds;  如果还有什么不清楚的加我Q吧

Try following:  std::cin.getline(ds.num1, 5);  std::cin.getline(ds.num2, 6);

引用 3 楼 zhaoxiatengkong_1 的回复:[quote=引用 2 楼 yulinlang 的回复:] 因为数组越界了  可以这么说吧， 如果输入的字符在提示的字符数范围内则正常显示，  但是为什么越界之后，不自动截断， 而出错这些怪怪的结果呢？[/quote] 首先，C以效率为第一优先，如果程序员需要某种额外的功能，必须自己添加，编译器只负责把程序员写下来的代码转换成最高效率的执行程序。而C++继承自C的指针等内容，也继承相同的设计方式。如果你想要不管你怎么写都能替你自动处理的语言，那就不该学C/C++。 然后，即使它想替你截断，它也没办法截断。对于cin的operator>>操作符重载函数，你给它的是一个由char数组隐式转换而来的char*指针，函数根本就没有接收到任何关于长度的信息，它怎么知道该从第几个字符的地方截断？ 最后，这个问题跟缓存没关系，纯粹是三个数据内存相连，你调用cin修改前两个数据的时候错误的使用它修改了三个数据所在的内存。在这个程序中你输入的第二个字符串所需的内存长度恰好只到num3为止，如果再长的话，连这三个数据所在函数退出的时候都会因为堆栈地址被改写而发生堆栈错误！

引用 1 楼 ak47_wz 的回复:这个我回答不了你。。。同学习中。 个人感觉应该是cout在输出的时候做了特殊的处理，这种库函数是带缓冲的。倘若用系统调用直接输出的话，应该会有不同的结果。 其次是，这个已经知道是错误的情况了，感觉没啥深究的必要啊。如果要深究，应该去看看cout输出流做了什么样的处理，可能这样会好一点。 第二次测试时考虑了缓存的问题， 所以加入了fflush(stdin)； 但是结果依然出错，cout的使用 还没去看MSDN ， 待会去看一下

引用 2 楼 yulinlang 的回复:因为数组越界了  可以这么说吧， 如果输入的字符在提示的字符数范围内则正常显示，  但是为什么越界之后，不自动截断， 而出错这些怪怪的结果呢？

因为数组越界了


Question: 解密加密.c

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。

引用 3 楼 abc594986308 的回复:[quote=引用 1 楼 gerrard0616 的回复:] 打印一下s[0]，看看里面存的是什么 改成scanf("%d\n",&n);接收掉一个回车就好了 接收是可以，但是在输入数字后，按回车就可以马上输入字符，而后提示“请输入字符”，后来才显示。[/quote] 2楼说的很到位了啊 输完了n的值后回车符'\n',程序继续执行，但是'\n'还在缓冲区里，在你后面用scanf接收字符时，你的'\n'还在，因此会存到s[0]中。 举个例子 输入4'\n'（回车） 然后输入ABCD 那么 你的s[0]-s[3]中实际存到的是"\nABC" 单步调试一下就能看见了。

引用 2 楼 u011779875 的回复:[quote=引用 楼主 abc594986308 的回复:] /* *设计一个加密和解密的算法，在对一个指定的字符串 *加密之后，利用解密函数能够对密文解密，显示明文 *信息。加密的方式是将字符串中每个字符加上它在字符 *串中的位置和一个偏移值5.第一个字符“m”在字符串 *中的位置为0，那么它对应的密文是“'m'+0+5”,即r. *依据题目信息。首先是加密函数 char *jm(char *str,int i,int m) {     for(i=0;i<m;i++) 	{ 	    s[i]=s[i]+i+5; 	} 	return str; } 再者，解密函数 char *jm1(char *str,int i,int m) {     for(i=0;i<m;i++) 	{ 	    s[i]=s[i]-i-5; 	} 	return str; } main() {     char s[100],int j,int n; 	printf("你要输入的字符串字符的个数\n"); 	scanf("%d",&n); 	printf("输入字符\n") 	for(j=0;j<n;j++) 	{ 	    scanf("%c",s[j]); 	} 	jm(s,j,n); 	for(j=0;j<n;j++) 	{ 	    printf("%c",s[j]); 	} 	jm1(s,j,n); 	for(j=0;j<n;j++) 	{ 	    printf("%c",s[j]); 	} } */ #include <stdio.h> char *jm(char *str,int i,int m) {     for(i=0;i<m;i++) 	{ 	    str[i]=str[i]+i+5; 	} 	str[m]='\0'; 	return str; } /*再者，解密函数*/ char *jm1(char *str1,int k,int p) {     for(k=0;k<p;k++) 	{ 	    str1[k]=str1[k]-k-5; 	} 	str1[p]='\0'; 	return str1; } main() {     char s[100],q[100]; 	int j; 	int n; 	printf("你要输入的字符串字符的个数\n"); 	scanf("%d",&n); 	printf("输入字符\n"); 	for(j=0;j<n;j++) 	{ 	    scanf("%c",&s[j]); 	} 	jm(s,j,n); 	printf("加密后的字符串\n"); 	for(j=0;j<n;j++) 	{ 	    printf("%c",s[j]); 		q[j]=s[j]; 	} 	printf("\n解密后的字符串\n"); 	jm1(q,j,n); 	printf("%c",q[0]); 	for(j=0;j<n;j++) 	{ 	    printf("%c",q[j]); 	} 	printf("\n"); } 运行后解密函数运行完后怎么老是少一个字符。  scanf("%d",&n); scanf("%c",s[j]); 连用的情况请在中间加入 getchar(); 或者fflush(stdin);  原因是scanf的实现 %d是按空格区分的 但是 %c可是无条件接收的 scanf %d 最后输入的回车 会保留在缓冲区  行缓冲 全缓冲  无缓冲的区别 百度看下[/quote] 非常感谢

引用 1 楼 gerrard0616 的回复:打印一下s[0]，看看里面存的是什么 改成scanf("%d\n",&n);接收掉一个回车就好了 接收是可以，但是在输入数字后，按回车就可以马上输入字符，而后提示“请输入字符”，后来才显示。

引用 楼主 abc594986308 的回复:/* *设计一个加密和解密的算法，在对一个指定的字符串 *加密之后，利用解密函数能够对密文解密，显示明文 *信息。加密的方式是将字符串中每个字符加上它在字符 *串中的位置和一个偏移值5.第一个字符“m”在字符串 *中的位置为0，那么它对应的密文是“'m'+0+5”,即r. *依据题目信息。首先是加密函数 char *jm(char *str,int i,int m) {     for(i=0;i<m;i++) 	{ 	    s[i]=s[i]+i+5; 	} 	return str; } 再者，解密函数 char *jm1(char *str,int i,int m) {     for(i=0;i<m;i++) 	{ 	    s[i]=s[i]-i-5; 	} 	return str; } main() {     char s[100],int j,int n; 	printf("你要输入的字符串字符的个数\n"); 	scanf("%d",&n); 	printf("输入字符\n") 	for(j=0;j<n;j++) 	{ 	    scanf("%c",s[j]); 	} 	jm(s,j,n); 	for(j=0;j<n;j++) 	{ 	    printf("%c",s[j]); 	} 	jm1(s,j,n); 	for(j=0;j<n;j++) 	{ 	    printf("%c",s[j]); 	} } */ #include <stdio.h> char *jm(char *str,int i,int m) {     for(i=0;i<m;i++) 	{ 	    str[i]=str[i]+i+5; 	} 	str[m]='\0'; 	return str; } /*再者，解密函数*/ char *jm1(char *str1,int k,int p) {     for(k=0;k<p;k++) 	{ 	    str1[k]=str1[k]-k-5; 	} 	str1[p]='\0'; 	return str1; } main() {     char s[100],q[100]; 	int j; 	int n; 	printf("你要输入的字符串字符的个数\n"); 	scanf("%d",&n); 	printf("输入字符\n"); 	for(j=0;j<n;j++) 	{ 	    scanf("%c",&s[j]); 	} 	jm(s,j,n); 	printf("加密后的字符串\n"); 	for(j=0;j<n;j++) 	{ 	    printf("%c",s[j]); 		q[j]=s[j]; 	} 	printf("\n解密后的字符串\n"); 	jm1(q,j,n); 	printf("%c",q[0]); 	for(j=0;j<n;j++) 	{ 	    printf("%c",q[j]); 	} 	printf("\n"); } 运行后解密函数运行完后怎么老是少一个字符。  scanf("%d",&n); scanf("%c",s[j]); 连用的情况请在中间加入 getchar(); 或者fflush(stdin);  原因是scanf的实现 %d是按空格区分的 但是 %c可是无条件接收的 scanf %d 最后输入的回车 会保留在缓冲区  行缓冲 全缓冲  无缓冲的区别 百度看下


Question: 函数传值的问题

引用 7 楼 AnYidan 的回复:林锐 高质量c/c++编成指南 有时间一定读，正在努力中。

引用 8 楼 zhao4zhong1 的回复:从汇编角度弄清楚__cdecl,__stdcall,__fastcall,thiscall的区别再说。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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 长知识了，以后一定记得前辈给的经验。

引用 5 楼 user-4 的回复:不是结果得不到吧！是代码编译都不过吧！ 错误已经帮你改好了，参考下修改后的代码！ 思路是没错的！  #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXE 10 typedef struct name {     char build[MAXE][21];     int top; }luxian;  luxian * create(void); int push(luxian *lu2); char * pop(luxian *lu3); int sempty(luxian *lu4);  int main() {     int i;//判断入栈是否成功     char *zu[21];//用来存储出栈时的所有元素     char *p;//用来接收出栈元素的那个元素     luxian *lu=NULL;     lu=create();     i=push(lu);     printf("%d\n",lu->top);     printf("%d\n",i); //  strcpy((zu[1]), pop(lu));     printf("%d\n",i);  } luxian* create(void) {     luxian *luxian1;     luxian1=(luxian *)malloc(sizeof(luxian));     luxian1->build[MAXE][21]=0;     luxian1->top=-1;     return(luxian1); }  int push(luxian *lu2) {     char name[21];     if(lu2->top==MAXE-1)     {            return(0);     }        printf("请输入地址\n");     scanf("%s",name);     lu2->top++;     printf("%d\n",lu2->top);     strcpy(lu2->build[lu2->top],name);     return(1); } char * pop(luxian *lu3) {     char *p;     printf("%s\n",lu3->build[lu3->top]);      if(sempty(lu3))     {         printf("栈为空了\n");         return NULL;     }     else     {         p=(char *)malloc(21*sizeof(char));         printf("%s\n",lu3->build[lu3->top]);         strcpy(p,lu3->build[lu3->top]);         printf("dazhele1\n");         lu3->top--;         return(p);       } } int sempty(luxian *lu4) {     if(lu4->top==-1)     {         return 0;     }     else     {         return 1;     } }   啊！！！！！！知道了，我去，搞混了。唉！  谢谢了！

mk:@MSITStore:C:\MSDN98\98VS\2052\vccore.chm::/html/_core_argument_passing_and_naming_conventions.htm Argument Passing and Naming Conventions Home |  Overview |  How Do I  All arguments are widened to 32 bits when they are passed. Return values are also widened to 32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. Parameters are pushed onto the stack from right to left.  The compiler generates prolog and epilog code to save and restore the ESI, EDI, EBX, and EBP registers, if they are used in the function.  Note   For information on how to define your own function prolog and epilog code, see Naked Function Calls.  The following calling conventions are supported by the Visual C/C++ compiler.  Keyword Stack cleanup Parameter passing  __cdecl Caller Pushes parameters on the stack, in reverse order (right to left)  __stdcall Callee Pushes parameters on the stack, in reverse order (right to left)  __fastcall Callee Stored in registers, then pushed on stack  thiscall  (not a keyword) Callee Pushed on stack; this pointer stored in ECX    For related information, see Obsolete Calling Conventions.

林锐 高质量c/c++编成指南

引用 4 楼 u012510962 的回复:[quote=引用 1 楼 u011779875 的回复:] 我没有看你程序的逻辑  第一点 我严重怀疑你的程序是会有很多警告的吧 对于警告  这个东西 最好全不干掉 要不然 你终有一天会吃大亏的  你主函数是这样调用的吗 luxian p; push(p);   第二点 你要记住 函数传参 永远是值的一份拷贝  就算是地址也是一份拷贝 只不过你可以对该地址指向的地方 进行修改值 嗯！确实有好多警告，以后一定注意。顺便问一下结构体指针中存在int变量，当这个指针为实参传值时在被调函数中改变int变量的值时，当函数结束后，其int改变的值会不会在主函数中有所保存。[/quote]  看你怎么传了 如果只是 luxian p;  push(p);   不会有任何改变  luxian p;  push(&p); 这样在处理函数中改变int型a的值 那就会改变 主函数会随着改变

引用 1 楼 u011779875 的回复:我没有看你程序的逻辑  第一点 我严重怀疑你的程序是会有很多警告的吧 对于警告  这个东西 最好全不干掉 要不然 你终有一天会吃大亏的  你主函数是这样调用的吗 luxian p; push(p);   第二点 你要记住 函数传参 永远是值的一份拷贝  就算是地址也是一份拷贝 只不过你可以对该地址指向的地方 进行修改值 嗯！确实有好多警告，以后一定注意。顺便问一下结构体指针中存在int变量，当这个指针为实参传值时在被调函数中改变int变量的值时，当函数结束后，其int改变的值会不会在主函数中有所保存。

引用 2 楼 user-4 的回复:没错阿！刚测试了阿！值反生改变了阿！ 传地址进去，修改地址上的内容啊！没错的。。楼主再试试！  #include <stdlib.h> #include <stdio.h> #include <string.h>  #define MAXE 10 typedef struct name {     char build[MAXE][21];     int top; }luxian;  int push(luxian *lu2) {     char name[21];     if(lu2->top==MAXE-1)     {            return(0);     }        printf("iput address\n");     scanf("%s",name);     lu2->top++;     printf("%d\n",lu2->top);     strcpy(lu2->build[lu2->top],name);     return(1); }   int main(void) {     luxian a = {0};      a.top = 2;     printf(" %d \n", a.top);     push( &a);      printf(" %s \n", a.build[a.top]);     printf(" %d \n", a.top); }  结果：  2  iput address zhongguo 3  zhongguo   3    这上面上面和我的有所出入，我写的程序的一部分是下面的麻烦大师看下  #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXE 10 typedef struct name { 	char build[MAXE][21]; 	int top; }luxian; luxian * create(void); int push(luxian *lu2); char * pop(luxian *lu3); int sempty(luxian *lu4); int main() { 	int i;//判断入栈是否成功 	char *zu[21];//用来存储出栈时的所有元素 	char *p;//用来接收出栈元素的那个元素 	luxian *lu=NULL; 	lu=create(); 	i=push(lu); 	printf("%d\n",lu->top); 	printf("%d\n",i); 	strcpy(*(zu[1]),pop(lu)); 	printf("%d\n",i);  } luxian* create(void) { 	luxian *luxian1; 	luxian1=(luxian *)malloc(sizeof(luxian)); 	luxian1->build[MAXE][21]=0; 	luxian1->top=-1; 	return(luxian1); }  int push(luxian *lu2) { 	char name[21]; 	if(lu2->top==MAXE-1) 	{ 		return(0); 	} 	printf("请输入地址\n"); 	scanf("%s",name); 	lu2->top++; 	printf("%d\n",lu2->top); 	strcpy(lu2->build[lu2->top],name); 	return(1); } char * pop(luxian *lu3) { 	char *p; 	printf("%s\n",lu3->build[lu3->top]);  	if(sempty(lu3)) 	{ 		printf("栈为空了\n"); 		return; 	} 	else 	{ 		p=(char *)malloc(21*sizeof(char)); 		printf("%s\n",lu3->build[lu3->top]); 		strcpy(*p,lu3->build[lu3->top]); 		printf("dazhele1\n"); 		lu3->top--; 		return(*p);   	} }  int sempty(luxian *lu4) { 	if(lu4->top==-1) 	{ 		return 0; 	} 	else 	{ 		return 1; 	} }   主要差别是我的传的是指针，而不是数组的名字。定义路线变量的时候用的是指针。