Question: 程序员面试宝典上的little-endian系统问题

引用 1 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？程序运行的结果也是这样。现在是想搞清楚为什么会有这个结果。

struct里总共有9个bit，所以2字节大。b1是0～4bit位，b2是7，8比特位  memcpy了EM，内存里就是 01000101（E）01001101 （M）  因为是小字节序，所以 15～0 bit位为 0100110101000101 红色b1为5，绿色b2补位（有符号）后，就是-2

引用 2 楼 u013539260 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？程序运行的结果也是这样。现在是想搞清楚为什么会有这个结果。[/quote] 理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

每套编译器的实现并不相同，你可以找找C语言标准看看，哪些行为是未定义的。 这个msvc的规则，一个变量可以跨字节存储：https://msdn.microsoft.com/en-us/library/yszfawxh.aspx


Question: socket 通信的问题（errrno 17, File Exists)

引用 8 楼 zhao4zhong1 的回复:对socket，我只用过recv,没用过read+1

引用 7 楼 biliky 的回复:[quote=引用 6 楼 s120922718 的回复:] 是采用的select吗，select成功以后是要对socket数组遍历的啊 read的时候传递的应该是建立连接的那个socket吧，你的nSockfd是什么  nTcpSelect是一个自定义的函数，该函数里调用了系统的select，这个自定义函数主要就是判断参数中nSockfd是否就绪，是否有数据可读。如果是，则往下执行read，进行读操作。 我的问题是，既然执行到read了，socket应该是有数据可读了，为什么读数据时又报File Exits的错误呢？[/quote]  当recv的参数有些为NULL的时候，recv和read在有些情况下可以理解成是一样的。 传递给read的socket fd是accept成功之后返回的fd，你的nSocketfd是什么

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

引用 19 楼 biliky 的回复:好像跟多次读操作有关。客户端连续三次write，服务端也是连续三次read，第一次read正常获得数据，就是第二次read报错。 三次write可能只需要一个read, tcp是流哦。

文件是不是真的存在呢

c方式，反复设置同一个ip时系统会抛出以下信息 关闭重新连接

参考MSDN98\SAMPLES\VC98\SDK\NETDS\WINSOCK\SIMPLE\IOCTL.C /******************************************************************************\ * ioctl.c - TCP server * *       This is a part of the Microsoft Source Code Samples. *       Copyright 1996-1997 Microsoft Corporation. *       All rights reserved. *       This source code is only intended as a supplement to *       Microsoft Development Tools and/or WinHelp documentation. *       See these sources for detailed information regarding the *       Microsoft samples programs. \******************************************************************************/    #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <stdlib.h> #include <stdio.h> #include <string.h>  #define DEFAULT_PORT 5001  int ReadAndEcho(SOCKET , char *,int ) ; int WriteMessage(SOCKET , char *,int ) ;  void Usage(char *progname) {     fprintf(stderr,"Usage\n%s -e [endpoint] -i [interface]\n",         progname);     fprintf(stderr,"Where:\n");     fprintf(stderr,"\tendpoint is the port to listen on\n");     fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");     fprintf(stderr," to bind to\n");     fprintf(stderr,"Defaults are 5001 and INADDR_ANY\n");     WSACleanup();     exit(1); } int main(int argc, char **argv) {      char Buffer[128];     char *interface= NULL;     unsigned short port=DEFAULT_PORT;     int fromlen;     int i, ioctl_opt =1;     struct sockaddr_in local, from;     WSADATA wsaData;     SOCKET listen_socket, msgsock;     fd_set readfds, writefds, exceptfds;      /* Parse arguments */     if (argc >1) {         for(i=1;i <argc;i++) {             if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) {                 switch(tolower(argv[i][1])) {                     case 'i':                         interface = argv[++i];                         break;                     case 'e':                         port = atoi(argv[++i]);                         break;                     default:                         Usage(argv[0]);                         break;                 }             }             else                 Usage(argv[0]);         }     }          if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {         fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());         WSACleanup();         return -1;     }          if (port == 0){         Usage(argv[0]);     }      //     // The fd sets should be zeroed out before using them to prevent errors.     FD_ZERO(&readfds);     FD_ZERO(&writefds);     FD_ZERO(&exceptfds);     memset(Buffer,0,sizeof(Buffer));      local.sin_family = AF_INET;      //     // bind to specific interface if desired.      local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface);      /*      * Port MUST be in Network Byte Order      */     local.sin_port = htons(port);      listen_socket = socket(AF_INET, SOCK_STREAM,0); // TCP socket     if (listen_socket == INVALID_SOCKET){         fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());         WSACleanup();         return -1;     }     //     // bind() associates a local address and port combination with the     // socket just created.      if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) )         == SOCKET_ERROR) {         fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());         WSACleanup();         return -1;     }      //     // start listening on the socket for incoming connections     //     if (listen(listen_socket,5) == SOCKET_ERROR) {         fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());         WSACleanup();         return -1;     }     printf("%s: Listening on port %d\n",argv[0],port);      //     // Set the socket to non-blocking mode.     //     if (ioctlsocket(listen_socket,FIONBIO,&ioctl_opt) == SOCKET_ERROR) {         fprintf(stderr,"ioctlsocket failed %d\n",WSAGetLastError());         WSACleanup();         return -1;     }     //     // The structure of the loop below is very simple. We only accept one     // connection at a time. As soon as another client connects, we     // disconnect the first one, and start talking to the new client.     // All this server does is to echo the data received on the socket     // back to the client.     //     // This is not a very realistic server, but it does serve to show that     // select() does not scale very well on win32. If we were dealing     // with more than one client, we would have to have a list of sockets     // that are in each fdset to be able to check them when select()     // returns.     //     while(1) {          //         // A socket in the listen() state becomes ready to read when a         // client connects to it. An accept() will complete without         // blocking.         // Since select sets the sockets that are ready to be read from or         // written to, we have to include listen_socket in the fdset each time         // through the loop.         //          FD_SET(listen_socket,&readfds);          i = select(0,&readfds,&writefds,&exceptfds,NULL);         if (i == SOCKET_ERROR) {             fprintf(stderr,"select failed %d\n",WSAGetLastError());         }         if (i==0){             fprintf(stderr,"Select returned no fds ready\n");         }          if (FD_ISSET(listen_socket, &readfds)){             //             // close the previous client socket.             // We must also clear it from the fdset to prevent select()             // from failing.             // 			closesocket(msgsock); 			FD_CLR(msgsock,&readfds); 			FD_CLR(msgsock,&writefds); 			fromlen = sizeof(from); 			msgsock= accept(listen_socket,(struct sockaddr*)&from,&fromlen); 			if (msgsock == INVALID_SOCKET) { 				fprintf(stderr,"accept failed %d\n",WSAGetLastError()); 				WSACleanup(); 				return -1; 			} 			FD_SET(msgsock,&writefds); 			FD_SET(msgsock,&readfds); 			continue; 		} 		if (FD_ISSET(msgsock,&readfds) ) { 			// 			// socket is ready to read, i.e., there is data on the socket. 			// 			if (ReadAndEcho(msgsock,Buffer,sizeof(Buffer))<0) { 				fprintf(stderr,"terminating connection\n"); 				FD_CLR(msgsock,&readfds); 				FD_CLR(msgsock,&writefds); 				closesocket(msgsock); 				continue; 			} 		} 		if (FD_ISSET(msgsock,&writefds) ){ 			if (WriteMessage(msgsock,Buffer,sizeof(Buffer)) <=0) { 				fprintf(stderr,"terminating connection\n"); 				FD_CLR(msgsock,&readfds); 				FD_CLR(msgsock,&writefds); 				closesocket(msgsock); 				continue;             }         }         FD_SET(msgsock,&writefds);         FD_SET(msgsock,&readfds);     } } int ReadAndEcho(SOCKET insock, char *Buffer,int size) {     int rc;      rc = recv(insock,Buffer,size,0);      if (rc == SOCKET_ERROR) {         fprintf(stderr,"recv() failed with error %d\n",WSAGetLastError());           return -1;     }     if (rc ==0) {         fprintf(stderr,"Connection closed by client\n");         return 0;     }     printf("Received [%s] from client\n",Buffer);     return rc; } int WriteMessage(SOCKET outsock, char *Buffer,int size) {     int rc;     int lasterr;      printf("Sending [%s] to client\n",Buffer);     rc = send(outsock,Buffer,size, 0);      if (rc == SOCKET_ERROR) {       lasterr = WSAGetLastError();       if (lasterr == WSAEWOULDBLOCK)         return 0;       else {         fprintf(stderr,"send() failed with error %d\n",lasterr);             return -1;       }     }     if (rc ==0) {         fprintf(stderr,"Connection closed by client\n");     }     return rc; }

引用 15 楼 mujiok2003 的回复:[quote=引用 12 楼 mujiok2003 的回复:] read不应该返回负数。 返回-1为出错。   nRead的类型是什么？[/quote]  nRead 当然是int类型。     引用 8 楼 zhao4zhong1 的回复:对socket，我只用过recv,没用过read  试过了，用recv效果一样，赵老师，你可是“千万行里改关键源码在弹指瞬间”啊，就等你的弹指瞬间啊。。。。

无码无真相.

引用 2 楼 luciferisnotsatan 的回复:贴代码  read函数能返回一个文件已存在（File Exists）错误？ 修正下 read函数返回失败，errno为17（文件已存在），这有可能么？ read是从文件里面读，怎么会报文件存在这个错误。

贴代码  read函数能返回一个文件已存在（File Exists）错误？

需要用抓包软件排错的话就用。

引用 12 楼 mujiok2003 的回复:read不应该返回负数。 返回-1为出错。   nRead的类型是什么？

试试  unlink

怎么不会返回负数呢？        Upon successful completion, read(), pread(), and readv() return a       non-negative integer indicating the number of bytes actually read.       Otherwise, the functions return -1 and set errno to indicate the       error.

read不应该返回负数。

以下内容摘自man 2 recv命令的输出： RETURN VALUE These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.    ERRORS These are some standard errors generated by the socket layer. Additional errors may be generated and returned from the underlying protocol modules; see their manual pages.  EAGAIN  The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.  EBADF  The argument s is an invalid descriptor.  ECONNREFUSED  A remote host refused to allow the network connection (typically because it is not running the requested service).  EFAULT  The receive buffer pointer(s) point outside the process's address space.  EINTR  The receive was interrupted by delivery of a signal before any data were available.  EINVAL  Invalid argument passed.  ENOMEM  Could not allocate memory for recvmsg.  ENOTCONN  The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).  ENOTSOCK  The argument s does not refer to a socket.

在线等各位大牛的高招啊。。。

引用 8 楼 zhao4zhong1 的回复:对socket，我只用过recv,没用过read  赵老师，recv和read有麻区别啊？难道你在用recv中没遇到过File Exists的情况？


Question: 自学者求助，请解释一下一段代码

因为一个循环i只加一次 所以在后面的if语句才用i++

给您一个赞

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

对啊。假如作者一早这样写我就懂了

只是一个循环递增，可以不放在里面，可以单独拿出来，i++放在两个if语句的后面

经一楼一讲解我就利马明白了，开头我以为wile语句可以自动扫描i的值，走进误区了，现在一下子明白过来了，谢谢

楼主   发表于： 2015-01-30 23:18:05       int main(void)  {    int i = 0;                     /* Buffer index               */    while(buffer[i] != '\0')    {      if(isalpha(buffer[i]))      // i在单次循环末尾要递增，要是在这里开始++  那么if(isdigit(buffer[i++])) i++ 单次循环i就会加两次，所以只能在单次循环的最后一个i的时++  这一句i不变        num_letters++;             /* Increment letter count     */      if(isdigit(buffer[i++]))//这个为什么要自加呢，为什么不跟上一句的if一样不用自加哦？       num_digits++;              /* Increment digit count      */    }


Question: 请教一个函数声明和定义中的P()的问题

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

#	define	P0()				(void) #	define	P1(x, a)			(a) #	define	P2(x, a, b)			(a, b) #	define	P3(x, a, b, c)			(a, b, c) #	define	P4(x, a, b, c, d)		(a, b, c, d)	 #	define	P5(x, a, b, c, d, e)		(a, b, c, d, e) #	define	P6(x, a, b, c, d, e, f)		(a, b, c, d, e, f) #	define	P7(x, a, b, c, d, e, f, g)	(a, b, c, d, e, f, g) #	define	P8(x, a, b, c, d, e, f, g, h)	(a, b, c, d, e, f, g, h)  就是这个定义，其实算起来，等替换完成，void gsm_destroy P1((S), gsm S)和void gsm_destroy（gsm S）就是一回事了，因为会被后者替换掉，我的意思是，我不明白这个宏放在这是有什么意义。

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。


Question: 写了个代码，不知道哪里错了，求高手更正。

你返回了局部变量数组，那么返回的是自定义函数xx中数组的首地址，那么当该函数调用结束后，数据的那部分空间里的数据就是未定义的，因为函数调用结束后，栈空间会被系统自动释放的。

这位兄弟加油，基本功要练扎实。

引用 5 楼 ChemistYH 的回复:顺便问一下，我看完了谭浩强的那本书，想更深入的学习C语言，想先学会编个俄罗斯方块那样的小游戏，不知道看看什么书好。  学完C语言就开发图形程序有些困难哦，要学的东西很多啊。学完C开始做算法倒是足够了。  SDL图形库，比较简单，用处也很广，如果你确实对图形程序很感兴趣，可以学习一下：https://zh.wikipedia.org/zh-cn/SDL

输入错误，应该是C Primer Plus.

C Prime Plus，不深入但全面。C专家编程，c语言陷阱与缺陷。 做游戏，我不了解。 提供一个C语言的俄罗斯方块代码： 转载：http://tieba.baidu.com/f?kz=1090419809 从效果图来看，还不错。 运行发现BUG太致命。你可以做个更好的。  PS:答主也在学习C Prime Plus。最近刚看到存储变量……

引用 4 楼 ChemistYH 的回复:奥，也就是说，调用子函数结束后，那个数组就不存在了。可有些元素还是正确的，这是不是就牵扯到存储方式的问题了。  C语言有个标准文档，那里面规定了哪些操作会有什么结果，也说明了哪些操作的结果是未知的（正确来说叫“未定义”）。 引用一个已经超出作用域的变量，然后获取其值的行为是未定义的，可能那个地址里面还是放着正确的数据，也可能已经变成其他数据了。

变量都有自己的作用域，超过了就无效了。 返回函数中在栈上建立的数组的指针这个做法是错误的。

#include<stdio.h> #include<stdlib.h> int *xx() { int i; int *a=(int*)malloc(20*sizeof(int)); for(i=0;i<20;i++) { a[i]=8; } return a; } int main() { int *p,i; p=xx(); for(i=0;i<20;i++,p++) { printf("%d",*p); } p-=20; free(p); printf("\n"); }

因为变量存在作用域，数组a在函数int * xx()中，即使用指针指向它，函数调用结束，编译器还是自动释放数组占用的内存。 可以采用以下2个办法解决函数中建立数组的过程： 1，声明静态变量，int * xx()中：static int a[20]; 2，采用动态分配内存，头文件添加：#include<stdlib.h>，创建数组用以下代码：int *a=(int*)malloc(20*sizeof(int);在函数中不适用free()释放，在主函数结尾添加:free(p)，释放数组占用内存。  相关知识：变量存储的作用域，动态分配内存。可在书本进行学习。  方法一的源代码直接添加即可。 方法二源代码：


Question: 电话号码分段显示

无满意答案...............

引用 3 楼 zhao4zhong1 的回复:作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。 //13812341234 显示成 138-1234-1234 #include <stdio.h> char s[20]="13812341234"; int main() {     printf("%.*s-%.*s-%.*s",               3,s,                    4,s+3,                         4,s+3+4);     return 0; } //138-1234-1234   顺便学习学习

把特定前缀放入数组中，然后匹配，作电话处理 其他作手机处理

%c%c%c-%c%c%c%c

Update


Question: 如何理解C语言结构体指针相等（单链表程序）

引用 9 楼 liuchang910781261 的回复:[quote=引用 3 楼 xionggch 的回复:] h->name[0]='\0';//把表头指针的数据域置空         h->link=NULL;   //把表头节点的链域也置空         p=h;            //这个说明了什么??????????????????????? 指针p指向头节点(链表头)   p->link=s;//把s的地址赋给了p的链域，这样p就指向了s //这里把s的地址赋给p指向的节点中指针变量link，即把s节点链接到p指向的节点                 printf("请输入第%d个人的姓名\n",i);                 scanf("%s",s->name);                 s->link=NULL;                 p=s;//同理???????????????????????????? 把p指针指向s节点 这也就是我不能理解的地方，为什么指针相同就是指向它（按我的想法，如果指针相同，那不是同一个地址吗？何来指向谁的问题？），请大神赐教！[/quote] 指针---即指针变量，它的值就是指针指向的地址

谢谢大神指点

struct node *p,*h,*s;//*h保存表头节点的指针                          //*p指向当前节点的前一个节点                          //*s指向当前节点 他们三个是一样的，关键是你希望他们在程序中扮演什么角色？ 比如p和s的角色就可以互换。 先看懂一道非常简单的程序，然后再回头想想，对你有大溢出。 ps：添加断点调试一遍是最快的学习方式。

引用 10 楼 zf97576419 的回复:[quote=引用 8 楼 liuchang910781261 的回复:] [quote=引用 2 楼 zf97576419 的回复:] 可能是我技术不精，说错请纠正，谢谢，下面是个人见解。 首先  struct node *p, //*p指向当前节点的前一个节点              *h, //*h保存表头节点的指针              *s; //*s指向当前节点                         我印象中我使用链表的时候 一般都是 头节点，当前节点，尾节点。至于你这里面提到的“当前节点的前一个节点”是做什么用的感觉不对吧，还是说你的注释错了。。  h->name[0]='\0';//把表头指针的数据域置空  h->link=NULL;   //把表头节点的链域也置空  p=h;            //这个说明了什么???????????????????????  这个地方如果把你的p理解成当前节点的话 应该就能理解了吧，但是前一个节点，这肯定不对啊。。  p->link=s;//把s的地址赋给了p的链域，这样p就指向了s printf("请输入第%d个人的姓名\n",i); scanf("%s",s->name);  s->link=NULL;   p=s;//同理????????????????????????????  这个如果按照我上面说的理解应该是没没问题，如果是当前节点的前一个节点就有问题了。。 读你的代码感觉你声明的“p”应该是代码当前节点的意思。 个人理解，不对请纠正。谢谢 小弟本身就是一知半解，后面的注释都是书上的，小弟没有做任何改动~~~[/quote]  个人见解是不是注释错误了，如果按照我说的，把p理解成为当前节点，你应该就能理解了吧。日常使用中一般会使用到头节点、当前节点、和尾节点。[/quote] 大神：按你说的，相对容易理解一点，谢谢大神指点~~~

引用 8 楼 liuchang910781261 的回复:[quote=引用 2 楼 zf97576419 的回复:] 可能是我技术不精，说错请纠正，谢谢，下面是个人见解。 首先  struct node *p, //*p指向当前节点的前一个节点              *h, //*h保存表头节点的指针              *s; //*s指向当前节点                         我印象中我使用链表的时候 一般都是 头节点，当前节点，尾节点。至于你这里面提到的“当前节点的前一个节点”是做什么用的感觉不对吧，还是说你的注释错了。。  h->name[0]='\0';//把表头指针的数据域置空  h->link=NULL;   //把表头节点的链域也置空  p=h;            //这个说明了什么???????????????????????  这个地方如果把你的p理解成当前节点的话 应该就能理解了吧，但是前一个节点，这肯定不对啊。。  p->link=s;//把s的地址赋给了p的链域，这样p就指向了s printf("请输入第%d个人的姓名\n",i); scanf("%s",s->name);  s->link=NULL;   p=s;//同理????????????????????????????  这个如果按照我上面说的理解应该是没没问题，如果是当前节点的前一个节点就有问题了。。 读你的代码感觉你声明的“p”应该是代码当前节点的意思。 个人理解，不对请纠正。谢谢 小弟本身就是一知半解，后面的注释都是书上的，小弟没有做任何改动~~~[/quote]  个人见解是不是注释错误了，如果按照我说的，把p理解成为当前节点，你应该就能理解了吧。日常使用中一般会使用到头节点、当前节点、和尾节点。

引用 3 楼 xionggch 的回复:h->name[0]='\0';//把表头指针的数据域置空         h->link=NULL;   //把表头节点的链域也置空         p=h;            //这个说明了什么??????????????????????? 指针p指向头节点(链表头)   p->link=s;//把s的地址赋给了p的链域，这样p就指向了s //这里把s的地址赋给p指向的节点中指针变量link，即把s节点链接到p指向的节点                 printf("请输入第%d个人的姓名\n",i);                 scanf("%s",s->name);                 s->link=NULL;                 p=s;//同理???????????????????????????? 把p指针指向s节点 这也就是我不能理解的地方，为什么指针相同就是指向它（按我的想法，如果指针相同，那不是同一个地址吗？何来指向谁的问题？），请大神赐教！

引用 2 楼 zf97576419 的回复:可能是我技术不精，说错请纠正，谢谢，下面是个人见解。 首先  struct node *p, //*p指向当前节点的前一个节点              *h, //*h保存表头节点的指针              *s; //*s指向当前节点                         我印象中我使用链表的时候 一般都是 头节点，当前节点，尾节点。至于你这里面提到的“当前节点的前一个节点”是做什么用的感觉不对吧，还是说你的注释错了。。  h->name[0]='\0';//把表头指针的数据域置空  h->link=NULL;   //把表头节点的链域也置空  p=h;            //这个说明了什么???????????????????????  这个地方如果把你的p理解成当前节点的话 应该就能理解了吧，但是前一个节点，这肯定不对啊。。  p->link=s;//把s的地址赋给了p的链域，这样p就指向了s printf("请输入第%d个人的姓名\n",i); scanf("%s",s->name);  s->link=NULL;   p=s;//同理????????????????????????????  这个如果按照我上面说的理解应该是没没问题，如果是当前节点的前一个节点就有问题了。。 读你的代码感觉你声明的“p”应该是代码当前节点的意思。 个人理解，不对请纠正。谢谢 小弟本身就是一知半解，后面的注释都是书上的，小弟没有做任何改动~~~

理解和讨论之前请先学会如何观察！

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

p=h;            //这个说明了什么??????????????????????? p=s;            //同理????????????????????????????  都是 p 保存当前结点，用以连接下一个新的结点，如下图

#include<stdio.h> #include<malloc.h> #define N 10 struct node {     char name[20];    //数据域     struct node *link;//指针域 };  //此函数创建了一个链表（包含一个头节点和其他n个带数据的节点） struct node *creat(int n)//该函数的返回值是一个指向node类型结构体的指针变量 {     struct node *p,*h,*s;//*h保存表头节点的指针                          //*p指向当前节点的前一个节点                          //*s指向当前节点     int i;     if((h=(struct node *)malloc(sizeof(struct node)))==NULL)     {                    //分配空间并检测         printf("不能分配内存空间");         exit(0);     }     else     {         h->name[0]='\0';//把表头指针的数据域置空         h->link=NULL;   //把表头节点的链域也置空         p=h;            //p指向头节点         for(i=0;i<n;i++)         {             if((s=((struct node *)malloc(sizeof(struct node))))==NULL)             {                 printf("不能分配内存空间");                 exit(0);             }             else             {                 p->link=s;//把s的地址赋给了p的链域，这样p的下一个节点就是s。                 printf("请输入第%d个人的姓名\n",i);                 scanf("%s",s->name);                 s->link=NULL;                 p=s;//p指向s节点，为连接下一个节点做准备             }         }     }     return (h); } void main() {     int number;     struct node *head;     number=N;     head=creat(number); }

画个图来理解一下


Question: 菜鸟求解答，x509的问题

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

(unsigned char **)&certBuf, len)\ -------->这个不能取地址 虽然不知道你的函数接口，但是试试 (unsigned char **)certBuf, len)\


Question: 八皇后问题的递归算法，为什么能输出好几个结果？

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

引用 4 楼 baidu_23849565 的回复:for (int col=1;col<=Queen;++col)         {             column[num] = col;             if (IsValid(num))             {                 EightQueen(num+1);             }         } for循环中一行一行遍历了所有可能的情况，第num行不冲突时，开始遍历下一行， 直到num=queen，输出，之后回到上一行继续遍历  呃…这个解释我…努力去理解

引用 3 楼 q3733353520 的回复:因为 col 和  num 没实质性的算法关系，所以会有很多层递归，每层递归直到num=5结束  哇，谢谢你的点拨！感觉懂了

/**                                                                               * The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.  *                                                                                * Given an integer n, return all distinct solutions to the n-queens puzzle.      *                                                                                * Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.  *                                                                                * For example,                                                                   *     There exist two distinct solutions to the 4-queens puzzle:                 *                                                                                *     [                                                                          *      [".Q..",  // Solution 1                                                   *       "...Q",                                                                  *       "Q...",                                                                  *       "..Q."],                                                                 *                                                                                *      ["..Q.",  // Solution 2                                                   *       "Q...",                                                                  *       "...Q",                                                                  *       ".Q.."]                                                                  *     ]                                                                          */                                                                                #include <stdio.h>                                                               #include <stdlib.h>                                                              #include <string>                                                                #include <vector>                                                                using namespace std;                                                                                void print_solves(vector<vector<string> > &vec) {                                    printf("[\n");                                                                   for (int i = 0; i < vec.size(); ++i) {                                               printf(" [\n");                                                                  for (int j = 0; j < vec[i].size(); ++j) {                                            printf("%s\n", vec[i][j].c_str());                                           }                                                                                printf(" ]\n");                                                              }                                                                                printf("]\n");                                                               }                                                                                class Solution {                                                                     public:                                                                              int diff(int x, int y) {                                                             return x > y ? x - y : y - x;                                                }                                                                                int succ(int index) {                                                                for (int i = 1; i < index; ++i) {                                                    if (array_[index] == array_[i] || (diff(index, i) == diff(array_[index], array_[i]))) {                     return 0;                                                                    }                                                                            }                                                                                return 1;                                                                    }                                                                                void solve_n_queens(int index) {                                                     if (index > n_) {                                                                    vector<string> vec;                                                              for (int i = 0; i < n_; ++i) {                                                       string str(n_, '.');                                                             str[array_[i + 1] - 1] = 'Q';                                                    vec.push_back(str);                                                          }                                                                                result_.push_back(vec);                                                          return;                                                                      }                                                                                for (int i = 1; i <= n_; ++i) {                                                      array_[index] = i;                                                               if (succ(index)) {                                                                   solve_n_queens(index + 1);                                                   }                                                                            }                                                                            }                                                                                vector<vector<string> > solveNQueens(int n) {                                        n_ = n;                                                                          array_.resize(n + 1, 0);                                                         solve_n_queens(1);                                                               return result_;                                                              }                                                                                private:                                                                             int n_;                                                                          vector<int> array_;                                                              vector<vector<string> > result_;                                         };                                                                                int main(int argc, char **argv) {                                                    int i = 8;                                                                       if (argc == 2) {                                                                     i = atoi(argv[1]);                                                           }                                                                                Solution s;                                                                      //for (int i = 0; i < 9; ++i) {                                                  vector<vector<string> > ret = s.solveNQueens(i);                                 printf("%d size:%d.\n", i, ret.size());                                          //}                                                                              print_solves(ret);                                                               return 0;                                                                    }

引用 1 楼 baidu_23849565 的回复:for (int col=1;col<=Queen;++col)         {             column[num] = col;             if (IsValid(num))             {                 EightQueen(num+1);             }         } 注意for循环  还是没懂OTL……可否详细讲一下？


Question: 新人学习C，两个问题卡了很久……

引用 18 楼 sholber 的回复:好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()

引用 25 楼 my_live_123 的回复:[quote=引用 24 楼 sholber 的回复:] [quote=引用 22 楼 my_live_123 的回复:] [quote=引用 20 楼 sholber 的回复:] [quote=引用 19 楼 my_live_123 的回复:] [quote=引用 18 楼 sholber 的回复:] 好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()[/quote]  你说得不对。 1，C99支持所规定的形式，第一种是 int main (int argc, char * argv []) {/* ... */} 或者其等价形式 int main (int argc, char * * argv) {/* ... */} 也支持没有参数的形式 int main (void) {/* ... */} 因为C99要求使用原型，所以它决不会规定你说的那种K&R形式： int main () {/* ... */} 还有，C99也允许C的实现规定的其它形式，比如 int main (int argc, char * * argv, char * env, char * apple) {/* ... */} 如果是在独立式执行环境中，main函数不是必需的。  2，main有一个特殊的地方 ，C99规定，如果main函数没有return语句，则默认返回0。  3，关于main函数的返回类型。在早期的C中，如果一个文件作用域的标识符在声明时没有类型指定符，则默认的类型是int。因此， main (void) {/* ... */} 意味着 int main (void) {/* ... */} 但是新标准禁止这种没有类型指定符的做法，但很多C的实现仍然可以接受。无论如何，C语言在历史上从来没有将main函数的返回类型指定为void，省略类型指定符int并不意味着它可以，或者就是void。[/quote]  咱俩的标准还不是一个了？ The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; 9)or in some other implementation-defined manner. 然后页低还有个标注： Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv, and so on. 因此，ssize_t也能用做返回值的声明，char *argv[] 等价于char **argv，要是算起来有6种写法。  ssize_t main(void){} int main(void){} int main(int argc, char *argv[]){} int main(int argc, char **argv){} ssize_t main(int argc, char *argv[]){} ssize_t main(int argc, char **argv){}  要是自己再定义typedef，又有多少种呢？你钻牛角了，我承认上面main中少了void   int main (int argc, char * * argv, char * env)  Because  ISO  C  specifies  that  the main function  be  written  with  two  arguments,  and because  this  third argument  provides  no  benefit  over  the  global  variable environ, POSIX.1  specifies  that environ should  be  used  instead  of  the  (possible)  third argument.  Access to  specific  environment  variables  is  normally  through  the getenv and putenv functions 最后2.3条观点是对的  说明一点：入口函数和编译器也有很大关系。gcc编译时使用-e参数可以指定自己的的入口点函数，换言之，源程序并不是必须以main入口点！不过很少使用。   [/quote]  我想到了这个方面，但没想到你会把它提出来： singed main (signed a, char * * b) {/* ... */} 这都没问题。这样看来，是你在钻牛角尖啦。[/quote] 切，明明是你自己非要把char *argv[]等价于char **argv单独拉出来算一种情况，自己去看你的回复！斗这嘴没啥意思[/quote]  有意思！当然有意思了！ 我的目标是积分超过赵老湿，然后，就不再上CSDN了。因为我还有很多正事要做哩。 你真豪爽，我开始喜欢你了。 # define o int #define k main  o k (void) ??< printf ("你真豪爽，嚓！"); ??>

引用 24 楼 sholber 的回复:[quote=引用 22 楼 my_live_123 的回复:] [quote=引用 20 楼 sholber 的回复:] [quote=引用 19 楼 my_live_123 的回复:] [quote=引用 18 楼 sholber 的回复:] 好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()[/quote]  你说得不对。 1，C99支持所规定的形式，第一种是 int main (int argc, char * argv []) {/* ... */} 或者其等价形式 int main (int argc, char * * argv) {/* ... */} 也支持没有参数的形式 int main (void) {/* ... */} 因为C99要求使用原型，所以它决不会规定你说的那种K&R形式： int main () {/* ... */} 还有，C99也允许C的实现规定的其它形式，比如 int main (int argc, char * * argv, char * env, char * apple) {/* ... */} 如果是在独立式执行环境中，main函数不是必需的。  2，main有一个特殊的地方 ，C99规定，如果main函数没有return语句，则默认返回0。  3，关于main函数的返回类型。在早期的C中，如果一个文件作用域的标识符在声明时没有类型指定符，则默认的类型是int。因此， main (void) {/* ... */} 意味着 int main (void) {/* ... */} 但是新标准禁止这种没有类型指定符的做法，但很多C的实现仍然可以接受。无论如何，C语言在历史上从来没有将main函数的返回类型指定为void，省略类型指定符int并不意味着它可以，或者就是void。[/quote]  咱俩的标准还不是一个了？ The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; 9)or in some other implementation-defined manner. 然后页低还有个标注： Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv, and so on. 因此，ssize_t也能用做返回值的声明，char *argv[] 等价于char **argv，要是算起来有6种写法。  ssize_t main(void){} int main(void){} int main(int argc, char *argv[]){} int main(int argc, char **argv){} ssize_t main(int argc, char *argv[]){} ssize_t main(int argc, char **argv){}  要是自己再定义typedef，又有多少种呢？你钻牛角了，我承认上面main中少了void   int main (int argc, char * * argv, char * env)  Because  ISO  C  specifies  that  the main function  be  written  with  two  arguments,  and because  this  third argument  provides  no  benefit  over  the  global  variable environ, POSIX.1  specifies  that environ should  be  used  instead  of  the  (possible)  third argument.  Access to  specific  environment  variables  is  normally  through  the getenv and putenv functions 最后2.3条观点是对的  说明一点：入口函数和编译器也有很大关系。gcc编译时使用-e参数可以指定自己的的入口点函数，换言之，源程序并不是必须以main入口点！不过很少使用。   [/quote]  我想到了这个方面，但没想到你会把它提出来： singed main (signed a, char * * b) {/* ... */} 这都没问题。这样看来，是你在钻牛角尖啦。[/quote] 切，明明是你自己非要把char *argv[]等价于char **argv单独拉出来算一种情况，自己去看你的回复！斗这嘴没啥意思

引用 22 楼 my_live_123 的回复:[quote=引用 20 楼 sholber 的回复:] [quote=引用 19 楼 my_live_123 的回复:] [quote=引用 18 楼 sholber 的回复:] 好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()[/quote]  你说得不对。 1，C99支持所规定的形式，第一种是 int main (int argc, char * argv []) {/* ... */} 或者其等价形式 int main (int argc, char * * argv) {/* ... */} 也支持没有参数的形式 int main (void) {/* ... */} 因为C99要求使用原型，所以它决不会规定你说的那种K&R形式： int main () {/* ... */} 还有，C99也允许C的实现规定的其它形式，比如 int main (int argc, char * * argv, char * env, char * apple) {/* ... */} 如果是在独立式执行环境中，main函数不是必需的。  2，main有一个特殊的地方 ，C99规定，如果main函数没有return语句，则默认返回0。  3，关于main函数的返回类型。在早期的C中，如果一个文件作用域的标识符在声明时没有类型指定符，则默认的类型是int。因此， main (void) {/* ... */} 意味着 int main (void) {/* ... */} 但是新标准禁止这种没有类型指定符的做法，但很多C的实现仍然可以接受。无论如何，C语言在历史上从来没有将main函数的返回类型指定为void，省略类型指定符int并不意味着它可以，或者就是void。[/quote]  咱俩的标准还不是一个了？ The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; 9)or in some other implementation-defined manner. 然后页低还有个标注： Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv, and so on. 因此，ssize_t也能用做返回值的声明，char *argv[] 等价于char **argv，要是算起来有6种写法。  ssize_t main(void){} int main(void){} int main(int argc, char *argv[]){} int main(int argc, char **argv){} ssize_t main(int argc, char *argv[]){} ssize_t main(int argc, char **argv){}  要是自己再定义typedef，又有多少种呢？你钻牛角了，我承认上面main中少了void   int main (int argc, char * * argv, char * env)  Because  ISO  C  specifies  that  the main function  be  written  with  two  arguments,  and because  this  third argument  provides  no  benefit  over  the  global  variable environ, POSIX.1  specifies  that environ should  be  used  instead  of  the  (possible)  third argument.  Access to  specific  environment  variables  is  normally  through  the getenv and putenv functions 最后2.3条观点是对的  说明一点：入口函数和编译器也有很大关系。gcc编译时使用-e参数可以指定自己的的入口点函数，换言之，源程序并不是必须以main入口点！不过很少使用。   [/quote]  我想到了这个方面，但没想到你会把它提出来： singed main (signed a, char * * b) {/* ... */} 这都没问题。这样看来，是你在钻牛角尖啦。

引用 7 楼 Newbeeskywrc 的回复:引用 5 楼 www4206 的回复:你写代码的时候，稍微规范下编码习惯请问哪里不规范呢？有没有比较好的关于代码规范方面的资料或书籍？  代码看起来还可以，布局有点问题，注意缩进 代码规范方面的权威书籍是《代码大全》，当初看的时候，边看后背边流冷汗

引用 20 楼 sholber 的回复:[quote=引用 19 楼 my_live_123 的回复:] [quote=引用 18 楼 sholber 的回复:] 好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()[/quote]  你说得不对。 1，C99支持所规定的形式，第一种是 int main (int argc, char * argv []) {/* ... */} 或者其等价形式 int main (int argc, char * * argv) {/* ... */} 也支持没有参数的形式 int main (void) {/* ... */} 因为C99要求使用原型，所以它决不会规定你说的那种K&R形式： int main () {/* ... */} 还有，C99也允许C的实现规定的其它形式，比如 int main (int argc, char * * argv, char * env, char * apple) {/* ... */} 如果是在独立式执行环境中，main函数不是必需的。  2，main有一个特殊的地方 ，C99规定，如果main函数没有return语句，则默认返回0。  3，关于main函数的返回类型。在早期的C中，如果一个文件作用域的标识符在声明时没有类型指定符，则默认的类型是int。因此， main (void) {/* ... */} 意味着 int main (void) {/* ... */} 但是新标准禁止这种没有类型指定符的做法，但很多C的实现仍然可以接受。无论如何，C语言在历史上从来没有将main函数的返回类型指定为void，省略类型指定符int并不意味着它可以，或者就是void。[/quote]  咱俩的标准还不是一个了？ The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; 9)or in some other implementation-defined manner. 然后页低还有个标注： Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv, and so on. 因此，ssize_t也能用做返回值的声明，char *argv[] 等价于char **argv，要是算起来有6种写法。  ssize_t main(void){} int main(void){} int main(int argc, char *argv[]){} int main(int argc, char **argv){} ssize_t main(int argc, char *argv[]){} ssize_t main(int argc, char **argv){}  要是自己再定义typedef，又有多少种呢？你钻牛角了，我承认上面main中少了void   int main (int argc, char * * argv, char * env)  Because  ISO  C  specifies  that  the main function  be  written  with  two  arguments,  and because  this  third argument  provides  no  benefit  over  the  global  variable environ, POSIX.1  specifies  that environ should  be  used  instead  of  the  (possible)  third argument.  Access to  specific  environment  variables  is  normally  through  the getenv and putenv functions 最后2.3条观点是对的  说明一点：入口函数和编译器也有很大关系。gcc编译时使用-e参数可以指定自己的的入口点函数，换言之，源程序并不是必须以main入口点！不过很少使用。

引用 8 楼 Newbeeskywrc 的回复:  我逐渐理解getchar的原理了，但还是没有出现按任意键继续。按任意键继续 是编译器运行时加上去的

会不会是缓存与输入文件混乱呢~~感觉代码很乱的感觉~~

引用 19 楼 my_live_123 的回复:[quote=引用 18 楼 sholber 的回复:] 好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()[/quote]  你说得不对。 1，C99支持所规定的形式，第一种是 int main (int argc, char * argv []) {/* ... */} 或者其等价形式 int main (int argc, char * * argv) {/* ... */} 也支持没有参数的形式 int main (void) {/* ... */} 因为C99要求使用原型，所以它决不会规定你说的那种K&R形式： int main () {/* ... */} 还有，C99也允许C的实现规定的其它形式，比如 int main (int argc, char * * argv, char * env, char * apple) {/* ... */} 如果是在独立式执行环境中，main函数不是必需的。  2，main有一个特殊的地方 ，C99规定，如果main函数没有return语句，则默认返回0。  3，关于main函数的返回类型。在早期的C中，如果一个文件作用域的标识符在声明时没有类型指定符，则默认的类型是int。因此， main (void) {/* ... */} 意味着 int main (void) {/* ... */} 但是新标准禁止这种没有类型指定符的做法，但很多C的实现仍然可以接受。无论如何，C语言在历史上从来没有将main函数的返回类型指定为void，省略类型指定符int并不意味着它可以，或者就是void。

参考 《C/C++学习指南》 http://www.afanihao.cn/c_guide/  的附录“编码规范”  你的教材太老了，函数竟然不写返回值。  引用 7 楼 Newbeeskywrc 的回复:引用 5 楼 www4206 的回复:你写代码的时候，稍微规范下编码习惯请问哪里不规范呢？有没有比较好的关于代码规范方面的资料或书籍？

引用 26 楼 sholber 的回复:[quote=引用 25 楼 my_live_123 的回复:] [quote=引用 24 楼 sholber 的回复:] [quote=引用 22 楼 my_live_123 的回复:] [quote=引用 20 楼 sholber 的回复:] [quote=引用 19 楼 my_live_123 的回复:] [quote=引用 18 楼 sholber 的回复:] 好在你没弄成 void mian ()   #include  <stdio.h> main() { printf("hello, world\n"); }  Figure 7.1 Classic C program When  we  compile  and  run  the  program  in  Figure7.1,  we  see  that  the  exit  code  is random.  If we  compile  the  same  program  on  different  systems,  we  ar elikely  to  get different exit codes, depending on the contents of the stack and register contents at the time that the main function returns:  c99规定两种形式 int main(int argc ,char *argv []) 和 int main()[/quote]  你说得不对。 1，C99支持所规定的形式，第一种是 int main (int argc, char * argv []) {/* ... */} 或者其等价形式 int main (int argc, char * * argv) {/* ... */} 也支持没有参数的形式 int main (void) {/* ... */} 因为C99要求使用原型，所以它决不会规定你说的那种K&R形式： int main () {/* ... */} 还有，C99也允许C的实现规定的其它形式，比如 int main (int argc, char * * argv, char * env, char * apple) {/* ... */} 如果是在独立式执行环境中，main函数不是必需的。  2，main有一个特殊的地方 ，C99规定，如果main函数没有return语句，则默认返回0。  3，关于main函数的返回类型。在早期的C中，如果一个文件作用域的标识符在声明时没有类型指定符，则默认的类型是int。因此， main (void) {/* ... */} 意味着 int main (void) {/* ... */} 但是新标准禁止这种没有类型指定符的做法，但很多C的实现仍然可以接受。无论如何，C语言在历史上从来没有将main函数的返回类型指定为void，省略类型指定符int并不意味着它可以，或者就是void。[/quote]  咱俩的标准还不是一个了？ The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: int main(void) { /* ... */ } or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared): int main(int argc, char *argv[]) { /* ... */ } or equivalent; 9)or in some other implementation-defined manner. 然后页低还有个标注： Thus, int can be replaced by a typedef name defined as int , or the type of argv can be written as char ** argv, and so on. 因此，ssize_t也能用做返回值的声明，char *argv[] 等价于char **argv，要是算起来有6种写法。  ssize_t main(void){} int main(void){} int main(int argc, char *argv[]){} int main(int argc, char **argv){} ssize_t main(int argc, char *argv[]){} ssize_t main(int argc, char **argv){}  要是自己再定义typedef，又有多少种呢？你钻牛角了，我承认上面main中少了void   int main (int argc, char * * argv, char * env)  Because  ISO  C  specifies  that  the main function  be  written  with  two  arguments,  and because  this  third argument  provides  no  benefit  over  the  global  variable environ, POSIX.1  specifies  that environ should  be  used  instead  of  the  (possible)  third argument.  Access to  specific  environment  variables  is  normally  through  the getenv and putenv functions 最后2.3条观点是对的  说明一点：入口函数和编译器也有很大关系。gcc编译时使用-e参数可以指定自己的的入口点函数，换言之，源程序并不是必须以main入口点！不过很少使用。   [/quote]  我想到了这个方面，但没想到你会把它提出来： singed main (signed a, char * * b) {/* ... */} 这都没问题。这样看来，是你在钻牛角尖啦。[/quote] 切，明明是你自己非要把char *argv[]等价于char **argv单独拉出来算一种情况，自己去看你的回复！斗这嘴没啥意思[/quote]  有意思！当然有意思了！ 我的目标是积分超过赵老湿，然后，就不再上CSDN了。因为我还有很多正事要做哩。 你真豪爽，我开始喜欢你了。 # define o int #define k main  o k (void) ??< printf ("你真豪爽，嚓！"); ??>[/quote]

好在你没弄成 void mian ()

用Ctrl+F5，就是不调试的运行，最后系统会给你来一个按任意键继续的 另外flush(stdin)是未定义行为，不一定有用 另外getchar早就不用了。。

区分 getchar() 和scanf()

Ctrl+f5 Ctrl+f7

另外，这个编码风格真是要改啊！

把 while语句的括号带上试试。

楼主，我运行了你的程序，同样是在Dev C++ 环境下 ，运行是正常的，更改了输出 %ld之后 在输入完成之后摁 ctrl+z 结束，可能是结束建输入的不对吧

楼主搞定了吗

getch() 试试


Question: 新人求问C语言的一个问题

谢谢各位大神了，我稍微有点明白了

怎么能用%s 关于枚举——http://blog.csdn.net/u012421456/article/details/38962443

路过学习~~~~

引用 2 楼 qq_16630121 的回复:那如果我写的是%s，能打印出字符串吗 楼上正解

枚举可以理解为int，你用%s打印int看看如何 内存很容易出问题的 如果你在调试语句中想看int对应的字符处串，需要专门写一转换函数

引用 2 楼 qq_16630121 的回复:那如果我写的是%s，能打印出字符串吗  这里头哪有字符串 你指的是打印“PINT”吗？那不行的，本身它就不是个字符串，只是个类似于宏定义的东西，让你看着方便，编译的时候就变成整数值了。 如果你有这样的需要，说明不应该用enum

%s的参数是字符串地址，PINT值是16，程序会去打印地址16开始的字符串，当然是段错误

那如果我写的是%s，能打印出字符串吗

#include <stdio.h>  enum Liquid{  	OUNCE = 1, 	CUP = 8, 	PINT = 16, 	QUART = 32, 	GALLON =128 };  int main() { 	int jar = QUART; 	printf("%d\n", jar);                  return 0; }


Question: 大数分解

仅供参考#include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }


Question: 求教：控制台环境C语言访问Oracle数据库

哪个系统下开发？如果是linux，那就用oracle提供的api，如果是windows平台，建议把ADO简单封装一下为c接口，ADO通吃windos下的所有数据库

您为我做了指导，这个指导具有普遍性，以后再遇到类似的问题也可以按照这样的方法解决，这就叫“授之以渔”，真心感谢您！

访问Oracle，需要安装oracle的客户端工具，如果不想安装可以使用oracle提供的接口库OCCI，Oracle官网搜索"OCCI"就有下载。

参考oracle自带的例子代码demo\*.* Program Name                              Features Illustrated cdemo81.c                                 Using basic SQL processing with release 8 and later functionality. cdemo82.c                                 Performing basic processing of user-defined objects. cdemocor.c                                Using complex object retrieval (COR) to improve performance. cdemodr1.c,cdemodr2.c,cdemodr3.c          Using INSERT/UPDATE/DELETE statements with RETURNING clause used with basic datatypes, LOBs and REFs. cdemodsa.c                                Describing information about a table. cdemodsc.c                                Describing information about an object type. cdemofo.c                                 Registering and operating application failover callbacks. cdemolb.c                                 Create and insert LOB data and then read, write, copy, append and trim the data. cdemolb2.c                                Writing and reading of CLOB/BLOB columns with stream mode and callback functions. cdemolbs.c                                Writing and reading to LOBs with the LOB buffering system. cdemobj.c                                 Pinning and navigation of REF object. cdemorid.c                                Using INSERT, UPDATE, DELETE statements and fetches to get multiple rowids in one round-trip. cdemoses.c                                Using session switching and migration. cdemothr.c                                Using the OCIThread package. cdemosyev.c                               Registering predefined subscriptions and specifying a callback function to be invoked for client notifications (for more information about Advanced Queuing, see Oracle Streams Advanced Queuing User’s Guide and Reference). ociaqdemo00.c,ociaqdemo01.c,ociaqdemo02.c Advanced queuing. cdemodp.c,cdemodp_lip.c                   Loading data with the direct path load functions. cdemdpco.c                                Loading a column object with the direct path load functions. cdemdpno.c                                Loading a nested column object with the direct path load functions. cdemdpin.c                                Loading derived type (inheritance) - direct path. cdemdpit.c                                Loading an object table with inheritance - direct path. cdemdpro.c                                Loading a reference with the direct path load functions. cdemdpss.c                                Loading SQL strings with the direct path load functions. cdemoucb.c,cdemoucbl.c                    Using static and dynamic user callbacks. cdemoupk.c,cdemoup1.c,cdemoup2.c          Using dynamic user callbacks with multiple packages. cdemodt.c                                 Datetime and interval example. cdemosc.c                                 Scrollable cursor. cdemol2l.c                                Accesses LOBs using the LONG API. cdemoin1.c                                Inheritance demo which modifies an inherited type in a table and displays a record from the table. cdemoin2.c                                Inheritance demo to do attribute substitutability. cdemoin3.c                                Inheritance demo that describes an object, inherited types, object tables, and a sub-table. cdemoanydata1.c                           Anydata demo. Inserts and selects rows to and from anydata table. cdemoanydata2.c                           Anydata demo. Creates a type piecewise using OCITypeBeginCreate() and then describes the new type created. cdemosp.c                                 Session pooling. cdemocp.c                                 Connection pooling. cdemocpproxy.c                            Connection pooling with proxy functionality. cdemostc.c                                Statement caching. cdemouni.c                                Program for OCI UTF16 API. nchdemo1.c                                Shows nchar implicit conversion feature and codepoint feature.

首先网上搜一个 c语言学生管理系统之类的程序 接下来好好研究研究,界面的书写和文件的访问. 再下来好好研究研究, oracle提供的c lib库. 然后把学生管理程序的文件访问改成调用oracle的库函数. 入门后, 后面自己添加自己需要的功能.


Question: 全局变量如何访问比较合理，具体请看代码

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

方法2的确有一个好处 但是这个好处在这里被你糟蹋了  方法2可以判断传入参数是否有效 是否越界

方法2 不是访问全局变量  你函数调用运算符写错了

前些天也问过类似的问题，也没有人给出明确性的总结

引用 5 楼 q3733353520 的回复:在编写大型项目的时候 会有很多文件 我们一般将全局变量的操作封装为 Set 以及 Get两个函数 方便其在他文件操作此全局变量 我个人编码也偏向于使用方法2，总是感觉直接去访问全局会有风险，封装起来会安全点。但是说不清为什么会安全？

具体只要考虑一下，页面粒度就可以了 X86早期版本都是 4K页面， 根据数据地，数据量址就可以确定是否跨页了 实际上，只要页面一直都在内存，跨页是没有问题的

2好  以后如果不使用&testtest[port]这种方式取地址. 只改Gettest函数就可以了. const test_t *Gettest(unsigned int port) {     return &testtest[port + 1];//只是例子 }  你要是觉得这里不会有变化,就无所谓了

全局的你就直接访问吧，不然就别弄成全局的了

我是觉得第二种好些,这样把具体的实现细节封装起来,调用者如果想要某个test_t对象只需调用那个函数,而无需知道函数是怎么实现的,也就是说你以后可以更改全局对象的存储方式,而不会影响上层用户

你有五个苹果，我叫你把第二个苹果拿出来，第一种方法就是直接拿第二个苹果，而你第二种方法是我把这五个苹果扔箱子里去，再去箱子里面拿出第二个苹果；只是用箱子包装了一下，又没有做其他事情，何必多此一举……


Question: 分页管理中，如何判定存放数据的数据有没有“跨页”？

[/quote]  引用 10 楼 whizer 的回复:如果你的程序在kernel运行, 在freebsd用vtophys. 其他系统应该有类似的函数.  从你的描述中我感觉你的程序运行在user空间, 你需要物理内存干什么?知道了操作系统也不会让你直接操作的. 我前面给你的说明只是说用这种方法可以得到你需要的信息.  话说你的问题真的需要知道内存的实际存放位置? 考虑效率还是别的需求? 考虑的还是搜索匹配的时间效率。做内存镜像分析的。想通匹配“关键字”定位一段特殊的信息。在实际测试中，发现“关键字”有时会存在“跨页的问题”，我寻思，操作系统，应该提供了一种机制即当我访问到“存放关键字”的前一部分那个内存物理页时，我应该能拿到存放关键字后一部分的内存物理页的地址（物理地址）；这样我能快速定位，不会因为“跨页”，影响查找速度。这是我的思路。可惜，刚刚接触，知道的太少。我也认为win平台也应该有“vtophys”类似的函数。。现在面临的困难，就是想找人指点下，解决这个问题，需要临时补充哪些知识？这方面知识哪有好的资料？真是新手。所以留贴这么久了。。谢谢

Windows内核讲义(东京大学) 来自http://i-web.i.u-tokyo.ac.jp/edu/training/ss/msprojects/ http://download.csdn.net/detail/zhao4zhong1/2742117

引用 7 楼 whizer 的回复:首先要注意你malloc出来的虚拟地址是连续的, 只是物理地址不连续, 接下来判断,  判断虚拟页地址:            A = (数据的起始地址 / 页大小) << log2(页大小) , 如果页大小4k, 左移12 bit            B = A + 页大小       C = B + 页大小 .....  判断物理页: (用虚实转换函数)         A' = vtop(A) ..... 前面都能懂，就是这个“虚实转换函数（vtop( )）”，没有听过，谷歌了下也没找到。能不能介绍下？函数名？有代码？ 学操作系统时，只知道虚拟页通过硬件查页表实现物理地址映射。具体到代码上就不清楚了。 作为新手，刚开始接触内存管理、分析方向，感觉泥学的不错。有好资料推荐嘛？谢谢

引用 3 楼 user-3 的回复:一般来说，只要页面不是太多，跨页根本不是问题 假定数据存放在A页，空间不足，跨页存放到了B页。那么，“跨页”了怎么确定B页的起始地址呢？ A页和B页都是逻辑分页。不是连续存放的。谢谢

引用 2 楼 whizer 的回复:先查页大小, 因为物理页和虚拟页一般大小相等, 因此虚拟页和物理页是一一对应的. 接下来查你的数据的起始地址,这是你自己可以得到的. 然后查你的数据的长度. 起始地址+长度 跨越页界限, 肯定是跨页访问.  具体算法:  起始地址%页大小 + 长度 >　页大小 恩。这个算法确实能判断是否分页。那么如果确定分页。加入部分数据存放在A页，另一部分存放在了B页。这两页原则上是 不会连续存放的。我想问下。如何确定B页的起始地址（希望能访问到B页）？Windows是不是有相应的属性记录了A页和B页的“关系”。还是。。。PS：我做的是模糊匹配查找，能确定的基本上只有数据的总长度。谢谢

quote=引用 2 楼 whizer 的回复:] 先查页大小, 因为物理页和虚拟页一般大小相等, 因此虚拟页和物理页是一一对应的. 接下来查你的数据的起始地址,这是你自己可以得到的. 然后查你的数据的长度. 起始地址+长度 跨越页界限, 肯定是跨页访问.  具体算法:  起始地址%页大小 + 长度 >　页大小[/quote] 恩。这个算法确实能判断是否分页。那么如果确定分页。加入部分数据存放在A页，另一部分存放在了B页。这两页原则上是 不会连续存放的。我想问下。如何确定B页的起始地址（希望能访问到B页）？Windows是不是有相应的属性记录了A页和B页的“关系”。还是。。。PS：我做的是模糊匹配查找，能确定的基本上只有数据的总长度。谢谢

一般来说，只要页面不是太多，跨页根本不是问题

所以才有类似VirtualLock之类的函数呀。


引用 1 楼 zhao4zhong1 的回复:作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。 //把192.168.1.11变成192.168.001.011 #include <stdio.h> char s[20]="192.168.1.11"; char t[20]; int a,b,c,d; int main() {     sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d);     sprintf(t,"%03d.%03d.%03d.%03d",a,b,c,d);     printf("%s\n",t);     return 0; } //192.168.001.011 //  其实自己后来也搞定了也是这样。但是没有第一时间搞定就是不合格，谢谢赵老师


Question: TTF字体引擎技术文档的独家翻译

支持楼主，支持开源精神！

支持楼主的分享精神！


Question: TTF字体引擎技术文档的独家翻译

支持楼主的分享精神！


Question: 一编程练习已经写出，请C达人看看如何优化更好。

引用 14 楼 onlysee8 的回复:你那C选项，是脱裤子放屁。每个功能块完成，都自动显示菜单了，还需要这个干嘛。show里面的排版都不会弄我也不用再学下去了。不过赵大师把括号弄整齐了，运行的确快了很多  [quote=引用 12 楼 fly_dragon_fly 的回复:] 看了一下，应该没什么速度问题，谈不上什么优化，就风格谈谈 1. human arr[12] 初始化在后面readfile中，前面就没必要了 2. ch=getchar();后面有很多处理，用switch吧，if太多了，最好用函数名来区别，就不需要看注释了 3. 魔法数字12，就是数组的长度，想其它方法避免，万一数组长度改为20，不要一条条去检查。  这位兄台说得中肯，昨晚我已经发现readfile的问题，而且把所有功能块修改为子函数形式。并把数组扩为二维， 在实际中某个类型的飞机，在公司里会有很多架，或者需要执行多个航班的情况。 改进为全动态分配内存，可以保存和分配无限多个航班与座位。在1000×1000的数组中测试运行稳定良好。 改进了几次容错机制，本人对这种习题都是按实际工程去考虑。当然是在自己学到的东西中尽力做到。 关于魔法12，用define一个常量就可，这只是习题。[/quote]  define 不是好的办法。  引用 2 楼 onlysee8 的回复:[quote=引用 1 楼 sholber 的回复:] 无可奉告。ffffff  哈，你自己也不懂[/quote] 这不是问问题的语气。

引用 12 楼 fly_dragon_fly 的回复:看了一下，应该没什么速度问题，谈不上什么优化，就风格谈谈 1. human arr[12] 初始化在后面readfile中，前面就没必要了 2. ch=getchar();后面有很多处理，用switch吧，if太多了，最好用函数名来区别，就不需要看注释了 3. 魔法数字12，就是数组的长度，想其它方法避免，万一数组长度改为20，不要一条条去检查。  另外关于switch，我也看了些国外的C教学文章，如果是函数指针方式调用推荐，如果是函数体用if。不知道恰当与否！

引用 13 楼 zhao4zhong1 的回复:楼主真的是高二学生的话：  高中生还是集中精力准备上大学吧。  希望你不要犯类似 “早知道吃完第七个包子就饱了，我为什么还要吃前六个包子呢？！”  这种低级错误。  上大学是必须滴，这只是爱好。我看了半年才看了10来章。

你那C选项，是脱裤子放屁。每个功能块完成，都自动显示菜单了，还需要这个干嘛。show里面的排版都不会弄我也不用再学下去了。不过赵大师把括号弄整齐了，运行的确快了很多 引用 12 楼 fly_dragon_fly 的回复:看了一下，应该没什么速度问题，谈不上什么优化，就风格谈谈 1. human arr[12] 初始化在后面readfile中，前面就没必要了 2. ch=getchar();后面有很多处理，用switch吧，if太多了，最好用函数名来区别，就不需要看注释了 3. 魔法数字12，就是数组的长度，想其它方法避免，万一数组长度改为20，不要一条条去检查。  这位兄台说得中肯，昨晚我已经发现readfile的问题，而且把所有功能块修改为子函数形式。并把数组扩为二维， 在实际中某个类型的飞机，在公司里会有很多架，或者需要执行多个航班的情况。 改进为全动态分配内存，可以保存和分配无限多个航班与座位。在1000×1000的数组中测试运行稳定良好。 改进了几次容错机制，本人对这种习题都是按实际工程去考虑。当然是在自己学到的东西中尽力做到。 关于魔法12，用define一个常量就可，这只是习题。

我的语气传染自2楼。

58: } else if(ch=='c') {//show alphabetical list of seats 59:             printf("TODO\n"); 60:             show(); 这几行是我加的，楼主看出来了吗？

拿一个半成品出来炫耀？  你也别装什么大尾巴狼，不就是早接触这东西？假以时日谁比谁牛还未必。

[quote=引用 4 楼 zhao4zhong1 的回复:] 拿一个半成品出来炫耀？ 赵老师你的话就有点过了，这是C perimer plus中的一个编程练习。 小菜只是个高二学生，买了本书自学，全出于爱好。没系统学过各方面的知识，只是想在论坛，得到各位的指点。 看自己思路的短板在哪。知道你很牛，但也不必言出尖酸刻薄。你不指点没关系，请不要用这种言语来自污清誉。

拿一个半成品出来炫耀？ #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<string.h> struct name {     char fn[30];     char ln[30]; }; struct human {     char ch[20];     bool bol;//false:未售，true:已售     struct name fm; }; void writefile(const struct human pt[],int z); void show(void); void read_file(struct human *ar,int x); int main(void) {     int i,tot,ch;     char temp[20];     struct human arr[12]= {         {.ch= "1-A",.bol=false,{"",""}},         {.ch= "2-B",.bol=false,{"",""}},         {.ch= "3-C",.bol=false,{"",""}},         {.ch= "4-D",.bol=false,{"",""}},         {.ch= "5-E",.bol=false,{"",""}},         {.ch= "6-F",.bol=false,{"",""}},         {.ch= "7-G",.bol=false,{"",""}},         {.ch= "8-H",.bol=false,{"",""}},         {.ch= "9-I",.bol=false,{"",""}},         {.ch="10-J",.bol=false,{"",""}},         {.ch="11-K",.bol=false,{"",""}},         {.ch="12-L",.bol=false,{"",""}},     };      show();     while(1) {         read_file(arr,12);         fflush(stdin);         ch=getchar();         if       (ch=='a') {//统计未售机票数             for(i=0,tot=0;i<12;i++)                 if(arr[i].bol==false)                     tot++;             printf("%d\n",tot);             show();         } else if(ch=='b') {//显示空位列表             for(i=0;i<12;i++)                 if(arr[i].bol==false) {                     printf("%4s ",arr[i].ch);                     if((i+1)%4==0)                         printf("\n");                 } else {                     printf(" *** ");                     if((i+1)%4==0)                         printf("\n");                 }             show();         } else if(ch=='c') {//show alphabetical list of seats             printf("TODO\n");             show();         } else if(ch=='d') {//分配客户预订座位             while(1) {//可以多个预订                 fflush(stdin);                 gets(temp);                 if(temp[0]=='\0') break; //按下回车结束预订步骤！                 for(i=0;i<12;i++) {                     if(strcmp(temp,arr[i].ch)==0) {//遍历成员，定位到某一座号                         if(arr[i].bol==false) {//如果未售出                             arr[i].bol=true;//赋为售出                             gets(arr[i].fm.fn);//输入名                             gets(arr[i].fm.ln);//输入姓                             break;//跳出for,到外层继续等待预订输入                         }                         printf("The seat have  been sale\n");//如果已售出则给出提示后跳出for                         break;                     }                 }             }             writefile(arr,12);//保存到文件中             show();         } else if(ch=='e') {//删除座位             while(1) {//可以删除多个                 fflush(stdin);                 gets(temp);                 if(temp[0]=='\0') break;                 for(i=0;i<12;i++) {                     if(strcmp(temp,arr[i].ch)==0)                         arr[i].bol=false;                 }             }             writefile(arr,12);             show();         } else if(ch=='f') {//结束程序             break;         } else {             printf("wrong choose (a,b,c,d,e,f)is right\n");         }     }     return 0; } void show(void) {     printf(         "To choose a funtion tnter its letter lable:\n"         "  a) show number of empty seats\n"         "  b) show list of empty seats\n"         "  c) show alphabetical list of seats\n"         "  d) assign a customer to a seat assignment\n"         "  e) delet a seat assignment\n"         "  f) quit\n"     );     return; } void read_file(struct human * ar,int x) {     FILE *fp;      int k=0;     if((fp=fopen("jp.txt","a+b"))==NULL) {         printf("cant open file\n");         exit(1);     }     rewind(fp);     while (k<x && fread(ar+k,sizeof(struct human),1,fp)==1) k++;     fclose(fp); } void writefile(const struct human pt[],int z) {     int i;     FILE *fp1;      if((fp1=fopen("jp.txt","w+b"))==NULL) {         printf("cant write file\n");         exit(2);     }     for(i=0;i<z;i++) fwrite(&pt[i],sizeof(struct human),1,fp1);     fclose(fp1); }

不是达人，没啥想法 不过，c那里多个空格

struct human arr[12]={{"1-A"},{"2-B"},{"3-C"},\                                     {"4-D"},{"5-E"},{"6-F"},\                                     {"7-G"},{"8-H"},{"9-I"},\                                     {"10-J"},{"11-K"},{"12-L"}};

高二？ 是对还是错....

楼主放下语气问题暂且不说（这个我不爱听），能说说我优化了哪些方面吗？（这个我爱听）。

引用 1 楼 sholber 的回复:无可奉告。ffffff  哈，你自己也不懂

无可奉告。ffffff


Question: C语新手的一个小问题~

引用 7 楼 ruying1389279 的回复:[quote=引用 5 楼 I_better 的回复:] [quote=引用 2 楼 bear234 的回复:] 奇葩代码啊..... 自己百度getchar函数........... 你好。我刚才看了一下getchar。 这里我想了解关于EOF的一些情况，请问什么情况下会返回EOF 比如我输入ABC[enter]。EOF在什么位置[/quote] EOF的意思是 文件结束符 windows下 ctrl+z 组合键实现结束，回车只是换行[/quote] 我刚才用while语句跑了一下。 ctrl+z的确会结束后面循环。但是并未跳出while循环 比如我输入“abcd^zefg” 输出为“abcd”，但是依旧可以循环输入，输出。没有出现press any key to continue

引用 5 楼 I_better 的回复:[quote=引用 2 楼 bear234 的回复:] 奇葩代码啊..... 自己百度getchar函数........... 你好。我刚才看了一下getchar。 这里我想了解关于EOF的一些情况，请问什么情况下会返回EOF 比如我输入ABC[enter]。EOF在什么位置[/quote] EOF的意思是 文件结束符 windows下 ctrl+z 组合键实现结束，回车只是换行

把分号移到下面来，用空语句

引用 2 楼 bear234 的回复:奇葩代码啊..... 自己百度getchar函数........... 你好。我刚才看了一下getchar。 这里我想了解关于EOF的一些情况，请问什么情况下会返回EOF 比如我输入ABC[enter]。EOF在什么位置

引用 1 楼 sholber 的回复:眼睛不要只盯着看得见的字符，回车就不算啦？ 你好。 请问什么情况下会返回EOF 比如我输入ABC[enter]。EOF在什么位置

字符数？可以用strlen（）吧

奇葩代码啊..... 自己百度getchar函数...........

眼睛不要只盯着看得见的字符，回车就不算啦？


上联：说你行你就行不行也行， 下联：说不行就不行行也不行。 横批：不服不行

编译器读到 #error 就会报错。  就是人为故意产生错误。

你是写C还是cpp呢，你到底是C语言程序还是C++

引用 4 楼 zhao4zhong1 的回复:The #error Directive Error directives produce compiler-time error messages.  Syntax  #error token-string  The error messages include the argument token-string and are subject to macro expansion. These directives are most useful for detecting programmer inconsistencies and violation of constraints during preprocessing. The following example demonstrates error processing during preprocessing:  #if !defined(__cplusplus) #error C++ compiler required. #endif  When #error directives are encountered, compilation terminates. _________________________________________________________  message #pragma message( messagestring )  Sends a string literal to the standard output without terminating the compilation. A typical use of the message pragma is to display informational messages at compile time.  The following code fragment uses the message pragma to display a message during compilation:  #if _M_IX86 == 500 #pragma message( "Pentium processor build" ) #endif  The messagestring parameter can be a macro that expands to a string literal, and you can concatenate such macros with string literals in any combination. For example, the following statements display the name of the file being compiled and the date and time when the file was last modified:  #pragma message( "Compiling " __FILE__ )  #pragma message( "Last modified on " __TIMESTAMP__ )  是说  引用 4 楼 zhao4zhong1 的回复:The #error Directive Error directives produce compiler-time error messages.  Syntax  #error token-string  The error messages include the argument token-string and are subject to macro expansion. These directives are most useful for detecting programmer inconsistencies and violation of constraints during preprocessing. The following example demonstrates error processing during preprocessing:  #if !defined(__cplusplus) #error C++ compiler required. #endif  When #error directives are encountered, compilation terminates. _________________________________________________________  message #pragma message( messagestring )  Sends a string literal to the standard output without terminating the compilation. A typical use of the message pragma is to display informational messages at compile time.  The following code fragment uses the message pragma to display a message during compilation:  #if _M_IX86 == 500 #pragma message( "Pentium processor build" ) #endif  The messagestring parameter can be a macro that expands to a string literal, and you can concatenate such macros with string literals in any combination. For example, the following statements display the name of the file being compiled and the date and time when the file was last modified:  #pragma message( "Compiling " __FILE__ )  #pragma message( "Last modified on " __TIMESTAMP__ )  好像有点明白了，但还是不太懂#error这个指令的作用.

引用 3 楼 Saleayas 的回复:#error 就是表示当编译器看到这一行的时候，保证编译器报错。 比如，你需要你的头文件被 .cpp 文件包含，而不是被 .c 文件包含。 那么就需要这样 #ifndef __cplusplus #error error message. #endif  你可以看看 atlbase.h 中的。atlbase.h 要求用 C++ 编译。也就是说，一旦用了#error就不能编译是吧？

引用 2 楼 www4206 的回复:你是写C还是cpp呢，你到底是C语言程序还是C++ 是C


Question: 关于对C语言指针数组的理解

哦。明白

理解和讨论之前请先学会如何观察！

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

1) 看c99对这个操作的描述.  When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.   2) 内存图   3)对比上面的内存图和操作描述,我们知道 ptr指向a, ptr + i指向a的第i个元素. *ptr指向a[0], *ptr + i指向a[0]的第i个元素.  希望对你有所帮助.

引用 1 楼 user-4 的回复:*prt+i 是 prt[ 0 ] + i *(prt+i) 是 prt[ i ] *(*prt+i) 是 prt[ 0 ][ i ] **(prt+i) 是 prt[ i ][ 0 ] 真心感谢这位大神~~~


Question: 求解

b是数组名也就是它的首元素地址 scanf（）需要存入一个地址，所以b==&b[0],而b+i是指针移动i个元素单位，所以它还是一个地址，可以给scanf使用。 而 b[i]是数组的第i个元素，也就是一个整数值。它对于scanf是非法滴。 这么说你应该明白了吧。

b[i] 等价于*(b+i) 而不等价于b+i

Pointer Arithmetic Additive operations involving a pointer and an integer give meaningful results only if the pointer operand addresses an array member and the integer value produces an offset within the bounds of the same array. When the integer value is converted to an address offset, the compiler assumes that only memory positions of the same size lie between the original address and the address plus the offset.  This assumption is valid for array members. By definition, an array is a series of values of the same type; its elements reside in contiguous memory locations. However, storage for any types except array elements is not guaranteed to be filled by the same type of identifiers. That is, blanks can appear between memory positions, even positions of the same type. Therefore, the results of adding to or subtracting from the addresses of any values but array elements are undefined.  Similarly, when two pointer values are subtracted, the conversion assumes that only values of the same type, with no blanks, lie between the addresses given by the operands.

scanf的问题 http://blog.csdn.net/u012421456/article/details/18501309

for (i=1; i<=4; i++)         scanf("%d", b+i); b+i是地址 b[i]是变量，改成&(b[i])就可以了

我看了下这个程序，b+i可以运行，像你说的改成b[i]也可以运行，都没有错误。 输入的时候scnaf("%d",&b[i]);就可以了，也运行过关了，但是你要是输入函数这样写就不对了scanf("%d",b[i]);为什么不对不解释。


Question: 求助一个小问题

p是一个指针常量,不能写成p++ 可以改成下面的: void main()  {      char *p[4]={"he","love","she"};      char **ptrp=p;      int i;      for(i=0;i<3;i++)         printf("%s",*(ptrp++));  }

p++ 或者 ++p  把p的值就变了  而数组名是绝对不能变的～～～～  你可以把数组名赋值给相应的指针数据去操作这个指针

这个问题看似简单，但含金量很高。请老油条们用“地址”、“变量”、“存储的是地址”等等来解释一下吧，看能不能解释得通。

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

引用 2 楼 wysdaomei 的回复:[quote=引用 1 楼 sholber 的回复:] char * p [3] = {"he", "love", "she"}; /* …… */ printf ("%s", * (p ++)); 前缀++运算符要求它的操作数是一个可修改的左值，但p的类型是数组，作为前缀++运算符的操作数时，调整为指向数组首元素的指针，但不再是左值。  那对于一个函数int num(char *p[],int n)；在该函数中可以对p进行自增，这跟我上面的有什么区别？[/quote]  尽管都是指针，但前者是调整（转换）而来的，转换之后是值，不再是左值；后者呢，本身就是一个左值，不是经转换来的。

引用 1 楼 sholber 的回复:char * p [3] = {"he", "love", "she"}; /* …… */ printf ("%s", * (p ++)); 前缀++运算符要求它的操作数是一个可修改的左值，但p的类型是数组，作为前缀++运算符的操作数时，调整为指向数组首元素的指针，但不再是左值。  那对于一个函数int num(char *p[],int n)；在该函数中可以对p进行自增，这跟我上面的有什么区别？


Question: 四个数论问题

p(x)表示整数x的最大素因数，如果数列{xn}满足： 1、首项x1为任意素数； 2、递推式x(n+1)=p(xn^2+1)。 计算显示，该数列很可能没有上界。  我感兴趣的是，如果把指数2变为1.6，数列是否存在上界。

问题1拓展版： p(x)表示整数x的最大素因数，且p(x)~x^a。 已知a≈0.62433，则1/a≈1.6。 数列{xn}满足： 1、首项x1为任意素数； 2、递推式x(n+1)=p([xn^1.6])。其中[xn^1.6]表示对xn^1.6取整。 问：该数列是否一定存在上界。

回楼上： 你脑子没坏，这个问题确实与prime gap有关。 一、Cramer猜想：x与x+lnx*lnx之间必有素数。 二、x与x+lnx*lnx之间有lnx*lnx/2个奇数。 三、由素数定理：2与lnx*lnx*lnlnx之间约有lnx*lnx/2个奇素数。 四、假设在整数x附近随机选择lnx*lnx/2个奇数，其中包含素数。（显然不对，但有一定启发性。） 五、根据以上四点，提出“加强版Goldbach”。

脑子坏了怎么扯到prime gap去了（大概是看到个log平方就想那里去了）。Goldbach的话印象里真没啥有关其中一个prime多大的结论。那我就完全没啥看法了。祈祷程序算个反例，算不出那就等于这题做不出了。

不好说。不过仔细想想，这个命题有反例也推翻不了原来的Goldbach。而那个渐进式也就比prime gap的Cramer猜想多了个loglog(n)。没想法，要猜的话我还是偏向有反例。 要写程序就写一个吧，算出个反例那最好，没有那就啥也说明不了。

谢楼上！  2. 加强版Goldbach没啥好说的 这个找到反例没有？

程序没意思。直接回答数学了。 1. 0.62433 2. 加强版Goldbach没啥好说的 3. 有反例。A是足够大的，mod (3*5*17*257*65537*641)=1，mod 6700417=-1的整数。对于这个A，讨论n mod 32的情况就能讨论出来A+2^n必定整除刚才一串质数的至少一个。 4. 显然不对。用经典的构造n项合数的方法，a=(k+1)!+1, b=1，那么这几个连续合数的质因子个数仅为<=k+1的所有质数，这在k>=4的时候就比k小了。  目测第三题，光初学C语言肯定想不到这个结论是不对的。我自己是想不到第二个构造的方法了。

被你发现了，从小立志抄作业！

作业？


Question: cygwin中文问题？

引用 4 楼 ForestDB 的回复:你的源文件是utf8的？你console的locale设定是怎样的？谢谢啊，看了下是编码选错了，选的是UTF-8 改成GBK就好了

printf语句之前做个清屏操作试试

你的源文件是utf8的？你console的locale设定是怎样的？

字符集的问题是C编程最麻烦的地方之一，你的问题不但与程序本身有关，也与编译器有关，不能一概而论。

缺少格式控制符%s，按理来说应该会报错，不能运行，不同编译器不一样，加个格式控制符是是。 printf("%s",'hello world !你好世界'\n);

不一定对，仅供参考： #include <stdio.h> #include <locale.h>   int main(void) {    setlocale(LC_ALL,"chs");     printf("%s","hello,word!你好世界\n");     return 0; }


Question: 求unicode转gb18030 linux下C程序

引用 7 楼 fang3453126 的回复:[quote=引用 6 楼 qq_25660979 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 qq_25660979 的回复:]  上传了之前我们一个平台上unicode转GB18030 的源代码，只找到上传jpg文件的方法，不知道能否下载下来，下来后重命名为.c 你可以在CSDN资源中上传。http://download.csdn.net/[/quote] 感谢，已经上传上去了  http://download.csdn.net/download/qq_25660979/8404881[/quote]  我是AIX系统的，这个stdfx.h好像没有，这个程序没有输出[/quote]  这个只是个demo程序，des为转换后的编码，输出方法的话，每个平台都不一样，关键看转换后的编码多不对

引用 9 楼 zhao4zhong1 的回复:ucs2就是标准的unicode编码  我把"成"cat到 aaa.txt里了。 然后iconv -f GB18030 -t 系统各种编码  aaa.txt 都没能得到6210这字符。

引用 9 楼 zhao4zhong1 的回复:ucs2就是标准的unicode编码  我编码为 0x6210,0x529f 对应的"成功"两字 就是不知道怎么转码。

引用 3 楼 zhao4zhong1 的回复:Windows下的码表在  http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\cvt>dir /a-d /w  驱动器 C 中的卷是 C_HD5_1  卷的序列号是 1817-D526   C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\cvt 的目录  8859_1       8859_10      8859_13      8859_14      8859_15      8859_16      8859_2       8859_3       8859_4 8859_5       8859_6       8859_7       8859_8       8859_9       baltic       big5         cp037        cp1006 cp1026       cp1250       cp1251       cp1252       cp1253       cp1254       cp1255       cp1256       cp1257 cp1258       cp424        cp437        cp500        cp737        cp775        cp850        cp852        cp855 cp856        cp857        cp860        cp861        cp862        cp863        cp864        cp865        cp866 cp869        cp874        cp875        cp932        cp936        cp949        cp950        cyrillic     ebcdic euc          euc_0208     gb12345      gb2312       greek        iceland      jis          jis0201      jis_0208 ksc5601      latin2       one_one      roman        sjis         sjis_0208    turkish      utf16        utf8 utf8_utf16   wbuffer      wstring      xjis         xone_byte    xtest        xtwo_byte               79 个文件      4,638,592 字节                0 个目录 13,399,814,144 可用字节   我iconv -l看了，AIX系统里iconv没有 UNICODE，我用命令 iconv(参数f t)的转换方法。都没有想要的输出，目前iconv只有 UCS-2， UTF-8 -16 -32，UCS-2.。。linux下的setlocale 然后用wcstombs转 可以，AIX就不行

引用 6 楼 qq_25660979 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 qq_25660979 的回复:]  上传了之前我们一个平台上unicode转GB18030 的源代码，只找到上传jpg文件的方法，不知道能否下载下来，下来后重命名为.c 你可以在CSDN资源中上传。http://download.csdn.net/[/quote] 感谢，已经上传上去了  http://download.csdn.net/download/qq_25660979/8404881[/quote]  我是AIX系统的，这个stdfx.h好像没有，这个程序没有输出

引用 5 楼 zhao4zhong1 的回复:[quote=引用 4 楼 qq_25660979 的回复:]  上传了之前我们一个平台上unicode转GB18030 的源代码，只找到上传jpg文件的方法，不知道能否下载下来，下来后重命名为.c 你可以在CSDN资源中上传。http://download.csdn.net/[/quote] 感谢，已经上传上去了  http://download.csdn.net/download/qq_25660979/8404881

引用 4 楼 qq_25660979 的回复: 上传了之前我们一个平台上unicode转GB18030 的源代码，只找到上传jpg文件的方法，不知道能否下载下来，下来后重命名为.c 你可以在CSDN资源中上传。http://download.csdn.net/

iconv是开源的吧，直接用iconv用的码表。

用iconv库试试？


Question: if((sum^a[i])

引用 7 楼 Ice_Alone 的回复:[quote=引用 4 楼 whizer 的回复:] 拿不准的话就加个括号，这是程序按你的思路工作的简单方法。 引用 5 楼 zhao4zhong1 的回复://C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+   你这个是在哪本书上，或者网站上看到的啊？[/quote] MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl 下载安装MSDN98到D:\MSDN98\ mk:@MSITStore:D:\MSDN98\98VS\2052\vclang.chm::/html/_pluslang_c.2b2b_.operators.htm

引用 4 楼 whizer 的回复:拿不准的话就加个括号，这是程序按你的思路工作的简单方法。  哦 恩恩

引用 4 楼 whizer 的回复:拿不准的话就加个括号，这是程序按你的思路工作的简单方法。 引用 5 楼 zhao4zhong1 的回复://C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+   你这个是在哪本书上，或者网站上看到的啊？

引用 2 楼 user-5 的回复:http://en.cppreference.com/w/cpp/language/operator_precedence 这是一个类似于工具书的网站吗？

^优化级比<低。 这种情况下加个括号就完事了。

拿不准的话就加个括号，这是程序按你的思路工作的简单方法。

（）的优先级最高，其他的可以参考优先级顺序表，多看几次就不会忘记了


帮结帖＋蹭分

这个问题已经解决了呢


Question: 怎样进一步提高编程能力

程序白痴也来求经验

我感觉你还没有入门  编程这个行业，门槛很模糊，很可能你学了一两年了，也能动手做一些东西了但你其实还是根本没有入门.....  又看php又看java有学c++  这就是在作死   php仍了，用c++入门   把c++学好了  其他语言都是浮云  找本c++ primer plus看几遍先

不能一直看书，每看了一点，有收获后就立即实践，选书也要注意好坏先后，只有做过了才是会了。加油！！！

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

多写代码，多写代码，还是多写代码

数据结构与算法  自己动手做一个小项目试试  试试在线编程题，比如zoj，poj等等

在CSDN多看多问吧...................

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

用你会用的语言去做一个小东西把。还有去看开源软件的代码，比如nginx，curl，学习别人的设计。


Question: c语言用ADO操作MYSQL问题

返回值仅表示对mysql服务访问的一种执行状态。是OK的。 至于你所查询的记录是否存在数据或者为空，要看你查询到的数据再做断定了。  比方，我用渔网捞鱼，网下水到收网，动作连贯，没有碰到障碍物神马的，说明我本次捞鱼的动作是OK的。 至于有没有鱼在网里...你得再看一眼了。

返回OK只代表执行正常，不代表就有记录吧


Question: 在C语言中如何读取MATLAB 的.mat文件中的数据

编译出来的库你有没有调用初始化。。貌似****institu什么的。记得有两个函数是初始化的

mlfCell2struct ？

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！