Question: assert断言引申的一系列问题

另外assert是调用的abort

断言在debug版本中会编译成目标代码，release版本中就没有了（它是个宏，release中被略去了）。  简单点说，return（main中的）和exit()是一样的，不过就是main return a（0或者1）以后，CRT的函数接受这个a，然后调用exit(a)，即exit是你调还是CRT的函数来调； exit和abort的区别就是exit打扫卫生，abort不打扫  abort -- cause abnormal program termination      The abort() function causes abnormal program termination to occur, unless      the signal SIGABRT is being caught and the signal handler does not      return.       Any open streams are flushed and closed.  exit, _Exit -- perform normal program termination      The exit() and _Exit() functions terminate a process.       Before termination, exit() performs the following functions in the order      listed:             1.   Call the functions registered with the atexit(3) function, in                 the reverse order of their registration.             2.   Flush all open output streams.             3.   Close all open streams.             4.   Unlink all files created with the tmpfile(3) function.       The _Exit() function terminates without calling the functions registered      with the atexit(3) function, and may or may not perform the other actions      listed.  详细的还可以看看APUE这样的书。

引用 2 楼 u012072837 的回复:[quote=引用 1 楼 shenchenman 的回复:] 1 断言有中断的效果 2 这种退出方式指的是什么？断言不需要退出 3 return是退出函数，exit是退出进程  1、请问有中断的效果是神马意思？ 2、断言不是判断错误就马上退出吗？ 3、这个大概能理解，那abort呢？[/quote]  1 中断就是控制权交给操作系统，程序暂时挂起 2 断言可以选继续retry 3 abort也是退出进程，但是比exit弱。它不记录状态

assert这类功能的特点是在Debug版中不符合断言则中断执行，在Release版中不编译到目标代码中。

引用 5 楼 zhao4zhong1 的回复:_ASSERT, _ASSERTE Macros Evaluate an expression and generate a debug report when the result is FALSE (debug version only).  _ASSERT( booleanExpression );  _ASSERTE( booleanExpression );  Macro Required Header Compatibility  _ASSERT <crtdbg.h> Win NT, Win 95  _ASSERTE <crtdbg.h> Win NT, Win 95    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBCD.LIB Single thread static library, debug version  LIBCMTD.LIB Multithread static library, debug version  MSVCRTD.LIB Import library for MSVCRTD.DLL, debug version    Although _ASSERT and _ASSERTE are macros and are obtained by including CRTDBG.H, the application must link with one of the libraries listed above because these macros call other run-time functions.  Return Value  None  Parameter  booleanExpression  Expression (including pointers) that evaluates to nonzero or 0  Remarks  The _ASSERT and _ASSERTE macros provide an application with a clean and simple mechanism for checking assumptions during the debugging process. They are very flexible because they do not need to be enclosed in #ifdef statements to prevent them from being called in a retail build of an application. This flexibility is achieved by using the _DEBUG macro. _ASSERT and _ASSERTE are only available when _DEBUG is defined. When _DEBUG is not defined, calls to these macros are removed during preprocessing.  _ASSERT and _ASSERTE evaluate their booleanExpression argument and when the result is FALSE (0), they print a diagnostic message and call _CrtDbgReport to generate a debug report. The _ASSERT macro prints a simple diagnostic message, while _ASSERTE includes a string representation of the failed expression in the message. These macros do nothing when booleanExpression evaluates to nonzero.  Because the _ASSERTE macro specifies the failed expression in the generated report, it enables users to identify the problem without referring to the application source code. However, a disadvantage exists in that every expression evaluated by _ASSERTE must be included in the debug version of your application as a string constant. Therefore, if a large number of calls are made to _ASSERTE, these expressions can take up a significant amount of space.  _CrtDbgReport generates the debug report and determines its destination(s), based on the current report mode(s) and file defined for the _CRT_ASSERT report type. By default, assertion failures and errors are directed to a debug message window. The _CrtSetReportMode and _CrtSetReportFile functions are used to define the destination(s) for each report type.  When the destination is a debug message window and the user chooses the Retry button, _CrtDbgReport returns 1, causing the _ASSERT and _ASSERTE macros to start the debugger, provided that “just-in-time” (JIT) debugging is enabled. See Debug Reporting Functions of the C Run-Time Library for an example of an assert message box under Windows NT.  For more information about the reporting process, see the _CrtDbgReport function and the section Debug Reporting Functions of the C Run-Time Library. For more information about resolving assertion failures and using these macros as a debugging error handling mechanism, see Using Macros for Verification and Reporting.  The _RPT, _RPTF debug macros are also available for generating a debug report, but they do not evaluate an expression. The _RPT macros generate a simple report and the _RPTF macros include the source file and line number where the report macro was called, in the generated report. In addition to the _ASSERTE macros, the ANSI assert routine can also be used to verify program logic. This routine is available in both the debug and release versions of the libraries.  Example  /*   * DBGMACRO.C   * In this program, calls are made to the _ASSERT and _ASSERTE   * macros to test the condition 'string1 == string2'.  If the   * condition fails, these macros print a diagnostic message.   * The _RPTn and _RPTFn group of macros are also exercised in   * this program, as an alternative to the printf function.   */  #include <stdio.h>  #include <string.h>  #include <malloc.h>  #include <crtdbg.h>  int main()  {  char *p1, *p2;  /*  * The Reporting Mode and File must be specified  * before generating a debug report via an assert  * or report macro.  * This program sends all report types to STDOUT  */  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);  /*  * Allocate and assign the pointer variables  */  p1 = (char *)malloc(10);  strcpy(p1, "I am p1");  p2 = (char *)malloc(10);  strcpy(p2, "I am p2");  /*  * Use the report macros as a debugging  * warning mechanism, similar to printf.  *  * Use the assert macros to check if the  * p1 and p2 variables are equivalent.  *  * If the expression fails, _ASSERTE will  * include a string representation of the  * failed expression in the report.  * _ASSERT does not include the  * expression in the generated report.  */  _RPT0(_CRT_WARN, "\n\n Use the assert macros to evaluate the expression p1 == p2.\n");  _RPTF2(_CRT_WARN, "\n Will _ASSERT find '%s' == '%s' ?\n", p1, p2);  _ASSERT(p1 == p2);  _RPTF2(_CRT_WARN, "\n\n Will _ASSERTE find '%s' == '%s' ?\n", p1, p2);  _ASSERTE(p1 == p2);  _RPT2(_CRT_ERROR, "\n \n '%s' != '%s'\n", p1, p2);   free(p2);  free(p1);  return 0;  }   Output  Use the assert macros to evaluate the expression p1 == p2.  dbgmacro.c(54) : Will _ASSERT find 'I am p1' == 'I am p2' ? dbgmacro.c(55) : Assertion failed   dbgmacro.c(57) : Will _ASSERTE find 'I am p1' == 'I am p2' ? dbgmacro.c(58) : Assertion failed: p1 == p2   'I am p1' != 'I am p2'   Debug Functions  See Also   _RPT, _RPTF看了一下，0.0好像主要在用法上解释的比较多，请问有没有您自己在这方面的使用经验呢？

assert Evaluates an expression and when the result is FALSE, prints a diagnostic message and aborts the program.  void assert( int expression );  Routine Required Header Compatibility  assert <assert.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  None  Parameter  expression  Expression (including pointers) that evaluates to nonzero or 0  Remarks  The ANSI assert macro is typically used to identify logic errors during program development, by implementing the expression argument to evaluate to false only when the program is operating incorrectly. After debugging is complete, assertion checking can be turned off without modifying the source file by defining the identifier NDEBUG. NDEBUG can be defined with a /D command-line option or with a #define directive. If NDEBUG is defined with #define, the directive must appear before ASSERT.H is included.  assert prints a diagnostic message when expression evaluates to false (0) and calls abort to terminate program execution. No action is taken if expression is true (nonzero). The diagnostic message includes the failed expression and the name of the source file and line number where the assertion failed.  The destination of the diagnostic message depends on the type of application that called the routine. Console applications always receive the message via stderr. In a single- or multithreaded Windows application, assert calls the Windows MessageBox API to create a message box to display the message along with an OK button. When the user chooses OK, the program aborts immediately.  When the application is linked with a debug version of the run-time libraries, assert creates a message box with three buttons: Abort, Retry, and Ignore. If the user selects Abort, the program aborts immediately. If the user selects Retry, the debugger is called and the user can debug the program if Just-In-Time (JIT) debugging is enabled. If the user selects Ignore, assert continues with its normal execution: creating the message box with the OK button. Note that choosing Ignore when an error condition exists can result in “undefined behavior.” For more information, see Using C Run-Time Library Debugging Support.  The assert routine is available in both the release and debug versions of the C run-time libraries. Two other assertion macros, _ASSERT and _ASSERTE, are also available, but they only evaluate the expressiosn passed to them when the _DEBUG flag has been defined.   Example  /* ASSERT.C: In this program, the analyze_string function uses  * the assert function to test several conditions related to  * string and length. If any of the conditions fails, the program  * prints a message indicating what caused the failure.  */  #include <stdio.h> #include <assert.h> #include <string.h>  void analyze_string( char *string );   /* Prototype */  void main( void ) {    char  test1[] = "abc", *test2 = NULL, test3[] = "";     printf ( "Analyzing string '%s'\n", test1 );    analyze_string( test1 );    printf ( "Analyzing string '%s'\n", test2 );    analyze_string( test2 );    printf ( "Analyzing string '%s'\n", test3 );    analyze_string( test3 ); }  /* Tests a string to see if it is NULL, */  /*   empty, or longer than 0 characters */ void analyze_string( char * string ) {    assert( string != NULL );        /* Cannot be NULL */    assert( *string != '\0' );       /* Cannot be empty */    assert( strlen( string ) > 2 );  /* Length must exceed 2 */ }   Output  Analyzing string 'abc' Analyzing string '(null)' Assertion failed: string != NULL, file assert.c, line 24  abnormal program termination   Error Handling Routines |  Process and Environment Control Routines  See Also   abort, raise, signal, _ASSERT, _ASSERTE, _DEBUG

顶顶

引用 1 楼 shenchenman 的回复:1 断言有中断的效果 2 这种退出方式指的是什么？断言不需要退出 3 return是退出函数，exit是退出进程  1、请问有中断的效果是神马意思？ 2、断言不是判断错误就马上退出吗？ 3、这个大概能理解，那abort呢？


Question: 谁有谭浩强C语言学习，急求

谭浩强的视频？？？ 楼主可以看看郝斌的视频，基础性较强

学这个还是看书比较好。

如果你是真的要学C语言而不是为了屁用都没有的计算机二级 完全不建议看谭浩强的

考试才看 谭浩强的c

唉。。。浩强啊，只能说别的专业考级用那个还行，专业的还是别看那个书的好

那玩意儿不是给零基础的人看的，而且书上还有好多错误 看C primer 这个靠谱

怒喷 谭浩强, 没有他中国的IT水平会高一个级别

推荐 c primer

谭C 一生黑  渣书 误人子弟 别看了

坐等楼主和谭浩强被喷。


Question: 中断问题

引用 1 楼 u012061345 的回复:这应该算临界区吧，上锁。 上了锁以后难道会阻断中断的产生吗？

Synchronization Functions The following functions are used in synchronization.        CancelWaitableTimer   CreateEvent   CreateMutex   CreateSemaphore   CreateWaitableTimer   DeleteCriticalSection   EnterCriticalSection   GetOverlappedResult   InitializeCriticalSection   InitializeCriticalSectionAndSpinCount   InterlockedCompareExchange   InterlockedDecrement   InterlockedExchange   InterlockedExchangeAdd   InterlockedIncrement   LeaveCriticalSection   MsgWaitForMultipleObjects   MsgWaitForMultipleObjectsEx   OpenEvent   OpenMutex   OpenSemaphore   OpenWaitableTimer   PulseEvent   QueueUserAPC   ReleaseMutex   ReleaseSemaphore   ResetEvent   SetCriticalSectionSpinCount   SetEvent   SetWaitableTimer   SignalObjectAndWait   TimerAPCProc   TryEnterCriticalSection   WaitForMultipleObjects   WaitForMultipleObjectsEx   WaitForSingleObject   WaitForSingleObjectEx        《Windows核心编程》 《深入解析Windows操作系统-Windows Internals》

这个地方需要写保护吧，上锁，程序跑完这里再解锁

引用 4 楼 richyhuang 的回复:对中断的这种数据操作的最好还是先关中断 ++

对中断的这种数据操作的最好还是先关中断

加锁，用完之后解锁，之后才能被别的进程调用

用锁，处理完这个过程再去执行下面的操作

这应该算临界区吧，上锁。

《Windows核心编程》


Question: 『大一』请教“字符本质是小整形”作何解释？

这样理解可能比较容易些吧，计算机所有的东西都是用二进制表示的，因此一串01表示什么由如何解释它决定。如何解释它是由用户决定的。比如一个4字节当成浮点数，CPU将采用浮点数运算对它进行运算，使用%f输出时，将按照浮点数表示规则转换为十进制数打印出来。比如一个字节当成ASCII字符，当要显示这个字符时（%c指明了要以字符的形式处理），首先会找到这个字节表示的数值（0~255）对应的字符，然后在屏幕上显示出来（文字的编码也是采用的这种逻辑）。所以说字符的本质就是小整数，它是通过整数记录的。

各位所说，给我很大启发！诸位所提的，绝大多数，是我在学校、在课本上闻所未闻的。我想，如果我弄懂了诸位所说，我的水平能有有所提升！再次感谢诸位的热心解惑！[

其次，一个声明为char类型的对象，足以容纳任何基本执行字符集的成员，并且保证为非负值。 ------------------------------------------>其次，一个声明为char类型的对象，足以容纳任何基本执行字符集的成员，当它保存的是基本执行字符集的成员时，保证为非负值。

来C版块这么久，也就这个帖子还有点价值。 首先，尽管历史上我们经常用char类型的对象来保存单个字符，但char类型是整数类型的一种。事实上，char、带符号整数类型、无符号整数类型和枚举类型，合称整数类型。将char类型看成是小整型，可能是作者自己的说法，在标准中没有这一个术语，他的意思是char类型的长度，是所有整数类型中最小的。 其次，一个声明为char类型的对象，足以容纳任何基本执行字符集的成员，并且保证为非负值。但是，char类型的对象并非仅仅针对ASCII，因为C允许多种字符集。那种认为char类型的对象保存的是ASCII字符的说法，无论从哪方面来说都是荒谬的。 再次，char类型是单字节的，它可能等效于unsigned char，也可能等价于signed char，到底是哪种，由C的实现决定。但是，不管怎样，char、signed char和unsigned char是三种截然不同的类型，而且互不兼容。 最后，char类型的最大值和最小值是实现定义的。未必象楼上有些人所说，毕竟一个字节包含多少比特（经常是8个），随处理器架构的不同而异。在有些机器上，一个字节是9个比特。一个字节所包含的比特数，以及char类型的取值范围，是在头文件<limits.h>中定义的。

这个说法也只能在某种条件下成立，“本质”这个词不能随便用，要说本质，无类型才是本质。

初接触计算机语言，都会感觉是一堆英文符号英文代码，但随着你对计算机体系的学习理解，你在看代码眼前出现的、感知的就不单单是文字代码，而有相应的空间、时间概念。知道源代码如何一步一步转换成机器识别机器码，知道机器代码如何存储，又是如何一步一步运行的。

我们老师没这么讲过。。

引用 楼主 u012310873 的回复:课余看《C和指针》做些拓展的时候，读到这么一句话“字符本质是小整形。”有点困惑，去百度查了之后，更糊涂了！cha型r与ASII相关，占一个字节，而ASII转换为二进制数。int型占两个字节，直接转换成二进制数。char的二进制表现范围在int型的范围之内，所以”字符本质是小整形“。那么，照这么说，int型不也就是小double型了吗？ 上述所说，可能存在严重错误，还请为我指出解惑！感谢！  你以为计算机里面能存 a b c d ？ 只有0和1罢了

先 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\*.*

引用 13 楼 sholber 的回复:[quote=引用 12 楼 FrankHB1989 的回复:] 说到底“字符本质是小整形”这种如果要说合理性也就是char是integer type而已，其它可以无视。 int型占两个字节更是经典胡扯。 现行ISO C规定： 1.有符号整数用原码反码补码之一表示，除了char等少数约定的类型外可以有padding； 2.int至少能表示得下32767，至于具体多大，没说； 3.一个字节的位数CHAR_BIT >= 8。 而大多数你碰得到的现实实现是这样的：补码表示；CHAR_BIT == 8；无padding；32位环境下sizeof(int) == 4（64位下不少还是一样）。 所以扯int两个字节的乱七八糟的玩意儿没什么参考价值。切记要尝试预估想要查证的资料的可靠性和权威性，不要乱投医。 另外，基本执行字符集也不见得是ASCII。主要的反例是EBCDIC。上来动辄扯ASCII跟char值的东西大多也就只能一笑了之了。 说实话就是C本身还好，ISO C算是公认的没被实现架空的规范（M$奇葩不论），也就谭×之类能骗骗小白。其它一些地方不靠谱的说法太多太乱了，大部分用户也未必需要搞清楚——也未必有机会搞清楚。比如关于reentrancy跟thread safety的定义涵盖，POSIX跟Qt文档使用的定义下的结论刚好相反。这时候还得搞清楚语境判断上下文再作结论。 所以10L赵老湿之类怎么放置play的正确姿势应该不难理解了吧。 +1 这两段话说得我好舒坦。老幻近来可好？[/quote] 偶尔教育些Lisp水群里的易经厨，看看yinwang的不定期娱乐材料，倒也乐呵得马马虎虎。

引用 12 楼 FrankHB1989 的回复:说到底“字符本质是小整形”这种如果要说合理性也就是char是integer type而已，其它可以无视。 int型占两个字节更是经典胡扯。 现行ISO C规定： 1.有符号整数用原码反码补码之一表示，除了char等少数约定的类型外可以有padding； 2.int至少能表示得下32767，至于具体多大，没说； 3.一个字节的位数CHAR_BIT >= 8。 而大多数你碰得到的现实实现是这样的：补码表示；CHAR_BIT == 8；无padding；32位环境下sizeof(int) == 4（64位下不少还是一样）。 所以扯int两个字节的乱七八糟的玩意儿没什么参考价值。切记要尝试预估想要查证的资料的可靠性和权威性，不要乱投医。 另外，基本执行字符集也不见得是ASCII。主要的反例是EBCDIC。上来动辄扯ASCII跟char值的东西大多也就只能一笑了之了。 说实话就是C本身还好，ISO C算是公认的没被实现架空的规范（M$奇葩不论），也就谭×之类能骗骗小白。其它一些地方不靠谱的说法太多太乱了，大部分用户也未必需要搞清楚——也未必有机会搞清楚。比如关于reentrancy跟thread safety的定义涵盖，POSIX跟Qt文档使用的定义下的结论刚好相反。这时候还得搞清楚语境判断上下文再作结论。 所以10L赵老湿之类怎么放置play的正确姿势应该不难理解了吧。 +1 这两段话说得我好舒坦。老幻近来可好？

主要原因归根结底大概是因为渣UNIX天生就混淆character跟byte的概念。 大约他们本来以为1个byte就能表示所有character了，所以把该叫byte的东西叫成了char。 经过各种胡乱设计和妥协，后来的结果就是C的char跟signed char和unsigned char是存储保证是1个byte的三种不同的整数类型。char专用于表示character，在算术操作中是不是有符号看实现高兴（或者你知道怎么艹编译选项）。 后来嘛，I18N需求出来了，如意算盘破产了，C94的multibyte character糊弄乱了，结果闹出个跟char类似废柴的wchar_t。只不过没signed wchar_t和unsigned char_t，不是内建类型罢了。再后来知道wchar_t的大小不确定不靠谱，于是不得不整出char16_t跟char32_t，姑且在假定CHAR_BIT==8以及实现不多留padding的基础上能做到ABI兼容了。 PS.C艹也逃不了，差别只是wchar_t、char16_t和char32_t是内建类型。结合权威定义，照样有“多字节字符”不是“字符”的搞笑逻辑。 PS2.Java的char在某种意义上更搞笑，因为有奇葩的UTF变种问题。不过编码之类的，LZ倒也未必需要急着了解了。

对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

引用 1 楼 caozhy 的回复:单字节的char相当于一个字节，或者一个表示0~255或者-127~127的整数。（所谓的“小整型”） 双字节的char相当于两个字节，或者short/ushort（在x86系统上的编译器上） 理论上说，double使用4个字节表示，也可以算“整型”。但是我们一般不这么看，因为char和整型有类似的一面，它都表示一个序数。比如'A'，它相当于“第65号字符”。而double对于整数的映射关系复杂的多。  不是“相当于”一个字节，它就是一个字节； “表示0~255或者-127~127的整数”：这么精确，你是怎么知道的？ “双字节的char相当于两个字节”：char是单字节的，还有双字节的？你说的是wchar_t吧？ 什么叫“理论上说”，这东西只取决于实现，没听说过取决于理论的。double就是浮点数，怎么会算是整型？这关系太复杂了，类型概念混乱……char本来就是整型，什么叫有类似的一面？char为什么必须表示一个序数？'A'凭什么是65号字符？

char可以表示0~127的整形数值，所以可以说是小整形 char, short, int, long这些有可比性，double是浮点数，内存存储编码格式是不同的


Question: C语言题目，我是新手，学到结构体加上指针有点迷茫，能否帮我看下这编程有什么错

#include <stdio.h> struct student {     int num;     char name[20];     float score; }; void input(struct student *p) {     int i;     for(i=0;i<4;i++)         scanf("%d %s %f",&(p+i)->num,(char *)&(p+i)->name,&(p+i)->score); } struct student * zuida(struct student const *p) {     int i= 0;     struct student *temp;     temp=p;     //temp.score=p ->score;     for(i=1;i<4;i++)         if((p+i) ->score >temp ->score)         {             temp =p+i;         }     return temp; } void output(struct student *p) {     printf("分数最高者:%s\n",p ->name);     printf("学号:%d\n",p ->num);     printf("成绩:%f\n",p ->score); } int main() {     struct student stu[4];     struct student *pr,*ptr;     pr=stu;     input(pr);     ptr = zuida(pr);     output(ptr);     return 0; }

引用 8 楼 cocodada 的回复:#include <stdio.h> struct student { 	int num; 	char name[20]; 	float score; }; void input(struct student *p) { 	int i; 	for(i=0;i<2;i++) 	{ 		scanf("%d %s %f",&(p+i)->num,&(p+i)->name,&(p+i)->score); 		//printf("%d %s %f",(p+i)->num,(p+i)->name,(p+i)->score); 	} } student zuida(struct student *p) { 	int i; 	student max; 	max=*p; 	for(i=1;i<2;i++) 		if(p[i].score>max.score) 		{ 			max=p[i]; 		} 	return(max);		 } void output(struct student p) { 	///printf("%f",*p); 	//for(int i=0;i<2;i++) 	printf("%d %s %f\n",p.num,p.name,p.score); } int main() { 	struct student *pr = new student[2]; 	//pr=&stu[2]; 	input(pr); //	printf("%f\n",); 	output(zuida(pr)); 	delete []pr; 	return 0; } 把zuida的返回值改一下 引用 8 楼 cocodada 的回复:#include <stdio.h> struct student { 	int num; 	char name[20]; 	float score; }; void input(struct student *p) { 	int i; 	for(i=0;i<2;i++) 	{ 		scanf("%d %s %f",&(p+i)->num,&(p+i)->name,&(p+i)->score); 		//printf("%d %s %f",(p+i)->num,(p+i)->name,(p+i)->score); 	} } student zuida(struct student *p) { 	int i; 	student max; 	max=*p; 	for(i=1;i<2;i++) 		if(p[i].score>max.score) 		{ 			max=p[i]; 		} 	return(max);		 } void output(struct student p) { 	///printf("%f",*p); 	//for(int i=0;i<2;i++) 	printf("%d %s %f\n",p.num,p.name,p.score); } int main() { 	struct student *pr = new student[2]; 	//pr=&stu[2]; 	input(pr); //	printf("%f\n",); 	output(zuida(pr)); 	delete []pr; 	return 0; } 把zuida的返回值改一下我不行你能运行

引用 11 楼 mcmay 的回复:#include <stdio.h>  struct student {     int num;     char name[20];     float score; };  void input(struct student * p[], int n) {     int i;      for(i=0; i< n; i++)     {         puts("Enter data in the order of student No. name score:");         scanf("%d%s%f", &p[i]->num, &p[i]->name, &p[i]->score);     } }  struct student * zuida(struct student * p[], int n) {     int i;     struct student * max;      max = p[0];     for(i = 1; i < 4; i++)         if(p[i]->score > max->score)             max = p[i];      return max; }  void output(struct student * p) {     printf("Highest mark: %f", p->score); }  int main(void) {     struct student stu[4];     struct student * pr[4];     struct student * max;     int i;      for(i = 0; i < 4; i++)         pr[i] = &stu[i];     input(pr, 4);     max = zuida(pr, 4);     output(max);      return 0; }  改一下： Line 17 scanf("%d%s%f", &p[i]->num, p[i]->name, &p[i]->score); //去掉&p[i]->name的&

接着往下看了下，你对指针和数组还没弄清楚  main() { struct student stu[4];//数组名就是代表的数组的首地址 struct student *pr; pr=&stu[4];//你在这里把pr指向了一个超过数组边界的地址， //数组的成员分别是stu[0]-stu[3]，stu[4]已经越界 input(pr); zuida(pr); output(pr); }

你的output函数 传递的就是pr的首地址，所以output无论如何都是打印的是第一个元素的内容，对你的zuida函数做了修改，返回最大分数的那个结构体的地址，调用output函数时，把最大的地址传进去  student * zuida(student *p) { 	student *tmp=p; 	for(i=1;i<4;i++){ 		if(tmp->score < p[i].score) 			tmp=p+i; 	} 	return tmp; }  //main函数其余部分省略 output（zuida（pr））；//zuida函数的返回值作为output函数的参数

我要的不是这种效果额，昨晚我自己改过，变成这样 #include <stdio.h> struct student { 	int num; 	char name[20]; 	float score; }; void input(struct student *p) { 	int i; 	for(i=0;i<4;i++) 	scanf("%d%s%f",&(p+i)->num,(p+i)->name,&(p+i)->score); } void zuida(struct student *p) { 	int i,temp=0; 	float max; 	max=p->score; 	for(i=1;i<4;i++) 	if((p+i)->score>max) 	{ 		max=(p+i)->score; 		temp=i; 	} } output(struct student *p) { 	printf("\nthe maximum score:\n"); 	printf("NO.:%d\nnmae:%s\nscore:%4.1f\n",p->num,p->name,p->score); } main() { 	struct student stu[4]; 	struct student *pr; 	pr=&stu[4]; 	input(pr); 	zuida(pr); 	output(pr); }  我要的效果是，写入4个人的信息，然后通过zuida这个函数，查出最大者，然后把最大者的号码，名字，和分数写出来  但我弄了一晚，还是不知道怎么在zuida 函数那里把最大者的地址传给主函数，他老是传初始地址

#include <stdio.h> struct student { 	int num; 	char name[20]; 	float score; }; void input(struct student *p) { 	int i; 	for(i=0;i<2;i++) 	{ 		scanf("%d %s %f",&(p+i)->num,&(p+i)->name,&(p+i)->score); 		//printf("%d %s %f",(p+i)->num,(p+i)->name,(p+i)->score); 	} } float zuida(struct student *p) { 	int i; 	float max; 	max=p->score; 	for(i=1;i<2;i++) 		if(p[i].score>max) 		{ 			max=p[i].score; 		} 	return(max);		 } void output(struct student *p) { 	///printf("%f",*p); 	for(int i=0;i<2;i++) 		printf("%d %s %f\n",(p+i)->num,(p+i)->name,(p+i)->score); } int main() { 	struct student *pr = new student[2]; 	//pr=&stu[2]; 	input(pr); 	printf("%f\n",zuida(pr)); 	output(pr); 	delete []pr; 	return 0; } 改了一下，现在运行可以了

调用函数scanf获取输入参数时，取变量地址应该用&，而不是*

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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

pr=&stu[4]; 這句話沒必要  stu就是代表 數組的首地址。 #include <stdio.h>   2    3 struct student   4 {   5    int num;   6    char name[20];   7    float score;   8 };   9   10 void input(struct student *p)  11 {  12     int i;  13     for(i=0;i<4;i++)  14     scanf("%d%s%f",&(p+i)->num,(p+i)->name,&(p+i)->score);  15     for(i = 0; i < 4; i++)  16     printf("%d\t%s\t%f\n", (p+i)->num , (p+i)->name, (p+i)->score);  17 }  18   19 float zuida(struct student *p)  20 {  21     int i, n;  22     float max;  23     max=p->score;  24       for(i=1;i<4;i++)  25     {  26         if((p+i)->score > max)  27         {  28             max=(p+i)->score;  29             n = i;  30         }  31     }  32     printf("%d\t%s\t%.2f\n", (p+n)->num, (p+n)->name, (p+n)->score);  33 }  34   35 int main()  36 {  37     struct student stu[4];  38     input(stu);  39     printf("***********the max*******************\n");  40     zuida(stu);  41     return 0;  42 }


Question: C语言

是不是为了研究怎么攻击缓冲区溢出？

不知道楼主是为了一些技巧性的东西还是说没有注意到 arr是一个5个元素的数组，而传递给函数的是一个8个元素的数组 存在着明显的越界访问

我感觉他说的修改arr[5]就是修改*(p+5)吧

arr数组的上界为arr[4],你要修改arr[5]????arr[5]的内存都不是你家的，你怎么改？？

fic的实参数组arr大小为5，最后一个元素为arr[4]，对arr[5]进行的写操作内存越界了。

怎么没修改值啊，我编译了一下变成6了啊

因为内存里： |           |             |            |            |            |    | arr[0]    arr[1]    arr[2]    arr[3]    arr[4]    p 所以arr[5] = p 虽然fic里面给arr[5]赋了6但是 p = fic(arr)又把值写入了arr[5],所以总是等译arr的指针地址

引用 13 楼 baichi4141 的回复:[quote=引用 9 楼 u014296991 的回复:] 回复#2：能否解释一下把五位数组的实参赋给八位数组的形参，在内存中发生了什么，函数执行结束后又发生了什么，具体说下怎么就等译为arr的地址。。。。。。 回复#3：请问你用的什么编译器，我的怎么一直不对 回复#4：可为什么只有arr【5】没有修改成功 回复#5：可为什么只有arr【5】没有修改成功 回复#6：是的 回复#7：故意这么干的 回复#8：需要一个函数，传递给函数一个5位数组，根据法则扩展为8位，当然要修改传递的数组本身。。。 数组不能整体操作，大多数时候隐式转化为指向其首元素的指针再进行运算，包括使用[]操作符的时候 所以，你传的实参不是数组a，而是一个指向a[0]的临时指针 同理，形参里写int a[8]和int a[80000]，没有任何区别，编译器根本就不看后面那个数，所有int a[n]等价于int*a 至于“根据法则扩展为8位”，真没听过这种法则  a[5]是p的值，p=fic()这里在fic函数结束后又一次给p赋值，你之前写的那个6被覆盖了，想看到具体过程可以断点调试，在fic函数返回前a[5]应该是6[/quote]  +1

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

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

引用 9 楼 u014296991 的回复:回复#2：能否解释一下把五位数组的实参赋给八位数组的形参，在内存中发生了什么，函数执行结束后又发生了什么，具体说下怎么就等译为arr的地址。。。。。。 回复#3：请问你用的什么编译器，我的怎么一直不对 回复#4：可为什么只有arr【5】没有修改成功 回复#5：可为什么只有arr【5】没有修改成功 回复#6：是的 回复#7：故意这么干的 回复#8：需要一个函数，传递给函数一个5位数组，根据法则扩展为8位，当然要修改传递的数组本身。。。 数组不能整体操作，大多数时候隐式转化为指向其首元素的指针再进行运算，包括使用[]操作符的时候 所以，你传的实参不是数组a，而是一个指向a[0]的临时指针 同理，形参里写int a[8]和int a[80000]，没有任何区别，编译器根本就不看后面那个数，所有int a[n]等价于int*a 至于“根据法则扩展为8位”，真没听过这种法则  a[5]是p的值，p=fic()这里在fic函数结束后又一次给p赋值，你之前写的那个6被覆盖了，想看到具体过程可以断点调试，在fic函数返回前a[5]应该是6

常量的值不能改

你那個 fic（int  a [8]） 這個8 是沒有什麽意義的， 形參  數組是根據傳進來的數組個數為準的！

因为arr[5]是一个数组中的某个变量，而*flc是指针函数  两个不同类型


Question: C语言，数组用什么函数，计算数组长度？

int a[10]={12,54,6,23,7,5,9,89,10,34}; 1 可以用strlen函数：头文件在＃include<string.h>  // int b=str(a); 2 可以用sizeof,例如：sizeof(a)//求出的是数组a总的字节长度。

用 sizeof（array）获得整个数组占用大小 sizeof（array）/sizeof(ArrayType)获得数组长度

函数的话是strlen,头文件在<string.h>,如果是计算字节个数用sizeof(array)/sizeof(array[0])

个数乘以每个的大小

int  arr[xxx];  可以sizeof. int *p = new int[xx]  你个人用变量记

sizeof获取长度

咱也学习一下，请百度搜索相关关键字

c语言中，定义数组后可以用sizeof命令获得数组的长度（可容纳元素个数） 如： { int data[4]; int length; length=sizeof(data)/sizeof(data[0]);  //数组占内存总空间，除以单个元素占内存空间大小 printf("length of data[4]=%d", length ); //输出length of data[4]=4 } 但，通过传递数组名参数到子函数中，以获得数组长度是不可行的。如： int getLength(int[] a){     int length;     length=sizeof(a)/sizeof(a[0]); //这样是错误的，得到的结果永远是1     return length; } 因为，a是函数参数，到了本函数中，a只是一个指针（地址，系统在本函数运行时，是不知道a所表示的地址有多大的数据存储空间，这里只是告诉函数：一个数据存储空间首地址），所以，sizoef(a)的结果是指针变量a占内存的大小，一般在32位机上是4个字节。a[0]是int类型，sizeof(a[0])也是4个字节，所以，结果永远是1。 因此，获得数组长度，只能在数组定义所在的代码区中，采用以上方法，才可以达到效果。

对静态的数组，sizeof(a)/sizeof(a[0]) countof是vc的宏定义。  动态申请的，没有。默认用户自己知道。

#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))

//计算占用内存大小 sizeof(array)   //计算数组元素个数 sizeof(array) / sizeof(array[0]) sizeof(arry) / sizeof (datatype) //直接使用数据类型作为参数

请组织好你的语言

引用 29 楼 cauc_guidian 的回复:可以自己写个for循环的函数，计算数组遇到\0时i的值，i就是数组的长度 不是字符串才以\0结尾么 我觉得可以定一个标志为数组结束标志。到标志返回位置比较好把

引用 10 楼 yiyefangzhou24 的回复:char str[1024]； 1024不就是长度？ emmm那如果是str[ ],长度是多少呢？

引用 8 楼 zhao4zhong1 的回复:最稳妥的办法是程序自己负责用变量记住或函数参数传递数组大小。+1,sizeof在函数调用的时候不适合,strlen只能用于char

C语言，数组用什么函数，计算数组长度？  ????? 在CSDN，没见到一个遣词造句像样的学生。现在的大学生语言文字学得不好啊。 “C语言用什么函数计算数组的长度”，这样说不好吗？

四楼正解,先用sizeof(array)求出整个数组张勇的内存空间,再用sizeof(array[0])求出单个元素所占内存空间,两者相除即长度

如果是字节数组，你们这些方法全部无效，字节数组中间就可能出现\0，一般使用字符串数组，就是strlen计算，字节数组的话，局部的都是记住长度，全局的用宏定义记住长度

受教。四楼。


Question: 求教字符指针作为函数参数的问题

你到底在多少个论坛发啊，在阿莫上也看到你发。去阿莫论坛看看吧。

0xC0000005一般都是内存访问越界

#include<stdio.h> #include<malloc.h> #include<stdlib.h> void catstr(char *dest,char *src);  int main() { char *dest, *src;//="help you?"; char *ch1,*ch2;//记录分配内存地址 ch1 = src =(char *)malloc(256); sprintf(src,"%s","help you?"); if((ch2 = dest=(char *)malloc(80))==NULL) { printf("no memory\n"); exit(1); } sprintf(dest,"%s","Can I "); //dest="Can I "; catstr(dest,src); puts(dest); free(ch1); free(ch2); return 0; }  void catstr(char *dest,char *src) { int i=0; while(*dest)	dest++; for(i=0;i<9;i++) { *dest = *src; src++; dest++; } *dest = '\0'; } //Can I help you?

引用 6 楼 stack009 的回复: #include<stdio.h> #include<malloc.h> #include<stdlib.h> void catstr(char *dest,const char *src);  int main() { char dest[30]="can i"; char src[20]=" help you? "; char *str; catstr(dest,src); puts(dest); system("pause"); return 0; }  void catstr(char *dest,const char *src) { while(*dest)   dest++;	 while(*dest++=*src++)    ;  *dest='\0';   } 你贴出来的代码问题是在是太多，大概就是三楼说的那些问题，我就在你的上面修修改改了一些，你看对你是否有一些帮助有用，多谢啊！

引用 3 楼 user-6 的回复:这段代码的问题太多了。 src初始值为help you?,但是后面又重新为指针申请了内存，256字节，没有初始化。 dest申请了内存，80个字节，没有初始化， dest重新指向了字符串can I， 导致原有80字节内存泄露 接下来在cat函数内部，对常量指针dest做运算，在while循环当中，dest已经指向了常量指针的内存结束位置 所以接下来在for循环中产生访问非法内存错误 你说的这本书我没看过。如果你列出的代码是书上源码的话，那么建议你不要再看这本书了。 这本书代码漏洞百出。。。我果然得换书了，手里有c和指针这本经典书，郭天祥写的这本指针太差了

看了3楼评论我把内存那块改了，好歹可以用了……谢大神

我猜楼主经常借东西忘还或还错人或以为东西本来就是自己的不是借别人的。

后续的指针没有释放等等，这些代码风格习惯方面的问题也很严重。 编程中，算法和思路很重要，但是良好的编程风格和习惯更重要。


Question: 无符号运算不会溢出，那会怎样？

UINT_MAX不是给你这样检测的 可以这样 if(a > UINT_MAX - b)。。。  因为UINT_MAX 最大，所以a<= UINT_MAX && b<= UINT_MAX  其实，对于两个无符号数， a,b 之和 c =a+b； 如果无溢出，必有 a<=c && b<=c ； 如果不满足a<=c && b<=c，一定是溢出了。

嗯我弄错了，但是《c陷阱与缺陷》上说: 如果需要检查a+b是否会“溢出”,可以这样做： if(a+b>UINT_MAX）       complain（）； 依据上面这种方法，我这样写： #include <stdio.h> #include <limits.h> int main() {     unsigned a=4294967295,b=1,c;     c=a+b;     printf("%u\n",UINT_MAX);     if(a+b>UINT_MAX)     printf("%u\n",c);//这里不能被执行到！ } 是这本书写错了吗？否则如何检查无符号运算已经溢出？

a、b、c的类型都是unsigned int，计算过程中无需类型提升，而且unsigned int的最大值为#  define UINT_MAX	4294967295U，计算结果也不会溢出。

不会怎么样,全靠自己掌握

UINT_MAX是4294967295 = INT_MAX*2+1


Question: 用gsoap返回结构体数组遇到的问题？怎么只返回了一个结构？

LZ，我也遇到了同样的问题想问下你怎么解决的，你后面贴的代码的客户端和服务端函数和输出参数的数据结构都不一致啊

问题已解决，分享一下。 /**********测试开始**********/ struct ns__card { xsd__string holdername; xsd__string value; };  struct ns__cardList { struct ns__card *__ptr; int __size; };  int ns__testfun(xsd__string bufin,struct ns__cardList *list);  /*服务端程序*/ int ns__testfun(struct soap *soap,xsd__string bufin,struct ns__cardList  *list) { printf("in=[%s]\n",bufin); list->__size =2;   list->__ptr = soap_malloc(soap,list->__size*sizeof(struct ns__card));  int i=0; for(i=0;i<list->__size;i++) { if (i==0) { (list->__ptr+i)->holdername = soap_strdup(soap,"zhangsan"); (list->__ptr+i)->value= soap_strdup(soap,"123"); } else { (list->__ptr+i)->holdername = soap_strdup(soap,"lisi"); (list->__ptr+i)->value= soap_strdup(soap,"789"); } }  for(i=0;i<list->__size;i++) { printf("name=[%s]\n",(list->__ptr+i)->holdername); printf("\n"); } return SOAP_OK; }  /*客户端程序*/ printf("hello\n"); struct ns2__testfunResponse rest; soap_call_ns2__testfun( &soap, server, "","abc" , &rest); printf("size=[%d]\n",rest.list->__sizeitem); int t; for(t=0;t<rest.list->__sizeitem;t++) { //printf("name=[%s]\n",rest.list->item->holdername); printf("name=[%s]\n",(rest.list->item+t)->holdername); printf("name=[%s]\n",(rest.list->item+t)->value); } printf("ok\n"); };

还没有人回答吗，再等等

to u012061345: 服务端写入后，可正常读出。

服务端写进去以后，再读出来看看，有问题吗？

谁有这种例子啊 给出来看看

引用 9 楼 user-3 的回复:int ns__nsGetAccountBankCardList(struct soap *soap,xsd__string accountId,struct ns__GetAccountBankCardListResponse *response) {     response->__size=2;     response->cardList= (struct ns__BankCard **)soap_malloc(soap,sizeof(struct ns__BankCard *)); for(i=0;i<response->__size;i++) {     response->cardList[i]=(struct ns__BankCard *)soap_malloc(soap,sizeof(struct ns__BankCard ));      response->cardList[i])->cardType=CREDIT_CARD;     response->cardList[i])->cardholderName = (char *)soap_malloc(soap,32);     response->cardList[i])->cardholderName = soap_strdup(soap,"zhangsan");  }      for(i=0;i<response->__size;i++)     {            //printf("%d\n",(*response->cardList[i]).cardType);         printf("%s\n",(*response->cardList[i]).cardholderName);         printf("\n");     }     return SOAP_OK; } 此段代码主要改动是在(struct ns__BankCard **)里作了强制类型转换， 这样也不能得到正确结果

引用 6 楼 user-3 的回复:好像是这样的  struct ns__GetAccountBankCardListResponse {   xsd__int __size；     struct ns__BankCard **cardList;  }; 试过这种方式，这种方式客户端输出只能得到__size

我再贴一次服务端代码，现在是这个样子。客户端还是只获取了一个 int ns__nsGetAccountBankCardList(struct soap *soap,xsd__string accountId,struct ns__GetAccountBankCardListResponse *response) {     response->__size=2;     response->cardList= soap_malloc(soap,(response->__size)*sizeof(struct ns__BankCard *));      response->cardList[0]=(struct ns__BankCard *)soap_malloc(soap,sizeof(struct ns__BankCard ));      (*response->cardList[0]).cardType=CREDIT_CARD;     (*response->cardList[0]).cardholderName = (char *)soap_malloc(soap,32);     (*response->cardList[0]).cardholderName = soap_strdup(soap,"zhangsan");      response->cardList[1]=(struct ns__BankCard *)soap_malloc(soap,sizeof(struct ns__BankCard ));      (*response->cardList[1]).cardType=PREPAID_CARD;//DEBIT_CARD;     (*response->cardList[1]).cardholderName = (char *)soap_malloc(soap,32);     //strcpy((*response->cardList[1]).cardholderName,"lisi");     (*response->cardList[1]).cardholderName = soap_strdup(soap,"lisi");      for(i=0;i<response->__size;i++)     {            //printf("%d\n",(*response->cardList[i]).cardType);         printf("%s\n",(*response->cardList[i]).cardholderName);         printf("\n");     }     return SOAP_OK; }

引用 4 楼 user-3 的回复:使用soap_malloc替换malloc,soap_malloc的内存soap_destory会给你释放的 现在已经把malloc改为soap_malloc了，结果还是一样，只能得到第一个结构。问题出在哪了？


Question: 关于字符顺序串的创建和输出。。为什么输入和输出始终对不上啊？

给点分吧，没法下载了！2分也好啊！

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

引用 10 楼 braveboyny 的回复:设置断点单步执行，或者在适当地方用printf查看程序运行情况，这一个程序员猿必会的，像这种小程序就该自己调试调试。 授人以鱼不如授人以渔。就是都是过了，也都没弄出来啊！所以才知道在哪里错了吗？

引用 6 楼 u010915464 的回复:#include<stdio.h>  #include<malloc.h> #include<string.h>//头文件  #define MAXSIZE 30  typedef char elemtype;  typedef struct{      elemtype str[MAXSIZE];      int len;  }SeqString;  //初始化顺序字符串 SeqString *InitStr(SeqString *s){      s=(SeqString *)malloc(sizeof(SeqString)); 	 memset(s,0,sizeof(SeqString));//申请的内存空间里面不知道有什么东西，所以要把他清空      s->len=NULL;      return s;   }    本人调试运行通过，完全没问题了     那你能再帮我看看吗？     SeqString *CreateStr(SeqString *s){     char ch;     printf("输入要输入的字符串（按回车键结束）：");     while((ch=getchar())!='\n')     {         s->str[s->len]=ch;         s->len++;     }     s->str[s->len]='\0';    //最后一个赋值为'\0'表示结束。（这个很重要）     return s; }       int StrInsert(SeqString *s,int pos,int len){     int i,j=0;     SeqString *s2;     s2=InitStr(s2);     s2=CreateStr(s2);                        //为什么这个只能执行到 printf("输入要输入的字符串（按回车键结束）：");这里啊？     if(pos<1||pos>=s->len||len<0||len>s->len-pos+1)     {         printf("位置或者长度错误！\n");         return 0;     }     for(i=s->len;i<pos;i--)     {         s->str[i+len]=s->str[i];     }     for(i=pos-1;i<pos+len;i++)     {         s->str[i]=s2->str[j];         j++;     }     s->len=s->len+len;     s->str[s->len]='\0';     printf("插入子串后的字符串为");     printf("%s\n",s->str);     return 1; }

引用 4 楼 ilikehigame 的回复:#include<stdio.h> #include<malloc.h> #define MAXSIZE 30 typedef char elemtype; typedef struct { 	elemtype str[MAXSIZE]; 	int len; }SeqString; //初始化顺序字符串 SeqString *InitStr(SeqString *s){ 	s=(SeqString *)malloc(sizeof(SeqString)); 	memset(s->str,0,sizeof(s->str)); 	s->len=NULL; 	return s; } //判断是否建立成功 int Judge(SeqString *s){ 	if(s->len==NULL) 	{ 		printf("顺序字符串建立成功.\n"); 		return 1; 	} 	else 		return 0; } //输入字符串 SeqString *CreateStr(SeqString *s){  //这个函数哪里错了，或者其他哪里错输出结果一直和输入不一样啊 	char ch; 	printf("输入要输入的字符串（按回车键结束）："); 	while((ch=getchar())!='\n') 	{ 		s->str[s->len]=ch; 		s->len++; 	} 	return s; }  int Printf(SeqString *s) { 	printf("%s",s->str); 	return 0; } int main() { 	SeqString *s = NULL;	 	s=InitStr(s); 	Judge(s); 	s=CreateStr(s); 	Printf(s); 	system("pause"); 	return 0; } 改一下 vs2010下结果正确memset(s->str,0,sizeof(s->str));是什么意思？麻烦解答下，谢谢

引用 2 楼 u012061345 的回复:str末尾加个'\0'试试。正解，不过我发现了。谢谢！

简单的问题要写这么复杂吗

// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。 //  #include "stdafx.h" #include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<string.h>  #define MAXSIZE 30  typedef char elemtype;  typedef struct{ 	elemtype str[MAXSIZE]; 	int len; }SeqString;  //初始化顺序字符串 SeqString *InitStr(SeqString *s){ 	s = (SeqString *)malloc(sizeof(SeqString));  	if (s != NULL) { 		memset(s, 0, sizeof(s)); 		s->len = 0; 	}  	return s; }  //判断是否建立成功 int Judge(SeqString *s){ 	if (s != NULL) 	{ 		printf("顺序字符串建立成功.\n"); 		return 1; 	} 	else 		return 0; }  //输入字符串 SeqString *CreateStr(SeqString *s){  //这个函数哪里错了，或者其他哪里错输出结果一直和输入不一样啊 	char ch; 	 	printf("输入要输入的字符串（按回车键结束）："); 	while ((ch = getchar()) != '\n') 	{ 		s->str[s->len] = ch; 		s->len++; 	}  	return s; }  int Printf(SeqString *s){ 	printf("%s\n", s->str); 	return 1; }  int main(){ 	SeqString *s = NULL; 	int pos, len;  	s = InitStr(s); 	 	if (!Judge(s)) { 		printf("initial failing!\n"); 		return -1; 	}  	s = CreateStr(s);  	Printf(s);  	return 0; }  /*malloc没有初始化，导致分配内存有脏数据*/

str末尾加个'\0'试试。

Too long to parse. 闪


Question: 关于一个建立二叉树算法里的问题

从原文档中没有看到数组a的定义，但根据赋值操作a[i] = q来判断，a应该为结构体指针数组，定义类似Lnode *a[]

不好意思！个人认为那个向量a[]本身存储的就是地址，它只不过是吧地址重新拿出来罢了！！！ 个人见解！若错勿怒！

强制类型转换？不过，这个整数代表的是一个结构体的地址吗？  int address; struct Node* p; //... p = (struct Node*)address;


Question: cAPI怎么了

引用 7 楼 u012564309 的回复:引用 5 楼 zhao4zhong1 的回复:[quote=引用 4 楼 li582158579 的回复:] graphics.h是在TC下的图像库头文件，在VC下是没有的，如果在VC下想用graphics，推荐楼主使用EasyX。库文件中函数的使用方法会有函数说明文档。http://www.easyx.cn  大哥 你用C做GUI 需要什么[/quote] Win32 API

引用 5 楼 zhao4zhong1 的回复:引用 4 楼 li582158579 的回复:graphics.h是在TC下的图像库头文件，在VC下是没有的，如果在VC下想用graphics，推荐楼主使用EasyX。库文件中函数的使用方法会有函数说明文档。http://www.easyx.cn  大哥 你用C做GUI 需要什么

引用 4 楼 li582158579 的回复:graphics.h是在TC下的图像库头文件，在VC下是没有的，如果在VC下想用graphics，推荐楼主使用EasyX。库文件中函数的使用方法会有函数说明文档。]  什么是 vc ? 是IDE还是语言？

就好比 我用c做 暗黑破坏神 应该会需要一些GUI头文件等等 这些头文件 自己编写的话 感觉 C里没有一个类型表示 此引用直接与显示器的一个位置链接 那么这些头文件去哪里找到 和了解  或者是什么情况

引用 1 楼 user-3 的回复:C语言标准库是国际标准，各个C编译器都应该支持。编译器厂商为了竞争，还会加入一些自己特有的功能。这个graphics.h 就是TC这个编译器所有的。估计楼主用的不是TC，所以找不到这个头文件。 你会用graphics.h吗 ？ 怎么会的 看源代码吗


Question: 运行后得到的，显示出来怎么少了两个数字，而且变成了问号，这是怎么回事？

#include <stdio.h> #include <stdlib.h> #include <string.h>  void main (void) { 	char ch[]="fdsafg8589fs59f376s456f5s621"; 	int *str=new int[sizeof(int)]; 	int i, j=0, k=0;  	 	int jj=0; 	for (i=0; (size_t)i<strlen(ch); i++) 	{ 		jj=int(ch[i]);		 		if ((jj>=48) && (jj<=57)) 		{			 			str[j]=jj; 			j++; 		} 	}  	int n=0; 	int min=0; 	int temp=0;     int l1=0;     int m=0;     for (l1=0;l1<j;l1++)     { 		min=l1; 		for(m=min+1;m<j;m++) 		{ 			if(str[min]>=str[m]) 				min=m;			 		} 		temp=str[l1]; 		str[l1]=str[min]; 		str[min]=temp; 		m=0; 	}	     for(k=0; k<j; k++) 	{ 		 		printf("%c\n",str[k]); 	} }  你在排序的时候没处理好吧，稍微改了一下

数组访问越界 一切行为都是可能发生的 重新为str数组分配足够的空间

Too long to parse.

指针空间分配不足吧

int *str=new int[sizeof(int)]; 改成int *str=new int[strlen(ch)];

你这代码的风格，真是看的头痛啊


Question: 建立二颗二叉树，写算法判断这二颗二叉树是否完全一样,程序编译通过,建立玩第一颗建立第二棵二叉树无法退出输入函数

#include<stdio.h> #include<stdlib.h> #include<string.h> #define maxlen 25  typedef struct BT {   char data;   struct BT *lchild,*rchild; }Bnode,*BTree;  typedef struct queue{   BTree a[maxlen];   int front,rear; }Linkqueue;  Linkqueue que;  //按层次建立二叉树，建立循环队列  void in_queue(BTree t) {    if(que.front==(que.rear+1)%maxlen)      printf("dui man\n");   else    {      que.rear=(que.rear+1)%maxlen;     que.a[que.rear]=t;   } }  BTree out_queue()  //出队列 {    if(que.rear==que.front)   {     printf("dui kong");        return 0;   }   else   {     que.front=(que.front+1)%maxlen;     return(que.a[que.front]);   } }  BTree creat_tree()      //构造二叉树 {   char ch,ch1,ch2; BTree t,p,q;   ch=getchar();   if(ch!='*')     {     p=(BTree)malloc(sizeof(Bnode));     if(!p)  exit(0);     p->data=ch;      in_queue(p);    }   else return NULL;   while(que.front!=que.rear)     {     t=out_queue();     ch1=getchar();     if(ch1!='*')         {       q=(BTree)malloc(sizeof(Bnode));       if(!q)  exit(0);       q->data=ch1;       t->lchild=q;       in_queue(q);     }     else  t->lchild=NULL;     ch2=getchar();     if(ch2!='*')     {       q=(BTree)malloc(sizeof(Bnode));       if(!q)  exit(0);       q->data=ch2;  t->rchild=q;       in_queue(q);     }     else  t->rchild=NULL;   }   return (p); }  char* preorder(BTree t, char *element) //改 char* preorder(BTree t)    //先序遍历 {   //删 不能用自动变量保存输出 char element[maxlen];   //删 不能用自动变量保存下标 int i=0;   if(t)   {       *element++=t->data;//改 element[i++]=t->data;     element=preorder(t->lchild, element);//改 preorder(t->lchild);     element=preorder(t->rchild, element);//改 preorder(t->rchild);   }   *element=0;//加 使字符串结尾为0   return element;//return element; }  char* midorder(BTree t, char *element) //改 char* midorder(BTree t)  //中序遍历 {   //删 char element[maxlen];   //删 int i=0;   if(t)    {       element=midorder(t->lchild,element);//改 preorder(t->lchild);     *element++=t->data;//改 element[i++]=t->data;     element=midorder(t->rchild,element);//改 preorder(t->rchild);   }   *element=0;//加 使字符串结尾为0   return element; }  int main() {   int conclusion1=0,conclusion2=0;   BTree t1,t2;   char pre1[maxlen],mid1[maxlen],pre2[maxlen],mid2[maxlen];//改 char  *pre1,*mid1,*pre2,*mid2;   //分别存储二叉树的先序与中序序列，从而确定两个二叉树是否相等    que.rear=0;   que.front=0;   printf("please input tree one data\n");   t1=creat_tree();  //创建第一个二叉树   getchar();//加 消化回车 没有这行导致“构造第二颗二叉树的时候就是退出不了”   que.rear=que.front=0;   printf("please input tree two data\n");   t2=creat_tree();  // 创建第二颗二叉树   getchar();//加 消化回车   preorder(t1,pre1);//改 pre1=preorder(t1);   midorder(t1,mid1);//改 mid1=midorder(t1);   preorder(t2,pre2);//改 pre2=preorder(t2);    midorder(t2,mid2);//改 mid2=midorder(t2);   conclusion1=strcmp(pre1,pre2);  //比较两棵树的先序序列是否相等   conclusion2=strcmp(mid1,mid2);  //比较两棵树的中序序列是否相等   if(conclusion1==0 && conclusion2==0)     printf(" the two trees equal\n");   else     printf(" the two trees not equal\n");   return 0; }


Question: clock()返回值为什么是零？

引用 9 楼 sd530842780 的回复:或者换一个单核500mhz的cpu，你那张囧脸啊能换换么 人家只是笑得比较灿烂点而已。

或者换一个单核500mhz的cpu，你那张囧脸啊能换换么

引用 5 楼 zhang5476499 的回复:引用 3 楼 FancyMouse 的回复:[quote=引用 2 楼 zhang5476499 的回复:] [quote=引用 1 楼 FancyMouse 的回复:] clock计算的是cpu时间，io挂起等待的时间不算在里面的。但是我的第一个代码没有输入输出，就只有两个for循环之后，就直接输出出程序的时间， 但是它输出0. 你那两个for能用掉多少时间？clock的精度普遍是毫秒级，你那两个for估计几个微秒就算完了。[/quote]但是第二个程序的输出： 1 2    Time= 0.002000 1    Time= 0.002000 1 2 3    Time= 0.002000 1 2 3 4    Time= 0.002000 1 3    Time= 0.002000 1    Time= 0.002000 1 4    Time= 0.002000 1 5 6 7    Time= 0.002000 每个Time的时间为什么相等？[/quote] 你去看clock的文档。你问的问题里面早就有说明。我不想把文档里每一句话重复一遍。

引用 3 楼 FancyMouse 的回复:引用 2 楼 zhang5476499 的回复:[quote=引用 1 楼 FancyMouse 的回复:] clock计算的是cpu时间，io挂起等待的时间不算在里面的。但是我的第一个代码没有输入输出，就只有两个for循环之后，就直接输出出程序的时间， 但是它输出0. 你那两个for能用掉多少时间？clock的精度普遍是毫秒级，你那两个for估计几个微秒就算完了。[/quote]但是第二个程序的输出： 1 2    Time= 0.002000 1    Time= 0.002000 1 2 3    Time= 0.002000 1 2 3 4    Time= 0.002000 1 3    Time= 0.002000 1    Time= 0.002000 1 4    Time= 0.002000 1 5 6 7    Time= 0.002000 每个Time的时间为什么相等？

引用 2 楼 zhang5476499 的回复:引用 1 楼 FancyMouse 的回复:clock计算的是cpu时间，io挂起等待的时间不算在里面的。但是我的第一个代码没有输入输出，就只有两个for循环之后，就直接输出出程序的时间， 但是它输出0. 换几个计算进去再试试就知道了

引用 2 楼 zhang5476499 的回复:引用 1 楼 FancyMouse 的回复:clock计算的是cpu时间，io挂起等待的时间不算在里面的。但是我的第一个代码没有输入输出，就只有两个for循环之后，就直接输出出程序的时间， 但是它输出0. 你那两个for能用掉多少时间？clock的精度普遍是毫秒级，你那两个for估计几个微秒就算完了。

clock计算的是cpu时间，io挂起等待的时间不算在里面的。


Question: C语言创建文件的奇怪现象

永远不要试图去修改常量内存区域。 先申请一个指针，然后分配内存，接着把cao拷贝到指针中，把指针传递给你的addc方法试试。

char* w = "cao"; 一般编译后， w指向的地址在 .rdata段， 默认情况下，该段为只读区域。   对于你这个程序，崩溃 或者异常是正常现象。

char* w = "cao"; 指向的常量，你在试图修改它的内容，出错不足为奇


Question: 获取mfc的EDIT控件上的数据并存储

[quote=引用 楼主 a13728843352 的回复:] 代码如下。  	FILE *p; 	p=fopen("test.bin","w+");  	CString strGetStr; 	GetDlgItem(IDC_EDIT_TEST)->GetWindowText(strGetStr); 	_cprintf("the  buf length is %d \n",strGetStr.GetLength()); 	fseek(p,0,SEEK_SET);//定位文件指针到文件开始位置 	fwrite(strGetStr,strGetStr.GetLength(),1,p); 	_cprintf("the buf get is %s \n",strGetStr);   后面的输出打印完全正确，但是写入文件失败，怎么回事？ fwrite((char*)&strGetStr,strGetStr.GetLength(),1,p);

换成char数组，将CString变量的内容strcpy到数组中，再写入这个字符数组试试


Question: 大一学生求五子棋c语言程序！！！！双人对战就可以

大一就做这种题目，什么学校啊？ 一般来说，大一写程序能入门就不错了

引用 楼主 hjw92695 的回复:求c语言五子棋程序，，有网格棋盘的，，完全不会啊。。。 这个是哪个脑残老师处的题目

我加一下你吧，，大神。。。。求指导

本人毕业时用纯C做了一个五子棋,可以在DOS和WINDOWS上运行的两栖程序,515311445

网上搜的大多看不懂，，我们上学期就编了一些普通的小程序，，这学期就要求五子棋，，压力大啊

这个应该网上一搜一大把吧。


Question: 笔试题求指导

好奇怪的题目啊、、、什么是未定义行为？为什么s++ 后是4 那*s 不应该也是4么？菜鸟对这个问题很感兴趣，望大神耐心讲解一下~~

这提的答案应该是 未定义行为，给数字就答错了。

引用 24 楼 luoxuechengbing 的回复:[quote=引用 2 楼 nadleeh123 的回复:] [quote=引用 楼主 shineyan1991 的回复:] 今天笔试,考了这样一道题  #include <stdio.h>  int main(void)  { 	char *s="123456790"; 	printf("%c,%c",*(char *)((int *)s+++1),*s); 	return 0; }  第一反应,糟糕的代码,但是既然人家出了,我总不能空在哪吧 我写的结果是5,1 printf的调用约定必然是__cdecl,自右向左入栈的,所以右侧输出肯定是1啊;第一个参数中的子表达式s++虽然有求值顺序的问题,但是由于是自右向左入栈的,所以不影响这里的输出啊  可是面试官说是5,2 ,然后我就和他讲嘛,它还是不信,那就跑一下喽,他用的是vs2013,结果竟然是5,2 !!!! 我完全不敢相信啊,然后回家后用ideone在线的编译了一下,果然还是5,1!!! 难不成见鬼了,求教到底是什么原因???莫非vs2013的printf的调用约定不是__cdecl??!! *(char *)((int *)s+++1, 是int指针+1,实际是s+加sizeof(int)个字节,再转回去是字符5,这个好理解,关键就在后面那个s上了.后面的s到底加1还是没加，欢迎各种精通C标准的来讨论。  [/quote]  不对，说错了》。   我看上去 直接认为 是。。。。 s++(+1);怎么就把 int的大小给算进来了。不懂。   可否耐心解释下？[/quote] 自己代码码一下 就知道 不同指针类型 直接+1，看看编译器是不是加的sizeof（类型）

要是考我这样的问题，我该怎么办啊

VC6环境  VS2010环境  VS2013环境  不同编译器，结果不一样。 最后说一句，遇到出这样“灰色地带”题目的傻逼公司，楼主，你直接走就行，考这样的面试题目，即使通过面试了，对你以后的发展也没什么好处。

引用 2 楼 nadleeh123 的回复:[quote=引用 楼主 shineyan1991 的回复:] 今天笔试,考了这样一道题  #include <stdio.h>  int main(void)  { 	char *s="123456790"; 	printf("%c,%c",*(char *)((int *)s+++1),*s); 	return 0; }  第一反应,糟糕的代码,但是既然人家出了,我总不能空在哪吧 我写的结果是5,1 printf的调用约定必然是__cdecl,自右向左入栈的,所以右侧输出肯定是1啊;第一个参数中的子表达式s++虽然有求值顺序的问题,但是由于是自右向左入栈的,所以不影响这里的输出啊  可是面试官说是5,2 ,然后我就和他讲嘛,它还是不信,那就跑一下喽,他用的是vs2013,结果竟然是5,2 !!!! 我完全不敢相信啊,然后回家后用ideone在线的编译了一下,果然还是5,1!!! 难不成见鬼了,求教到底是什么原因???莫非vs2013的printf的调用约定不是__cdecl??!! *(char *)((int *)s+++1, 是int指针+1,实际是s+加sizeof(int)个字节,再转回去是字符5,这个好理解,关键就在后面那个s上了.后面的s到底加1还是没加，欢迎各种精通C标准的来讨论。  [/quote]  不对，说错了》。   我看上去 直接认为 是。。。。 s++(+1);怎么就把 int的大小给算进来了。不懂。   可否耐心解释下？

引用 2 楼 nadleeh123 的回复:[quote=引用 楼主 shineyan1991 的回复:] 今天笔试,考了这样一道题  #include <stdio.h>  int main(void)  { 	char *s="123456790"; 	printf("%c,%c",*(char *)((int *)s+++1),*s); 	return 0; }  第一反应,糟糕的代码,但是既然人家出了,我总不能空在哪吧 我写的结果是5,1 printf的调用约定必然是__cdecl,自右向左入栈的,所以右侧输出肯定是1啊;第一个参数中的子表达式s++虽然有求值顺序的问题,但是由于是自右向左入栈的,所以不影响这里的输出啊  可是面试官说是5,2 ,然后我就和他讲嘛,它还是不信,那就跑一下喽,他用的是vs2013,结果竟然是5,2 !!!! 我完全不敢相信啊,然后回家后用ideone在线的编译了一下,果然还是5,1!!! 难不成见鬼了,求教到底是什么原因???莫非vs2013的printf的调用约定不是__cdecl??!! *(char *)((int *)s+++1, 是int指针+1,实际是s+加sizeof(int)个字节,再转回去是字符5,这个好理解,关键就在后面那个s上了.后面的s到底加1还是没加，欢迎各种精通C标准的来讨论。  [/quote]     问个比较傻缺的问题，为什么  是  s+sizof(int)；       小白看着只知道是， s+(s+1)然后转 int*,然后在转char*   各位不要见笑，我太水了。。平时只去 灌水，，今天。。。。

就是 5 和 1 啊！ （int*）这是一个整形的指针，指针加1 就是加一个步长，int是4个字节，就s++ 后就到4 了，在加1 就到5了

未定义行为，考察你的基础了。

可能是考你先要确定选择哪个编译器。

翻了下书，发现学的全忘了。。。。哎，可悲啊。

兄弟，不是我看不起你，虽然我从没面过试，我也没做过老师，但是这种题目出出来，对吧，有半点意思吗？ 你也好意思拿出来问？C语言刚入门的人都能告诉你，这种题目的编程方式，了解下就算了，拿出来当题目，整个公司的实力也就能知道了

奇葩题目

首先是运算符优先级的问题。 其次是两个表达式谁先计算的问题........

学习了

这个和编译器的计算方式有关，vs2010下也是5,2 它是从左往右算的；

引用 18 楼 ilikehigame 的回复:引用 13 楼 a515360208 的回复:[quote=引用 10 楼 ilikehigame 的回复:] 这个和编译器的计算方式有关，vs2010下也是5,2 它是从左往右算的；不是吧， 你把输出的两个位置换一下，还是2,5好不 你可是试一下看看是1,5还是2,5，光说没用运行一下就知道了！[/quote]既然敢说自然就是运行了的， ，在自己不确定的情况下要先确定

引用 13 楼 a515360208 的回复:引用 10 楼 ilikehigame 的回复:这个和编译器的计算方式有关，vs2010下也是5,2 它是从左往右算的；不是吧， 你把输出的两个位置换一下，还是2,5好不 你可是试一下看看是1,5还是2,5，光说没用运行一下就知道了！

标准的未定义行为

如果int  是兩個字節的系統呢？？？？？？？？？ 答案是毛啊！


Question: 新人第一次发帖，求问下在windows操作系统中，无安装任何c编译器情况下，如何使用记事本编写c程序

linux下缺省安装有c编译器，因为linux作为开源来说，有时候需要编译内核什么的。 windows可不是开源的，没有什么免费的东西给你用。 c代码的编写可以用任何文本编辑器。但是这只是程序代码，它是需要编译为可执行代码来运行的。  这就和语言一样，你不能因为美国人不需要学习英语就懂英语而要求中国人也天生就懂英语。 这里英语就相当于C程序，美国人就是linux，中国人就是windows。

一般linux的发行版都带gcc编译器，但是也有个别没有的，比如fedora的xfce很干净，就需要手动安装gcc！gcc只是GNU的一个工具！ 此外，lz需要注意vim是个文本编辑器。它不是编译器，一个字之差！vim用来编写代码，编译工作还是交给了gcc。但是它是神之编辑器，强大的震撼。用绝了，任何IDE都弱暴了！此外linux的终端也是位window的cmd的dos命令无法比拟的！建议你还是在linux下玩吧。

在线编译器，好用得很涅：http://codepad.org/

上网，在线编译呗。

引用装个编译器难么？ Dev C++ TC BC ++3.1 Win-TC gcc for win32 Watcom C Intel C compiler VS6 VS200x VS201x ……  主要是想问下不装编译器的情况下，能否使用windows系统自带的东西编译

linux自带编译器，Windows不带，所以你写了不能编译啊

有能力的话，可以手动编译.....

用批处理实现个C编译器慢慢撸么。

没编译器你怎么编译程序？

没有编译器怎么编译啊。linux自带gcc的，windows又不自带cl。


Question: C语言提取网页链接，本人小白，求大神指点

引用zhao4zhong1引用yiyefangzhou24感谢两位的耐心回答，顺利毕业了，也找了开发的工作； 本该把源码贴上来，实在不忍睹，不要误导了别的新人

赵老四果然很搞人

建议楼主学习使用抓包工具比如wireshark 建议楼主学习使用正则表达式＋《编译原理》中词法分析＋有限状态自动机 建议楼主学习使用hash_map

最终还是没能做../路径的合成 只做了 /、XX.htm类路径的合成 不知道怎么样。。PS：毕业设计结束给分

QueryInfo

没人说话，是都被我弄得凌乱了嘛？

在《HTTP协议(RFC2616)中文版》中看到的 HEAD 方法和GET 方法一致，除了服务器不能在响应里返回消息主体。HEAD请求响应里 HTTP头域里的元信息（译注：元信息就是头域信息）应该和GET请求响应里的元信息一致。 此方法被用来获取请求实体的元信息而不需要传输实体主体（entity-body）。此方法经常被用 来测试超文本链接的有效性，可访问性，和最近的改变。. HEAD请求的响应是可缓存的，因为响应里的信息可能被缓存用于更新以前那个资源对应缓存 的实体.。如果出现一个新的域值指明缓存的实体和当前源服务器上的实体有所不同（可能因为 Content-Length，Content-MD5，ETag或Last-Modified值的改变），那么缓存（cache）必 须认为缓存项是过时的（stale）。 小白就是要测试连接的有效性，提取信息的办法各位大牛有什么好办法

引用 8 楼 yiyefangzhou24 的回复:http://192.168.20.1:8080/index.jsp 8080就是端口 3Q~~这个懂了  小白还有问：发送HEAD请求后服务器返回的消息类似这样  HTTP/1.1 200 OK Content-Length: 102792 Content-Type: text/html Content-Location: http://lnrsks.com/index.html Last-Modified: Tue, 29 Apr 2014 03:55:10 GMT Accept-Ranges: bytes ETag: W/"9afb78d15e63cf1:f79" Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET Date: Tue, 29 Apr 2014 06:54:00 GMT Connection: close  有什么好办法提取状态码、Content-Length、Content-Type、Last-Modified这些属性呢，小白目前只想到字符串匹配（strstr函数），感觉太丑了，不像规范的样子，是不是有更好的办法？

引用 6 楼 yiyefangzhou24 的回复:[quote=引用 4 楼 junjie2606 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 使用curl库。 curl好像不是VS2010的类库？  还有个新问题，C语言socket怎么获取服务器端口，或者说能获取到使用哪个端口吗？[/quote]web服务不是80端口？[/quote]  默认是80，这个服务器也可以配置其他的端口，下午老师问题怎么没处理端口，不太明白，也有网站端口用的不是80吧，可是忘记在哪见过8080、8081、9000这样的端口

引用 4 楼 junjie2606 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 使用curl库。 curl好像不是VS2010的类库？  还有个新问题，C语言socket怎么获取服务器端口，或者说能获取到使用哪个端口吗？[/quote]web服务不是80端口？

引用 3 楼 yiyefangzhou24 的回复:分析出链接和原始页面路径合并成绝对URL，并存储在可快速查询的数据结构中 这句话着实没弄懂，不过要求你用socket库写的话，也就是对download下来的数据进行字符串处理，不会太难吧  合并路径是的，但是到相对路径的时候不知道怎么确定位置，比如我测试的地址是：www.lnrsks.com时候会获取到相对路径“/HtmlNews/ksdt/ksxw/index.html”我连接到一起就可以得到绝对路径了，但是我用www.lnrsks.com/HtmlNews/ksdt/ksxw/index.html测试的时候也会有“/HtmlNews/ksdt/ksxw/index.html“”这样的相对路径，我记得以前学静态网页的时候可以写成“../../”这样的相对路径我就不知道怎么再去拼新的绝对路径了；  可快速查询的数据结构就是获取到绝对路径以后要减小数据冗余，储存的时候会查找以前的数据，就是为了快速查找到数据设计的存储结构，还没考虑，暂时忽略了。。。

引用 1 楼 zhao4zhong1 的回复:使用curl库。 curl好像不是VS2010的类库？  还有个新问题，C语言socket怎么获取服务器端口，或者说能获取到使用哪个端口吗？

张老师所言极是

使用curl库。


Question: 未初始化的数据段的内容并不放在磁盘上的程序文件中

《Windows PE权威指南》

简单比喻一下，你有一个账本，记录你今年买了多少米； 如果这些米没什么区别，你难道还需要记录每个米粒的信息；  只怕，你连几袋子米，你都不乐意去记录、 只要记录，每次买了几斤米就行了。

未初始化的数据段，只需要知道每个数据的位置和大小就可以了； 位置，多半写入代码的指令中去了； 每个数据大小，如果需要的话，也已经写入代码中了； 所以大小，只需要整个未初始化的数据段的大小即可； 文件里存储这些数据，岂非多余，而且增加文件的空间占用量。


Question: L298控制两个直流电机正转反转程序

虽然不怎么懂. 应该是给一个信号吧, 应该有一个驱动API接口,  给某个地方输入高电平或者低电平, 即可得到不同的方向.

经典的电机驱动控制 IC - L298，百度一下资料漫天。

提醒：小心空回误差。


Question: 结构体中变量定义求助

引用 11 楼 sholber 的回复:[quote=引用 10 楼 mujiok2003 的回复:] 柔性数组：http://ideone.com/Q7d66b 引用 8 楼 a345485527 的回复:是“变长数组”还是“变量长度数组”，我建议称之为“变量长度数组”。当然，这个似乎不是那么重要。哈哈，用的不多，见笑[/quote]  “柔性数组”的说法更不常见。通常，变量长度数组是指： void f (int n) {     int ia [n];     /* …… */ } 这样的数组； 在结构体中，像这样的用法： struct s { int i; char c[]; }; 通常称struct s的成员c为弹性数组，很多人也称之为柔性数组。 纯概念上的不同而已，无所谓啦。[/quote] 是从flexible array member翻译来的。

引用 10 楼 mujiok2003 的回复:柔性数组：http://ideone.com/Q7d66b 引用 8 楼 a345485527 的回复:是“变长数组”还是“变量长度数组”，我建议称之为“变量长度数组”。当然，这个似乎不是那么重要。哈哈，用的不多，见笑[/quote]  “柔性数组”的说法更不常见。通常，变量长度数组是指： void f (int n) {     int ia [n];     /* …… */ } 这样的数组； 在结构体中，像这样的用法： struct s { int i; char c[]; }; 通常称struct s的成员c为弹性数组，很多人也称之为柔性数组。 纯概念上的不同而已，无所谓啦。

引用 4 楼 a345485527 的回复: struct staff    {  	int age; char name[];// 如果还不行的话 写成这样 ，char name[0]，视编译器而定  };  恩 多谢

引用 6 楼 sholber 的回复:[quote=引用 3 楼 a345485527 的回复:] 想用变长数组？要把他放在结构体的最后 是“变长数组”还是“变量长度数组”，我建议称之为“变量长度数组”。当然，这个似乎不是那么重要。[/quote]哈哈，用的不多，见笑

#include "stdio.h" #include "string.h"  struct staff    {     char name[20];     int age;     };  void main() {  struct staff staff1;  staff1.age=20;  strncpy(staff1.name,"jiangchao",19);staff1.name[19]=0;  printf("name:%s\nage:%d\n",staff1.name,staff1.age);   }

引用 3 楼 a345485527 的回复:想用变长数组？要把他放在结构体的最后 是“变长数组”还是“变量长度数组”，我建议称之为“变量长度数组”。当然，这个似乎不是那么重要。

引用 1 楼 user-5 的回复:结构体中不能	char name[];这样定义，你如果想表示char数组的话，可以以使用char *name； 别乱说，看一下3楼和4楼的解释。

想用变长数组？要把他放在结构体的最后

引用 1 楼 user-5 的回复:结构体中不能	char name[];这样定义，你如果想表示char数组的话，可以以使用char *name； 额 char name[]编译是没有错的，int age那一行出错了


Question: 用C语言实现一个功能，急！！

#include <stdio.h> #include <limits.h>  int change_bits(char *pBuf, int length, int Begin, int BitCnt) {     int i = 0;     unsigned int byte_off = 0;     unsigned int bit_off = 0;     char * p = NULL;     unsigned char mask = 0;      if (pBuf == NULL)     {         return -1;     }      byte_off = BitCnt / CHAR_BIT; /* 需要取反的字节数 */     bit_off = BitCnt % CHAR_BIT;  /* 最后1字节需要取反的比特数 */     mask = 0xff << (CHAR_BIT - bit_off); /* 取反比特掩码 */      if (length < (Begin + byte_off + (bit_off != 0)))     {         return -1;     }      p = pBuf + Begin;     for (i = 0; i < byte_off; i++)     {         p[i] = ~p[i];     }      p = p + i;     p[i] = (~p[i] & mask) |     /* 取反n bits部分 */         (p[i] & ~mask);         /* 原始8-n bits部分 */      return 0; }  int main(void) {     int i = 0;     unsigned char buf[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0xed, 0xff, 0x33, 0x33};      printf("buf before changing:\n");     for (i = 0; i < sizeof(buf); i++)     {         printf("0x%02x, ", buf[i]);     }     printf("\n");      change_bits(buf, 9, 4, 6);      printf("buf after changing:\n");     for (i = 0; i < sizeof(buf); i++)     {         printf("0x%02x, ", buf[i]);     }     printf("\n");      return 0; }

我认为函数原型改成：  //[first, last) is expected to be a valid range void fun(char* first, char* last) {     while(first < last)      {            *first = ~*first;            ++first;      } }  更好，更专注于功能身。

int ChangeBuf(char *pBuf, int iLength, int iBegin, int iBitCnt) { 	int i; 	if(iLength<(iBegin+iBitCnt)) 	{ 		//编写超出事件的处理代码 		return -1;//-1表示有超出的情况 	} 	for(i=0; i<iBitCnt; i++) 	{ 		pBuf[iBegin+i]=~pBuf[iBegin+i]; 	} 	return 0;//0表示正常 }


连接pc的串口是uart0 做了RS232电平转换 这个mini2440的手册上有的，所以说pc连的是串口0 你测试字符串发到串口1又没有和pc连通

没有人遇到这样的问题吗？

自己顶一下，希望各位能伸出援助之手

其实我就是简单的测试一下串口1，PC机用串口调试工具连，波特率 数据位 校验位什么的，都和板子设置的一样，但终端上就是什么都不显示。我用轮询的方式发送数据，不是中断。 我的main函数简单：  #include "2440addr.h" #include "uart.h" int main() {    uartini(); //串口初始化    while(1)   {      uart1SendByte('1');   } return 0; }  /******************************************************* 【函数功能】	从串口1发送字符 ********************************************************/ void uart1SendByte(char data2) { 	if(data2=='\n')         {             while(!(rUTRSTAT1 & 0x2));            // Delay(1);                 //because the slow response of hyper_terminal              rUTXH1 = '\r';         }           while(!(rUTRSTAT1 & 0x2));   //Wait until THR is empty.       //  Delay(1);         rUTXH1 = data2; }

信息量太少。 你说板子问题，那就是主机有问题。

我就是根据手册编的啊，寄存器的设置肯定木有问题

看手册，开发板的手册和demo.


Question: 决定学习路线了。。。

楼主加油吧！不过，VC6.0的确。。。建议再装一个比较新的编译器

加油。。。。

Windows.环境下32位汇编语言程序设计(第2版)罗云彬  这个比这个<<windows程序设计>>好  windows程序设计这书里面很多东西没讲清楚甚至没有  如果不是搞游戏开发的话个人不建议学windows编程，想搞应用软件开发的话建议学了C 学JAVA 吧，绝B不是乱说

windows api，啥年代了，小心被坑爹。。。我们都是被vc6.0+API+MFC坑爹过来的，那时候总觉得C，C++就是MFC。。就是windows API，被坑的不行了。。 建议 linux， gcc，记事本+c，c++

现在还有人用“vc 6 英文版”，好屌丝的开发工具。

摸着石头过河

引用 楼主 liweibopa0598 的回复:我的原帖http://bbs.csdn.net/topics/390770090  先从windows api编程开始，一边复习c语言一边学习windows编程，学习教材，windows程序设计。参考教材c专家编程，大话数据结构。学习环境，win7 32位 加vc 6 英文版。为了兼容性可能考虑换xp系统。  目标1，用时6个月把c语言和windows基本原理还有基础数据结构大概搞清楚。  目标2。。。1实现再考虑!  给自己加油吧! linux呢？

引用 楼主 liweibopa0598 的回复:我的原帖http://bbs.csdn.net/topics/390770090  先从windows api编程开始，一边复习c语言一边学习windows编程，学习教材，windows程序设计。参考教材c专家编程，大话数据结构。学习环境，win7 32位 加vc 6 英文版。为了兼容性可能考虑换xp系统。  目标1，用时6个月把c语言和windows基本原理还有基础数据结构大概搞清楚。  目标2。。。1实现再考虑!  给自己加油吧!  为毛一堆人学C喜欢顺带去搞windows编程？ 图形有c++的dx，app有睡下铺，根本没C啥子事。

感觉可行。 不过，既然是复习C语言，那得用CLANG，或者GCC，用VC你就惨了。


Question: 关于UDP 发送图片..

你的图片是jpg还是bmp，好像lin下的bmp在win下显示有问题。你用libjpeg压缩一下传过来应该就可以了。

UDP发送数据不在乎是否丢包，当你的图片中少一个数据包都有可能导致图片打不开，最好使用tcp  另外看楼主的说法好像不是丢包问题，而是打开格式问题，建议试试一楼的方法

估计没处理。

UDP会丢包的，不知楼主是如何处理丢包问题的呢？

你可以用ftp之类的传过去试试看能否打开


Question: 请教一个C语言中sizeof的问题

我没调试   怎么感觉  sizeof(a)/sizeof(int)=1呢？

请研究用数组做函数参数的人思考以下问题： 为什么没人将整个互联网内容作为函数参数传递呢？！

函数传是都是值。。值。。值。。值。。。  其他都是业障。。。

数组作参数，传递的是指针，所以sizeof(a)是等于4的。

如果能够计算数组的大小，那在排序时还要传入数组长度干什么呢

数组在作为函数参数时退化为指针，int b=sizeof(a)/sizeof(int);利用这段求数组大小是错误的，应该在添加个参数来指定数组长度。 #include<stdio.h> void sort(int a[] ,int b){     int temp,n,m;     for(n=0;n<b;n++){         for(m=0;m<b-n;m++){             if(a[m]>a[m+1]){                 temp=a[m];                 a[m]=a[m+1];                 a[m+1]=temp;             }         }     }     for(n=0;n<5;n++){         printf("%d\t",a[n]);     }     printf("\n"); }

直接std::begin和std::end;

gcc编译器下如果这样写的话，你把数组名a传进去的话，我可以告诉你，b的值一定是1； 为什么呢？ 因为数组名做形参的时候，传进来的数组a就是个数组a的地址，你用sizeof（b）得到的是一个指针变量的大小（32位系统下是是4字节，64位系统下是8字节），所以你获取的是b值是1； 而如果你在数组中需要用到数组的大小，在给sort函数天剑一个数组大小的int参数，可以在main函数中用sizeof（a）获取后传给这个参数即可。

引用 10 楼 heimasjx 的回复:a作为数组名，类型应该是指针吧。sizeof求的是该类型内存大小，整形占4个字节，指针在不同的平台上占大小不同，64位机应该就是8个字节，得到的是2。而32位机占8个字节，得到的是1。你这样说不太对吧，很简单，你定义一个数组int a[10]; sizeof(a)/sizeof(a[0])肯定是10，但若函数的形参为数组，实际上是当做指针来处理的，情况就不一样了

在进行函数传参时，你传递的只是数组的首地址而已，并没有将整个数组传过去，你的函数形参列表不论是 *p还是p[],都当做*p来看，所以sizeof(p)==4；

引用 5 楼 u013163178 的回复:#include<stdio.h> void sort(int (&a)[5]) { 	int temp,n,m;  int b=sizeof(a)/sizeof(int);//这段求数组大小 	//t b=4; 	for(n=0;n<b;n++) 	{ 		for(m=0;m<b-n;m++) 		{ 			if(a[m]>a[m+1]) 			{ 				temp=a[m]; 				a[m]=a[m+1]; 				a[m+1]=temp; 			} 		} 	} 	for(n=0;n<5;n++){ 		printf("%d\t",a[n]); 	} 	printf("\n"); } int main(){ 	int a[5]={12,1,22,3,5}; 	sort(a); 	return 0; }    用c++编译器试试 正确答案啊，谢谢

引用 2 楼 u014753262 的回复:怎么可能，我试了一下都是5 我在linux下算得2，今天在windows下用vc6.0得到的是1，就是没得到过5

加油加油加油加油加油

void fsort (int a[], int len);

数组做参数弱化为指针，所以在函数sort中 sizeof(a) == sizeof(int*)

怎么可能，我试了一下都是5

#include<stdio.h> void sort(int a[], int num){     int temp,n,m; //  int b=sizeof(a)/sizeof(int);利用这段求数组大小     int b=num;     for(n=0;n<b;n++){         for(m=0;m<b-n;m++){             if(a[m]>a[m+1]){                 temp=a[m];                 a[m]=a[m+1];                 a[m+1]=temp;             }         }     }     for(n=0;n<5;n++){         printf("%d\t",a[n]);     }     printf("\n"); } int main(){     int a[5]={12,1,22,3,5};     sort(a, sizeof(a)/sizeof(int));     return 0; }   数组做参数的时候，就成指针了。


Question: 鞍点-程序问题

sum=0; 我忘初始化了 请指正鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅鹅


Question: 简单的程序运行不出来，前辈看下

你传入的line指向的内容是常量，不能修改的...

哎，是我不小心char *cl="name1=3d&name2=1";这句是将一个字符串常量赋值给指针常量。C语言在处理的过程中通常将字符串常量处理成静态字符数字。常量是不能修改的

你看看取值有没有问题，像line[x++]的话，如果x=5，则line[x++]是取line[5]，之后x=6。看看这个细节有没有注意到


Question: 关于MP3持续时间获取 window平台 c/c++  有源码  求分析

难道发错地方了？

还有没有人知道  或者告诉我另外一个方法也可以啊 能正确得到MP3的持续时间就可以了 在线等

引用 1 楼 user-1 的回复:不能回答 既然知道mciSendCommand调用出问题 那么你该去查查 mciSendCommand 的平台兼容性如何  64位下怎么调用  顺便看看错误码 是什么错误  我也想去看错误代码提示啊 但是直接程序就挂了 提示指针指向的内存错误 我也百度了好久 没看见这个有什么平台兼容性啊 如果你知道 能告诉我正确的写法吗？


Question: 大家看看我的最小乘积代码有问题吗？我总感觉不对，求证明

如果没有负数，那么结果就是求这些的最小值输出即可 如果有负数，去掉＝0的数据 如果负数的个数是奇数，那么就是求所有数的乘积 如果负数的个数是偶数，去掉最小的负数，求剩余所有数的乘积

@user-2 恩，你说的int 溢出这些我没有考虑 只想确认下单纯从方法上是不是对的？ -------------------------------------------------------------------------- 然后就是max_pos==0的时候（从交界扩展的时候第一个数负，后面都是正），你那个min_from会出问题。但是因为这只是多了个0的candidate，这数据本身有负解，所以不会影响到最终答案，只是那变量的值不是你想要的。  -------------------------------------------------------------------------- 这个表示没有怎么看懂，能详细举个例子解释下否？

溢出我就不考虑了。 你的数据类型是int，我也就假设不会出现0到1的实数。如果会出现的话那整个算法就不对了。 然后就是max_pos==0的时候（从交界扩展的时候第一个数负，后面都是正），你那个min_from会出问题。但是因为这只是多了个0的candidate，这数据本身有负解，所以不会影响到最终答案，只是那变量的值不是你想要的。

#define MIN2(A,B) ( (A>B)?B:A )


Question: [SWU]用函数产生一个字符串

tbmnqvwpxhPPFWJDJKAG5985362495 执行的结果如此 ，能否有改进的措施？

1 #include <stdio.h>   2 #include <stdlib.h>   3   4 void main()   5 {   6         int i, j;   7         char str[1024];   8         srand((int)time(0));   9         for(i=0; i<10; i++){  10                 j       = 97+(int)(26.0*rand()/(RAND_MAX+1.0));  11                 str[i]  = j;  12         }  13        for(i=10; i<20; i++){  14                j        = 65+(int)(26.0*rand()/(RAND_MAX+1.0));  15                str[i]   = j;  16        }  17        for(i=20; i<30; i++){  18                j        = 48+(int)(10.0*rand()/(RAND_MAX+1.0));  19                str[i]   = j;  20        }  21        for(i=0; i<30; i++){  22                printf("%c", str[i]);  23        }  24        printf("\n");  25 } ~ 我这样产生了随机的字符串     但是觉得有很大的缺陷   因为我已经限定了在前面的哪段位置产生什么样的数据

char *RandStr() {       char buf[128]={0};       srand(time(NULL);       for(int i=0;i<127;i++)       buf[i]=rand()%96+32;       return buf; }

为何   这样产生的随机数是 1 #include <stdio.h>   2 #include <stdlib.h>   3   4 void main()   5 {   6         int i, j;   7         for(i=0; i<10; i++){   8                 j       = (int)(10.0*rand());   9                 printf("%d ", j);  10         }  11 }  12 -2147483648

可以这样做：生成1-62的随机数，62=26+26+10，能想出来了吗？

//产生一个包含字母、数字、以及其他字符的字符串 #include <stdio.h> #include <stdlib.h> #include <time.h> #define CN  8 //大写英文字母个数 #define LN  8 //小写英文字母个数 #define NN  8 //数字个数 #define SN  8 //符号个数 char t[CN+LN+NN+SN+1]; char S[33]="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; char *myrandstr() {     int i,n,a,b;     char tc;      for (i=0;i<CN;i++) sprintf(t         +i,"%c",'A'+rand()%('Z'-'A'+1));     for (i=0;i<LN;i++) sprintf(t+CN      +i,"%c",'a'+rand()%('z'-'a'+1));     for (i=0;i<NN;i++) sprintf(t+CN+LN   +i,"%c",'0'+rand()%('9'-'0'+1));     for (i=0;i<SN;i++) sprintf(t+CN+LN+NN+i,"%c",S[rand()%32]          );      n=CN+LN+NN+SN-1;     for (i=n;i>0;i--) {         a=i-1;b=rand()%i;         if (a!=b) {tc=t[a];t[a]=t[b];t[b]=tc;}     }     return t; } int main() {     int i;      srand(time(NULL));     for (i=0;i<10;i++) printf("%s\n",myrandstr());     return 0; } //iWQ*RG7r2)u'9lAJ9t2Vl03d)Ht"5-@/ //^dQPe_R>00Z6H6x3+klGS2=Ewqf/86^) //u>2oR=55?aaj4OXG0:9rX#6+Dv6DDt-= //5Ym?X9_'qDDoe#p5v2M[S8!p8He3I9)+ //81w{`951ScIy=92K@ZMJ[p%@qkdLb7Y} //2oIRnxw6~:84MF;~C|]msWr1Q~9Jb88= //1IV}4x,TpheG[3J4T}g"Pc"3uV]q022! //mH12~+81Kipri5QYUUd|:Oo7B(\e50(` //laHaY=IyIby!J5b?6}Vy25]8B"65%3E" //2>W|33hQQ2vA5ws02J<TkS!1Rlik[[]! //

对，用随机函数生成相应范围内的ascii码值，然后就能得到了

用srand随机生成一些数字，然后转化为相应的字符就是了

哪里不会呢。


Question: IDE安装问题：安装SQL server2005自带vs2005没有模板怎么办？


Question: 十进制转换为N进制（哪里有错，请指正）

那个32是4个字节的二进制位数

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

不是有个itoa的函数吗

for(j=i-1;j>0;j++)         printf("%d",a[j]); 这里仍然以10进制在输出, 那肯定是不能符合你的需求了.  既然 + 48  +55就意思说会转换成字符.  所以int a[32]; 修改成char a[32];   for(j=i-1;j>0;j++)         printf("%d",a[j]); 修改成 printf("%s",a);


Question: 请教：单词计数程序中的if...else if...语句，谢谢！

引用 7 楼 sholber 的回复:对于 if ( 表达式 ) 语句1 else 语句2 若表达式的值不等于0，执行语句1； 若表达式的值等于0，执行语句2； 若语句1是通过一个标号到达的，则不执行语句2：      goto label;      if (0)         label: printf("a.\n");     else         printf("b.\n");  标准里面还允许这种代码存在？？ C，C++果然有点博大精深的味道！！ label:无处不在！

引用 9 楼 wangyang745 的回复:比如当你输入一个1，然后打回车。那么你总共输入了2个字符：‘1’和‘\n’ ;getchar()函数，第一次c=='1'，第二次c==‘\n’ 此时b=='1'于是就会出现lz的结果。 呵呵，明白， 多谢！

引用 6 楼 buyong 的回复:[quote=引用 4 楼 xiazhiqiuyu 的回复:] [quote=引用 1 楼 lm_whales 的回复:] 你这个提问，有点含糊不清：  if 和 else if else 是并列的分支 只有 条件表达式是逐个测试的，执行语句，只会执行一个分支的 一旦任意分支的分支语句执行以后，整个 if  else if else 就执行完成了，其他部分就不再执行了。   if(c1) s1; else if(c2)s2; else s3;  s1,s2,s3;三个语句只有一个能够得到执行。 c1,c2,会挨个测试，直到有一个条件满足（值为为非零） 执行该分支为止。  所有条件都为0， 执行else 分支 即s3 。 无else，在没有一个条件能够满足时，什么也不做。 if 结构是互斥的，只要一个分支执行了，其他分支都不会再执行了。 最前面的条件优先判断，不满足条件，才会继续判断以后的其他条件。 首先，谢谢您的讲解！下面是我做的一个测试if...elseif的小程序，运行结果为hello xx。从结果来看，若if(条件1) elseif(条件2)，条件1和条件2不是判断同一个变量，那么if,elseif后面的语句都会执行，并不是互斥关系了。    不知道是哪里出错或理解有误，请指教! main() { int c; int b = 0; while  ((c = getchar()) != EOF) { if (c == '1') { b='1'; printf("hello\n"); } else if (b == '1') printf("xx\n"); } }  [/quote]  你这个while很有问题呀。你把他改成if,就一次，你就看出来了[/quote]  哦。为什么while 不行呢？谢谢！

引用 4 楼 xiazhiqiuyu 的回复:[quote=引用 1 楼 lm_whales 的回复:] 你这个提问，有点含糊不清：  if 和 else if else 是并列的分支 只有 条件表达式是逐个测试的，执行语句，只会执行一个分支的 一旦任意分支的分支语句执行以后，整个 if  else if else 就执行完成了，其他部分就不再执行了。   if(c1) s1; else if(c2)s2; else s3;  s1,s2,s3;三个语句只有一个能够得到执行。 c1,c2,会挨个测试，直到有一个条件满足（值为为非零） 执行该分支为止。  所有条件都为0， 执行else 分支 即s3 。 无else，在没有一个条件能够满足时，什么也不做。 if 结构是互斥的，只要一个分支执行了，其他分支都不会再执行了。 最前面的条件优先判断，不满足条件，才会继续判断以后的其他条件。 首先，谢谢您的讲解！下面是我做的一个测试if...elseif的小程序，运行结果为hello xx。从结果来看，若if(条件1) elseif(条件2)，条件1和条件2不是判断同一个变量，那么if,elseif后面的语句都会执行，并不是互斥关系了。    不知道是哪里出错或理解有误，请指教! main() { int c; int b = 0; while  ((c = getchar()) != EOF) { if (c == '1') { b='1'; printf("hello\n"); } else if (b == '1') printf("xx\n"); } }  [/quote]  你这个while很有问题呀。你把他改成if,就一次，你就看出来了

感觉他纯是在考验你耐心 @lm_whales

引用 1 楼 lm_whales 的回复:你这个提问，有点含糊不清：  if 和 else if else 是并列的分支 只有 条件表达式是逐个测试的，执行语句，只会执行一个分支的 一旦任意分支的分支语句执行以后，整个 if  else if else 就执行完成了，其他部分就不再执行了。   if(c1) s1; else if(c2)s2; else s3;  s1,s2,s3;三个语句只有一个能够得到执行。 c1,c2,会挨个测试，直到有一个条件满足（值为为非零） 执行该分支为止。  所有条件都为0， 执行else 分支 即s3 。 无else，在没有一个条件能够满足时，什么也不做。 if 结构是互斥的，只要一个分支执行了，其他分支都不会再执行了。 最前面的条件优先判断，不满足条件，才会继续判断以后的其他条件。 首先，谢谢您的讲解！下面是我做的一个测试if...elseif的小程序，运行结果为hello xx。从结果来看，若if(条件1) elseif(条件2)，条件1和条件2不是判断同一个变量，那么if,elseif后面的语句都会执行，并不是互斥关系了。    不知道是哪里出错或理解有误，请指教! main() { int c; int b = 0; while  ((c = getchar()) != EOF) { if (c == '1') { b='1'; printf("hello\n"); } else if (b == '1') printf("xx\n"); } }

引用 1 楼 lm_whales 的回复:你这个提问，有点含糊不清：  if 和 else if else 是并列的分支 只有 条件表达式是逐个测试的，执行语句，只会执行一个分支的 一旦任意分支的分支语句执行以后，整个 if  else if else 就执行完成了，其他部分就不再执行了。   if(c1) s1; else if(c2)s2; else s3;  s1,s2,s3;三个语句只有一个能够得到执行。 c1,c2,会挨个测试，直到有一个条件满足（值为为非零） 执行该分支为止。  所有条件都为0， 执行else 分支 即s3 。 无else，在没有一个条件能够满足时，什么也不做。 if 结构是互斥的，只要一个分支执行了，其他分支都不会再执行了。 最前面的条件优先判断，不满足条件，才会继续判断以后的其他条件。  这位讲解的真是耐心~


Question: 指向函数的指针问题求指导

引用 6 楼 u014768562 的回复:[quote=引用 2 楼 sholber 的回复:] [quote=引用 1 楼 u013803262 的回复:]   y2=internal(f,1,2); 函数f里面没带参数   函数声明可以省略参数列表。 不过，如此一来，float类型的实参都被提升为double了，所以楼主傻了……[/quote] 艾 以前学java 发现基础不太行，现从C学起，请问学了C能做啥工作啊，ps:我不想学c++[/quote] 哈哈，你把分数全给我吧…… 学了C只是刚刚开始。C只是工具，真正重要的，是工具之外的东西。

引用 2 楼 sholber 的回复:[quote=引用 1 楼 u013803262 的回复:]   y2=internal(f,1,2); 函数f里面没带参数   函数声明可以省略参数列表。 不过，如此一来，float类型的实参都被提升为double了，所以楼主傻了……[/quote] 艾 以前学java 发现基础不太行，现从C学起，请问学了C能做啥工作啊，ps:我不想学c++

#include "stdio.h" #include "math.h"  float internal(float (*fun)(float),float a,float b) { float z; z=(*fun)(a)+(*fun)(b); return (z); }  float f(float x) { return (x); } /*自定义函数*/   void main() {   float y1,y2;   //float internal();   //float f();    y1=internal(sin,3.14,3.14);;   y2=internal(f,1,2);   printf("y1=%0.6f\ny2=%f\n",y1,y2); }  y1=0.003185 y2=3.000000

估计又是float问题。 把float都改成double.

float internal(float (*fun)(),float a,float b) 里的float (*fun)(),是不是该指明fun的参数类型float (*fun)(float)

引用 1 楼 u013803262 的回复:y2=internal(f,1,2); 函数f里面没带参数   函数声明可以省略参数列表。 不过，如此一来，float类型的实参都被提升为double了，所以楼主傻了……

y2=internal(f,1,2); 函数f里面没带参数


Question: 哪儿来的野指针？

引用 14 楼 sholber 的回复:[quote=引用 13 楼 lm_whales 的回复:] 严格来说，你的代码不够健壮，没有处理，只有一个参数 ，argv[1] 不存在的情况。 argv[0] 是程序名字，永远存在，argv[1] 必须从命令行传入。 windows 下，一种方式是控制台窗口中输入  文件名 参数 参数。。。。 这样处理。  在IDE中，需要设置命令行参数才能调试。 根据argc ，可以知道有几个命令行参数。  只有在argc大于0时，argv[0]才指向程序名，但这不是保证，更不用说“永远存在”了，因为，如果执行环境不能提供程序名，则argv[0]是空指针。 如果argc大于1，则argv[1]到argv[argc-1]是指向程序参数，由C的实现决定，不一定是啥。[/quote] 哦，这是标准么？ 请问何种情况下argv[0]不存在 固件代码，，，，操作系统，，，

char buffer[128];最好初始化一下！ 输入的文件名太长会出现问题啦！

int main(int argc,char *argv[]) {     if(argc < 2)     {         printf("没有输入文件\n");         return 0;     }     FILE *fp4;     char buffer[128];  开头加个这个

FILE * __cdecl _tfsopen (         const _TSCHAR *file,         const _TSCHAR *mode         ,int shflag         ) {     FILE *stream=NULL;     FILE *retval=NULL;      _VALIDATE_RETURN((file != NULL), EINVAL, NULL);

你用的哪个ide？ vs 是在 工程属性里头. 有个调试，然后你在里面填上就好了 codeblocks 是在project -> setproject parameters里面

VC6：  工程、设置、Debug、U程序变量：填写命令行参数。 VS20XX：  项目、属性、配置属性、调试、命令参数：填写命令行参数。  /* 编写一个通用的显示磁盘文件内容的程序 */ #include <stdio.h> #include <stdlib.h>  int main(int argc,char *argv[]) { FILE *fp4; char buffer[128]; if (argc<2) {     printf("Usage: %s filename.ext\n",argv[0]);     exit(1); } if( (fp4 = fopen(argv[1],"r")) == NULL) //从命令行取文件名，打开文件 { printf("File [%s] can not be opened!\n",argv[1]); exit(1); } while(fgets(buffer,128,fp4)!=NULL)  //读一行字符 printf("%s",buffer); fclose(fp4);     /*关闭文件*/  return 0; }

你是用VS直接调试->开始执行的吧，这样就是没有传入命令行参数的，你可以给生成的exe文件创建一个苦熬接方式，然后在目标那一行后面添加参数，也就是你要读取的文件的路径名，这样就可以了

if( (fp4 = fopen(argv[1],"r")) == NULL)      打开文件这行打一个断点，看一下打开的路径是否正确和fp4指针是否为空

buffer 读入 128 个字符后，没有结束符的位置

断点调试啊，如果只靠浏览代码那找问题麻烦大啦

没问题啊，我运行了一遍

没有任何问题。

/* 编写一个通用的显示磁盘文件内容的程序 */ #include <stdio.h> #include <stdlib.h>  int main(int argc,char *argv[]) { 	FILE *fp4; 	char buffer[128]; 	if( (fp4 = fopen(argv[1],"r")) == NULL) //从命令行取文件名，打开文件 	{ 		printf("File cannot be opened\n"); 		exit(1); 	} 	while(fgets(buffer,128,fp4)!=NULL)  //读一行字符 		printf("%s",buffer); 	fclose(fp4);			/*关闭文件*/  	return 0; }

引用 13 楼 lm_whales 的回复:严格来说，你的代码不够健壮，没有处理，只有一个参数 ，argv[1] 不存在的情况。 argv[0] 是程序名字，永远存在，argv[1] 必须从命令行传入。 windows 下，一种方式是控制台窗口中输入  文件名 参数 参数。。。。 这样处理。  在IDE中，需要设置命令行参数才能调试。 根据argc ，可以知道有几个命令行参数。恩恩，在cmd下，用你的格式，运行通过了，但是再ide下，找不到，设置参数的地方来调试啊。

引用 11 楼 user-15 的回复:如果是vc编译的话，在Project->Setting的Program arguments项中输入参数，gcc的话在程序文件名后面添加要打开的文件名。你的野指针是argv[1]。我的编译器居然在Project->Setting中没有Program arguments项

引用 7 楼 zyaiwx 的回复: #include <stdio.h> #include <stdlib.h>   int main(int argc,char *argv[]) {     FILE *fp4;     char buffer[128];     if( (fp4 = fopen(argv[1],"r")) == NULL) { //从命令行取文件名，打开文件         printf("File cannot be opened\n");         exit(1); 	} 	while(fgets(buffer,128,fp4)!=NULL)  //读一行字符 	    printf("%s",buffer); 	fclose(fp4);            /* 关闭文件*/ 	     return 0; }   你确保你输入文件名了？而且文件名路径正确。 我猜你可能没输入正确的文件路径作为参数 我的测试文件为在编译器编译链接之后，运行就直接弹错误框，根本来不及在命令行输入任何东西。

引用 13 楼 lm_whales 的回复:严格来说，你的代码不够健壮，没有处理，只有一个参数 ，argv[1] 不存在的情况。 argv[0] 是程序名字，永远存在，argv[1] 必须从命令行传入。 windows 下，一种方式是控制台窗口中输入  文件名 参数 参数。。。。 这样处理。  在IDE中，需要设置命令行参数才能调试。 根据argc ，可以知道有几个命令行参数。  只有在argc大于0时，argv[0]才指向程序名，但这不是保证，更不用说“永远存在”了，因为，如果执行环境不能提供程序名，则argv[0]是空指针。 如果argc大于1，则argv[1]到argv[argc-1]是指向程序参数，由C的实现决定，不一定是啥。

你没有传入你要打开的文件吧


Question: C51点亮发光二极管

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

#include<reg52.h> sbit led1=P1^0 void main() {        led1=0; }   写成这样就行了    最好自己写在keil上  别复制粘贴

引用 5 楼 u011314565 的回复:   #include<reg52.h>  void main() { sbit led1=P1^0=0; }  是这个哪里错了  你这个回复真让人抓狂，，，，

你试试将#include放入main(),看看出不出错。因为sbit是一种预处理，需要预处理编译，而不参与编译，所以编译器无法容纳预处理在main()中作为执行的一部分。Ps:C编译过程如下 C源程序－>编译预处理－>编译－>优化程序－>汇编程序－>链接程序－>可执行文件

sbit led1=0;    改成 led1=0;

C51的位变量语法，不同于一般的C的语法 sbit led1=P1^0; /* 初始化 位变量led1, led1的位地址,是p1口的 第0位。这有点C++初始化引用的意思。 */  void main(){ sbit led1=0; /* 既不是位变量赋值，也不是位变量初始化,C51 没有这语法 */ led1= 0; /*这是位变量赋值*/   }

#include<reg52.h>  sbit led1=P1^0; void main() { sbit led1=0;	 //为什么写在这里时编译错误呀  }


Question: 求指教：关于.c文件中TCHAR用法问题

引用 16 楼 weiqiyun1986 的回复:[quote=引用 15 楼 sholber 的回复:] [quote=引用 13 楼 weiqiyun1986 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 10 楼 weiqiyun1986 的回复:] [quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。[/quote]  请问IDE难道不是集成编译器的吗？大神，多动动脑子，少抬杠，多关注问题本身[/quote] 那如果不集成呢？我就经常用code::blocks编辑，然后用clang编译。是你自己糊涂罢了。[/quote]  年轻人，你没看到楼主用的是VS吗？你用的和楼主用的不一样，你经常用什么IDE那是你的问题，难道你经常尿床还能怪到楼主的身上吗？好好跺实下自己的基础，这个论坛是大家讨论学习的地方，不要因为你要抓什么“可用分”而玷污了这块净土，年轻人，敬告你以下，勿要捡了芝麻丢了西瓜，要好好做人，争取早日报销祖国[/quote]  多谢你的忠告，谢谢，尽管错别字特别多，我也不计较。 IDE什么的，一不一样是一回事，说话严不严谨是另一回事。我尿床不会误导别人，你不严谨会误导别人，这就是区别。

引用 15 楼 sholber 的回复:[quote=引用 13 楼 weiqiyun1986 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 10 楼 weiqiyun1986 的回复:] [quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。[/quote]  请问IDE难道不是集成编译器的吗？大神，多动动脑子，少抬杠，多关注问题本身[/quote] 那如果不集成呢？我就经常用code::blocks编辑，然后用clang编译。是你自己糊涂罢了。[/quote]  年轻人，你没看到楼主用的是VS吗？你用的和楼主用的不一样，你经常用什么IDE那是你的问题，难道你经常尿床还能怪到楼主的身上吗？好好跺实下自己的基础，这个论坛是大家讨论学习的地方，不要因为你要抓什么“可用分”而玷污了这块净土，年轻人，敬告你以下，勿要捡了芝麻丢了西瓜，要好好做人，争取早日报销祖国

引用 13 楼 weiqiyun1986 的回复:[quote=引用 11 楼 sholber 的回复:] [quote=引用 10 楼 weiqiyun1986 的回复:] [quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。[/quote]  请问IDE难道不是集成编译器的吗？大神，多动动脑子，少抬杠，多关注问题本身[/quote] 那如果不集成呢？我就经常用code::blocks编辑，然后用clang编译。是你自己糊涂罢了。

引用 12 楼 weiqiyun1986 的回复:[quote=引用 11 楼 sholber 的回复:] [quote=引用 10 楼 weiqiyun1986 的回复:] [quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。[/quote]  你这样说就有些扯淡了，我们只是根据楼主的实际情况得出的结论，给出解决方案。而你只是空谈，没有看到实际的问题[/quote]  你不是扯“语法”问题吗！按语法来你就是说错了。你的意思只不过是VS自己的问题，又不能全怪C的语法。是你自己说不清楚罢了。

引用 11 楼 sholber 的回复:[quote=引用 10 楼 weiqiyun1986 的回复:] [quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。[/quote]  请问IDE难道不是集成编译器的吗？大神，多动动脑子，少抬杠，多关注问题本身

引用 11 楼 sholber 的回复:[quote=引用 10 楼 weiqiyun1986 的回复:] [quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。[/quote]  你这样说就有些扯淡了，我们只是根据楼主的实际情况得出的结论，给出解决方案。而你只是空谈，没有看到实际的问题

引用 10 楼 weiqiyun1986 的回复:[quote=引用 9 楼 sholber 的回复:] [quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准[/quote]  不确定。因为IDE不管编译，它只是一个IDE而已，不是编译器。 不过你也没有说你的话只适用于以前的标准。

引用 9 楼 sholber 的回复:[quote=引用 6 楼 llxxhm 的回复:] 纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。[/quote]  你确定楼主的IDE支持你所谓的最新的C语言标准

权且当我说的纯C是ANSI C吧。

引用 2 楼 zhao4zhong1 的回复:纯C语法要求所有变量声明必须在任何可执行语句之前。 什么叫“纯C”？我只听说过传统的C和标准的C，或者K&R C，C89，C99，C11，或者单纯用C写的程序和混合C与汇编之类的说法，你要表达的是什么？ 在C中，哪些语句类型是不可执行的？算了，你还是说说在C中，“语句不可执行”是什么意思吧。

引用 6 楼 llxxhm 的回复:纯粹语法问题,声明要写在前面  建议你翻翻最新的C语言标准。

引用 5 楼 weiqiyun1986 的回复:赵老湿说的很对，“所有变量声明必须在任何可执行语句之前”。 引用 7 楼 s634772208 的回复:2楼正解，在c中“所有变量声明必须在任何可执行语句之前”   C中哪些语句是可执行的，哪些是不可执行的。说说看。

纯C语法要求所有变量声明必须在任何可执行语句之前。

从代码上来说是不应该有你说的问题的. 我觉得问题应该在于你调换顺序的时候, 哪里弄错了  从这句可以看也来:   “TCHAR”: 将此类型用作表达式非法 它没有提示说是 未声明的标识符, 而是说作为表达式非法.

2楼正解，在c中“所有变量声明必须在任何可执行语句之前”

纯粹语法问题,声明要写在前面

赵老湿说的很对，“所有变量声明必须在任何可执行语句之前”。


Question: 困惑已久的问题，求大神解决

那这个程序是对的了？（我照课本70页改的）

楼上说得不错，基本上看出来了。

引用 20 楼 sholber 的回复:[quote=引用 19 楼 ypzhong 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 不要太钻编译器牛角尖，编译器都不信，难不成你还想自己搞个编译器。<c专家编程>也有讨论标准，但是也没你这么钻牛角尖的，普通标准知识完全可以应付编程。计算机系统那么庞大，c标准只是冰山一角吧。[/quote] 你都不知道我们在讨论什么，瞎掺和什么。 普通标准知识掌握了，一般不会说外行话。说外行话，就是连普通标准知识都不掌握。话说，哪些标准知识属于普通标准知识？ C标准虽然只是冰山一角，C编译器也得遵守不是。不遵守谁还敢用，用VC6的都是些什么人，还不清楚吗？[/quote]  你估计还不知道他的回帖风格，在这里晃荡久了，见他基本上都会流水线作业，回复的都是模版，很有点见人就念阿弥陀佛的感觉，也几乎等于在刷分！都已经习惯了，几乎不看，大道理即使再正确也是太枯燥无聊的！恕我多言

啥啥呀~~什么叫编译器和标准一起讨论是外行…… 不符合标准的编译器报错是好的，很多根本不报错，因为它本身就是有毛病的。 你自认为能写出强壮的代码不行，起码得大家都公认才行。在这个网上发言的，估计没有几个认为自己说的话有毛病，但照样错误百出不是？！

引用 20 楼 sholber 的回复:[quote=引用 19 楼 ypzhong 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 不要太钻编译器牛角尖，编译器都不信，难不成你还想自己搞个编译器。<c专家编程>也有讨论标准，但是也没你这么钻牛角尖的，普通标准知识完全可以应付编程。计算机系统那么庞大，c标准只是冰山一角吧。[/quote] 你都不知道我们在讨论什么，瞎掺和什么。 普通标准知识掌握了，一般不会说外行话。说外行话，就是连普通标准知识都不掌握。话说，哪些标准知识属于普通标准知识？ C标准虽然只是冰山一角，C编译器也得遵守不是。不遵守谁还敢用，用VC6的都是些什么人，还不清楚吗？[/quote] 编译器不要按照标准来编译程序，依据符不符合标准进行报错或者警告，编译器和标准一起讨论是外行？还有我是码农，至少我现在不用看标准能够写出强壮的代码。

引用 19 楼 ypzhong 的回复:[quote=引用 8 楼 sholber 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 不要太钻编译器牛角尖，编译器都不信，难不成你还想自己搞个编译器。<c专家编程>也有讨论标准，但是也没你这么钻牛角尖的，普通标准知识完全可以应付编程。计算机系统那么庞大，c标准只是冰山一角吧。[/quote] 你都不知道我们在讨论什么，瞎掺和什么。 普通标准知识掌握了，一般不会说外行话。说外行话，就是连普通标准知识都不掌握。话说，哪些标准知识属于普通标准知识？ C标准虽然只是冰山一角，C编译器也得遵守不是。不遵守谁还敢用，用VC6的都是些什么人，还不清楚吗？

引用 8 楼 sholber 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 不要太钻编译器牛角尖，编译器都不信，难不成你还想自己搞个编译器。<c专家编程>也有讨论标准，但是也没你这么钻牛角尖的，普通标准知识完全可以应付编程。计算机系统那么庞大，c标准只是冰山一角吧。

1+1=2，这个是数学问题。谈不上现实不现实吧，除非你用的是类比。但是数学是严格的。 C也是严格的。C的标准在修正，跟不上标准的编译器，那是它自己的问题。是编译器要适应标准，而不是相反。

1+1=2在现实世界中不是从来没对过吗？

证明完毕。         11``

引用 13 楼 zhao4zhong1 的回复:不迷信编译器，你能解释下面这段代码是怎么工作的吗？ //仅对VC6 #include <stdio.h> void fun1() {     int f1=1;     printf("fun1\n");     printf("fun1\n"); } void fun2() {     int f2=2;     printf("fun2\n"); } void fun3() { } void main() { #ifdef _DEBUG     printf("sizeof(fun1)==%d\n",*(int *)((int)fun2+1)-*(int *)((int)fun1+1));     printf("sizeof(fun2)==%d\n",*(int *)((int)fun3+1)-*(int *)((int)fun2+1)); //sizeof(fun1)==59 //sizeof(fun2)==43 #else     printf("sizeof(fun1)==%d\n",(int)fun2-(int)fun1);     printf("sizeof(fun2)==%d\n",(int)fun3-(int)fun2); //sizeof(fun1)==32 //sizeof(fun2)==16 #endif }   有回复也不通知一下，真是的！ 没太明白你的意思， void main (... 是不对的搞法。 VC 6居然承认这种搞法， 所以，你用的编译器是不对的， 所以，不能迷信编译器。

这个也同上： #pragma comment(linker,"/SECTION:.text,RW") #include <stdio.h> #ifdef _DEBUG #define OFFSET 0x0C #else #define OFFSET 0x01 #endif int *p; int p2() {     int a;       a=2;     return a; } int main() {     p=(int *)((char *)p2+OFFSET);     printf("p2==0x%08x,p==0x%08x,*p==%d\n",(char *)p2,p,*p);     *p=3;     printf("p2()==%d\n",p2());     return 0; } //p2==0x00401000,p==0x0040100c,*p==2 //p2()==3 //

引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 sholber 的回复:] [quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 我猜你驾船出海时一定带好几个指南针：“指南针真的可信吗？据我所知，每个指南针都曾经有BUG。”[/quote]  这正是人们不迷信指南针的原因。[/quote] 而那个驾船出海带一个指南针的人虽然经过了磁场异常的很多海域，但最终还是比其它带很多指南针且不相信指南针的人更早找到了陆地。[/quote] 能告诉我是谁，在哪天发生的事吗？

引用 10 楼 sholber 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 sholber 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 我猜你驾船出海时一定带好几个指南针：“指南针真的可信吗？据我所知，每个指南针都曾经有BUG。”[/quote]  这正是人们不迷信指南针的原因。[/quote] 而那个驾船出海带一个指南针的人虽然经过了磁场异常的很多海域，但最终还是比其它带很多指南针且不相信指南针的人更早找到了陆地。

引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 sholber 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 我猜你驾船出海时一定带好几个指南针：“指南针真的可信吗？据我所知，每个指南针都曾经有BUG。”[/quote]  这正是人们不迷信指南针的原因。

引用 8 楼 sholber 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  别的我不说了，只说“要迷信编译器”。 你让大家说说，编译器真的可信吗？据我所知，每个编译器都曾经有BUG。[/quote] 我猜你驾船出海时一定带好几个指南针：“指南针真的可信吗？据我所知，每个指南针都曾经有BUG。”

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

这种定义方式是可以的 有于你的max不不需要返回值,直接显示 所以 把 int  max(int a, int b) 改成 void  max(int a, int b) 就可以了  另外,如果你的函数实现是在主函数后面 所以在主函数前面要有关于自定义函数的申明 参考2楼


Question: 疑难求教，我是初学者

真是太感谢了

引用 1 楼 zhaowech 的回复:试了下，帮你修改了，vs2010，亲测可正常运行，总结些问题： 1.新手指导gets、puts、getchar和putchar的功能和用法即可，在实践中最好少用，因为它们的处理会设计到很多“不可见”的字符，如换行符、缩进符等，对新手，这类问题是很困扰的 2.多调试才能发现问题，并解决问题 3.运行到失败步骤，别使用exit，这导致进程退出，一些其他函数的必要步骤可能被跳过，最好使用return，让函数返回，不影响其他函数的执行。 代码，最后漏了 return 0; 记得加上

#include<stdio.h> #include<stdlib.h> #include<string.h>  #define MAX_WORD_NUM 200 #define MAX_WORD_LEN 16 #define MAX_PATH 260  int main() { 	FILE *fp=NULL; 	char word[MAX_WORD_NUM][MAX_WORD_LEN],forget[MAX_WORD_NUM][MAX_WORD_LEN],s[MAX_WORD_LEN],FilenameIn[MAX_PATH],FilenameOut[MAX_PATH]; 	int iCount; 	int j; 	printf("Input the open file:"); 	scanf("%s",FilenameIn); 	if(NULL==(fp=fopen(FilenameIn,"r"))) 	{ 		printf("File open error!"); 		return -1; 	} 	iCount=0; 	while(!feof(fp)) 	{ 		fscanf(fp,"%s",word[iCount]); 		iCount++; 	} 	fclose(fp); 	j=0; 	for(int i=0;i<iCount;i++) 	{ 		if(i%2==0) 		{ 			printf("%s\n",word[i+1]); 			scanf("%s",s); 			fflush(stdin);//这里是为了消除使用scanf时的回车符 			if(strcmp(s,word[i])==0) 			{ 				printf("Right\n"); 			} 			else 			{ 				printf("Wrong\n"); 				strcpy(forget[j],word[i]); 				strcpy(forget[j+1],word[i+1]); 				j+=2;//这里是加2，不是加1，调试才能更好找问题 			} 		} 	} 	printf("Wrong:%d\n",j); 	printf("Do you want to save the wrong words to a file?<y/n>"); 	if(getchar()=='y') 	{ 		printf("Input the output file:"); 		scanf("%s",FilenameOut); 		getchar(); 		if((fp=fopen(FilenameOut,"w"))==NULL) 		{ 			printf("File open error!"); 			exit(1);	 		} 		for(int i=0;i<j;i++) 			fprintf_s(fp,"%s\n",forget[i]); 		fclose(fp); 	} } 试了下，帮你修改了，vs2010，亲测可正常运行，总结些问题： 1.新手指导gets、puts、getchar和putchar的功能和用法即可，在实践中最好少用，因为它们的处理会设计到很多“不可见”的字符，如换行符、缩进符等，对新手，这类问题是很困扰的 2.多调试才能发现问题，并解决问题 3.运行到失败步骤，别使用exit，这导致进程退出，一些其他函数的必要步骤可能被跳过，最好使用return，让函数返回，不影响其他函数的执行。


Question: freopen函数具体怎么使用？为什么的老是编译不通过？

将变量声明放在函数开头。

引用 4 楼 zhang5476499 的回复:引用 3 楼 zhao4zhong1 的回复:将变量声明放在函数开头。嚯嚯，居然错在这里，明白了，我发现白学了c。 哈哈，下的是CPP代码，结果用当成C来编译了。。。估计你没留意。。。  哦，据说C11还是C99，也可以到处声明变量了，，，是我记错了，，还是谣传？？ 。。。你自己的代码是乱改的吧。。通不过你就改成字符串了，，为何不看文档，，

引用 1 楼 uuuououlcz 的回复:难道是编译器遵循的C标准太老，要求变量定义写在最前面，其他语句放在变量定义后面？反正错误就是出在freopen();这个函数上，书上的代码和网上的代码照搬过来都是编译出错。


Question: 【请教】局部变量及悬垂指针问题

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

引用 1 楼 a345485527 的回复:i 的确是在函数结束后就释放了，但是被释放掉的那块内存不意味着被马上覆盖掉， 只是说 随时都有可能被覆盖掉 所以 这么做是很危险的 解释的很透彻， 给一个未知指针赋值时，可以先null,或者用完就null，不然就容易变成野指针

引用 楼主 li582158579 的回复:请教各位大神，  以下代码中，为何第一次 printf 的时候 *iPtr 的值会是10呢？  变量i不应该在f1函数结束后就释放了吗？  局部变量i到底在什么时候释放的呢？   int *iPtr = NULL;   void f1()   {       int i = 10;       iPtr = &i;   }      void CtestAreaDlg::OnBnClickedButtonPtr()   {       // TODO:  在此添加控件通知处理程序代码       f1();       printf("the value of the ptr is %d\n",*iPtr);       Sleep(1000);       printf("the value of the ptr now is %d\n",*iPtr);   }       说明释放并不是内存清0，而是标记为可用

为什么第二次变成了1000？？

一个良好的习惯是调用指针完毕之后，再把指针置NULL


Question: 把输入一次一个字符地复制到输出 getchar和putchar  疑问-K&R书

谢谢 tujjaw

如用户在按回车之前输入了不止一个字符，其他字符会保留在键盘缓存区中，等待后续getchar调用读取.也就是说，后续的getchar调用不会等待用户按键，而直接读取缓冲区中的字符，直到缓冲区中的字符读完为后，才等待用户按键


Question: 求助，谢谢

第七行，建议lz好好看看书吧

第二行？ 第六行？


Question: 对c语言感兴趣！！不知道能不能学？

我来看版主的回复的~

引用 18 楼 darksworld 的回复:[quote=引用 17 楼 stack009 的回复:] [quote=引用 16 楼 darksworld 的回复:] 入门推荐 谭浩强的书。。 千万别看这本书，这书我们上学期学的时候感觉压根就不是给计算机专业写的，我推荐你去看C和指针这一本书，感觉写的挺好的，我也不能告诉你怎么学，毕竟我也是个小菜鸡[/quote] 我不是计算机专业滴~~[/quote]  真正学成能实际做事的大都不是计算机专业的 放心学吧 按专业的思路，你将变的不专业 因为这是在中国

引用 17 楼 stack009 的回复:[quote=引用 16 楼 darksworld 的回复:] 入门推荐 谭浩强的书。。 千万别看这本书，这书我们上学期学的时候感觉压根就不是给计算机专业写的，我推荐你去看C和指针这一本书，感觉写的挺好的，我也不能告诉你怎么学，毕竟我也是个小菜鸡[/quote] 我不是计算机专业滴~~

引用 16 楼 darksworld 的回复:入门推荐 谭浩强的书。。 千万别看这本书，这书我们上学期学的时候感觉压根就不是给计算机专业写的，我推荐你去看C和指针这一本书，感觉写的挺好的，我也不能告诉你怎么学，毕竟我也是个小菜鸡

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  智者的梦再美，也不如愚人实干的步伐！ 讲一千遍理论，不如写一行代码！  任何语言不落实到实际行动上都等于白说， 没读过MSDN例子代码的程序员实在让人感到可怕！  用C语言1000行源码能完成的工作千万不要用C++重写， 整天把高级技术放在嘴边那是一种浮夸！  少年啊，千万要重视单步调试和设置断点， 用VC调试时记得按下Alt+5、Alt+6、Alt+7和Alt+8。   对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和 寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时 候。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文 字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针 的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  进程都退出了，输入缓冲区刷不刷新都无关痛痒。  不要企图优雅的结束（因为这是不可能办到的） 而要在烂的不能再烂的摊子上也能重整河山！  这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。 常立志不如立长志，立长志不如立即干！

各有各的路 各有各的方法  看楼主的定位如何了~

入门推荐 谭浩强的书。。

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

做永远比说难很多，找本经典的C语言书籍，好好研究，好好钻研，多思考多动手。 学好，是需要付出巨大代价滴~

看书啊。看视频。有的c语言教学的视频。十几集数的，就可以简单入门了。多敲代码，只看书，只会纸上谈兵罢了。要实际的去敲代码。成就感倍增。对了，首先要装个VC

想学就学，学到什么程度，就要看你的悟性和努力了

版主说得一针见血啊。 不过，编程是可以自己学习的，其实也只能自己学习。 关键在于，要写具备一定实用功能的程序，而不是做习题。 建议你可以把Linux下的某些经典命令重现一下，源代码可以在GNU上下载。

语言不就是个工具么

LZ, 每个人都能学的。只是看你怎么去学而已。我就是自学过来的。虽然学的不是很好，还没学全面。但是努力就行了。多敲代码，多看别人的代码。

以上纯属逗乐，版主幸勿嗔怪！

引用 2 楼 caozhy 的回复:任何人都可以学。但是关键要看你打算学到什么程度，用它做什么。  如果是了解一下，大致能看懂人家写的小程序，或者应付下考试之类的，那很容易学会。 但是如果你打算拿这个吃饭——我可以负责任地告诉你，这个论坛上大多数人，甚至一些看上去等级挺高的人，都是业余票友，他们写的程序也就是学校里面习作的水平，这样的代码，是没有什么质量可言的。 引用 3 楼 caozhy 的回复:我们姑且不论怎么样能学好C语言，光是那些人自己都只是二半吊子，你如何相信他们能点拨你正确的方向？  版主说“光是那些人自己都只是二半吊子，你如何相信他们能点拨你正确的方向”。 版主以上发言其实就是点拔。 所以，版主不是二半吊子。 另外，二半吊子不可能当上版主。 所以，版主必须不是二半吊子。

被你发现了，闪人。  引用 3 楼 caozhy 的回复:我们姑且不论怎么样能学好C语言，光是那些人自己都只是二半吊子，你如何相信他们能点拨你正确的方向？

看lz这么问，感觉lz需要了解的太多了，像这种情况，个人以为，去看一些基础性的视频比较好，个人推荐郝斌的C语音


Question: 风光互补路灯控制的软件设计

只是毕业设计要用的程序

没有行业知识


Question: C语言内存分配和释放问题，求大神指导~~

引用 3 楼 u013163178 的回复:node->neibID = (int*)calloc(count, sizeof(int));这是什么意思是啊   neibID在Struct里面忘记写了，但是好像也不是这个地方的问题。谢谢！ 这个是为数据结构里面的neibID分配数量为count，大小为sizeof(int)的连续的内存空间。

在这个里面AttributeNum是一个常数 和graph->numNeib没有关系。我觉得是内存分配和释放时候出了问题，就是不知道具体是怎么回事啊。

graph->numNeib 和 AttriButeNum 的关系是？ 会不会是numNbeib > AttriButeNum 了？          count = graph->numNeib;	 	node->neighbor = (Node*)calloc(count, sizeof(Node)); 	node->neibID = (int*)calloc(count, sizeof(int)); 	node->weight = (double*)calloc(count, sizeof(double)); 	node->neibInfln = (int**)calloc(count, AttributeNum*sizeof(int));


Question: 遇到个蛋疼的问题，还好解决了！

原来是单片机啊

大牛，膜拜下

原来已经结贴了

可以找版主，移到非技术区

引用 5 楼 nadleeh123 的回复:[quote=引用 3 楼 u012421456 的回复:] 你发这个帖子是为了？ 其实我发错地方了[/quote]

引用 3 楼 u012421456 的回复:你发这个帖子是为了？ 其实我发错地方了

没有datasheet比较服气

你发这个帖子是为了？


Question: 关于数据结构与算法的问题

C只有值传递一种参数传递方式。 C语言，指针也是值传递，不过指针的值传递，可以实现地址传递；  值传递是单向的，调用者可以把值，通过实参，传递到函数； 函数不能通过形参，改变调用者传入的实参。 当传递一个指针参数的时候，由于指针，可以得到并修改指针所表示的地址单元的内容；  所以，C语言，指针的值传递，可以（模拟）实现地址（引用）传递。 方法是，实参为地址（也就是一个指针），形参是指针。 在这个过程中，实参（指针或者地址）是不会改变的。  能够改变的是临时变量（形参指针）的值，和该指针指向的内容。 临时变量（形参）是实参的拷贝，二者不是同一个数据（对象）。  要通过函数调用，改变指针的值，也只能用同样的方式； 即实参是指针的地址，形参是指针的指针。  这里，一级指针是要改变的数据。二级指针是指针（数据的地址）。 实参只能是指针的地址，也就是指针的指针，即二级指针。 形参只能是（指针的指针）二级指针。

引用 2 楼 Revivedsun 的回复:typedef struct BiTNode {     char data;     struct BiTNode *lchild,*rchild; } BiTNode, *BiTree;   BiTree是一个指针类型     BiTree T = NULL;     CreateBiTree(&T); 创建树，向函数传入T,保存根结点地址，所以要修改T变量存储空间内的数值（保存一个指针），所以要获得该指针变量的地址。能否说的通俗易懂一点。。。

引用 1 楼 CarlXie 的回复:创建树的时候，传入的参数使用双重指针是因为内部要申请内存空间，要改变这个指针的内容，所以传入指针的指针来反映这种变化。实际上第一重指针T是作为真正的参数，而*T是为了获得T的改变。值传递不能返回在函数内部的变化，这个是很好验证的吧。 运算符&是在这里代表的是取地址符，也就是获得变量的内存地址，转为指针。你的意思是不是说，地址传递其实是被调用函数另外生成一个指针，指向这个地址。但是指针已经变化了？

×× 指针的指针


Question: 加密程序  运行时缺少头文件

或者用mingw

用windows下相应的库替换之。

就不引用这个头文件了，引用windows的


Question: 关于指向数组的指针问题

引用 楼主 qingchuninfo 的回复: int (*p)[5]; //定义一个指向有5个元素的数组 int  a[5] = {1, 2, 3, 4, 5}; p = &a; //&a是什么意思？为啥用a不可以呢？a不是代表数组的首地址吗？   p = a不行，但是p=&a就可以， 不明白为什么 我是在vc6下编译的 ////////////////////////////////////////////////////////////////////////////// 首先，楼主，你没弄清楚两个概念： int (*p)[5];  这句话的意思是有5个int类型的数组，*p存放的是这个数组的首地址的地址； int a[5],是一个有5个int类型的数组，首先这个a是一个常量地址，它不可以被赋地址值； p指向的是a的首地址的地址，因此*p会得到a的首地址，因此只能把&a赋值给p； 这道题只说明你对指针的理解还不够，。。。。

简而言之， a的类型是 int*  而 &a的类型是 int(*)[5]

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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楼和2楼说的都很明白。

int (*p)[5];//p实际上是一个指向二维数组的指针

a是指向整数的指针，也就是数组中的第一个元素。 &a返回的才是指向数组指针的指针。

p = a不行，但是p=&a就可以， a的类型是 int [5],可以隐式转换为int*, 但不能隐式转换为 int (*)[5] &a的类型是int(*)[5],刚好匹配，无需转换。

p相当于int**，a相当于int*，&a相当于int**

a是一个指向数组的指针！

[code=c]#include<stdio.h> int a[3]={1,3,5}; int *p1= NULL; int (*p2)[3]=NULL; int main() { 	printf("首个元素地址%p\n",a); 	printf("第二个元素地址%p\n",a+1); 	printf("正真的数组地址%p\n",&a); 	printf("正真的数组地址%p\n",(&a)[0]); 	printf("数组地址+1后是%p\n",(&a)[1]); 	printf("sizeof (a) = %d\n",sizeof (a)); 	printf("sizeof (&a) = %d\n",sizeof (&a)); 	printf("sizeof (a + 1) = %d\n",sizeof (a + 1)); 	printf("---------------------------------\n"); 	printf("为什么是 %d\n",*(a+1)); 	printf("为什么是 %d\n",*(*(&a+1) - 1)); 	printf("为什么是 %d\n",*a); 	printf("---------------------------------\n");  	p1 =a; 	p2 = &a; 	printf("为什么是 %d\n",p1[0]); 	printf("为什么是 %d\n",*p2[0]); 	printf("为什么是 %d\n",p2[0]); 	printf("为什么是 %d\n",sizeof (p1)); 	return 0; }[/code 数组名不是数组的地址，而是数组第一个元素的地址，要想的到数组的地址，就需要的数组名去地址，这个地址和数组的第一个元素的地址在数值上相同，逻辑上却不一样，


Question: c

呃呃呃   我又写错了

应该是int (*ar)[cols]吧

对了   ，还有个问题是 void matrix_rows(int ar[][cols], int rows)中 我如果定义成这样就不行了  ，是为什么呢 void matrix_rows(int （ar*）[cols], int rows)

谢啦   ！嘿嘿  ，之前没注意定义的形式参量跟宏定义的一样，

void matrix_rows(int ar[][cols], int rows) void matrix_cols(int ar[][cols], int rows) 这两个函数的参数列表里面的"int rows"在编译时被替换成了"int 3"，对于变量定义而言，这是不对的。 建议#define时全用大写，并且起复杂点的名字。


Question: 【提问】 关于DEV-c++中编译的一个错误

你先写个hello world,如果还是这样的错，就是环境问题

引用 1 楼 yangyuyu77584 的回复:if(current = (DLinkListNode*)head )        这里少了一个等号吧。 呃 是少了个等号，不过编译还是会提示有那样的错误

呃 是少了个等号，不过编译还是会提示有那样的错误


Question: C语言文件操作~~在线等~~大牛快来啊

应该是读完第一个结构体之后 文件指针没有在第二个结构体的第一个字符前面 看看你的文件结构吧，尤其是第一个结构体和第二个结构体连接的位置

debug一下啊，你的代码有问题肯定的啊，文件应该没有问题，因为你已经读出来一个正确的了

引用 1 楼 u012061345 的回复:if(head == NULL) head = p2 = p1; else { p2->next = p1; p2 = p1; //改成 p1 = p2 } } }感谢你的回答~~不过，还是只能读出一个结构体的信息，而且感觉就逻辑上不对吧~~~我一直怀疑，我这个stufile是不是有问题，我这个文件是通过另一个程序将学生信息写在里面的，这里相当于直接读里面的信息~~~文件能够通用嘛？


Question: 请教一个 fseek后内存的问题

1. 已经有个多层缓存了：内核的预读取，CRT的IO流缓冲。如果你想对缓冲有更多控制的话，使用OS提供的无缓冲的API， 不要基于已经存在的多层缓存。  2. 你可以自己记录最近的查询结果，如果不在历史缓冲中再从文件流中查找并更新历史记录。这种方法简单有效。

似乎不需要，具体还要看你做什么用。

C库文件API执行系统调用操作如果过于频繁，会效率偏低，其实这些API已经和你考虑一样这样做了，它已经给你缓存了，至于缓存多少，你需要查看下它的实现（好像是FILE结构体中一个成员指定），这样就减少很多的系统调用，操作缓存内容，减少IO，而且满足大多数需求，如果你是特例，你可以是重做这些API; 不过我觉得映射也可行！


Question: c和fortran如何编译生成dll

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。

1）fortran生成DLL 或者lib  2）C调用fortran 要把接口做对，类型对应，调用约定一致 3）C需要输出的函数，在def 导出，不会先学，很容易，可以看看MSDN。    DLL 提供给外部使用的都要导出，一般是标准调用约定，就是WinAPI那种。   外部使用DLL，需要提供.h，. Dll,.lib   .h,.lib 静态链接用，.h也是文档的一部分。

c调用fortran，c里面声明了要调用的fortran函数，不知道怎么根据上面已有的文件重新编译生成dll

1）fortran 生成库供C调用，C生成DLL 2） C生成库供fortran调用，fortran 生成DLL 具体要看，文件内容和调用关系


Question: 求助 C语言 数据写入TXT文件

先输出每行，每行结束换行， C printf("\n"); C++ cout<<endl;

可以你用fwrite

关系到文件那一章。

引用 3 楼 hanxingyu21 的回复:1楼你在敷衍我。。  你自己2楼代码不是“循环遍历”？

1楼你在敷衍我。。

FILE *wfp;		  /*打开文本文件以写入内容*/     wfp = fopen("c:\\result_test_data_array.txt", "w");     if (!fp)     {         perror("cannot open file");         //exit(-1);     }          /*把二维数组的内容写入文件*/     for (i = 0; i < 8; i++)     {         for (j = 0; j < 2; j++)         {             fprintf(wfp, "%4d ", store_key_array[i][j]);         }         fputc('\n', wfp);     }     fclose(wfp);          return 0;

循环遍历


Question: typedef void(*Stuff)(); 的问题

老注册新号很麻烦的

又来？而且分还是那么低，也太扣了吧？强烈鄙视……起码得100分。 没错， typedef int Stuff;  typedef void(*)() Stuff; 看起来在形式上没有什么不同，都是希望用Stuff指示一种类型。但是，要知道，关键字typedef在声明中作为存储类指定符出现： int long long typedef unsigned i;    //等效于typedef unsigned long long int i; 这就是说，声明有声明的语法，typedef只是声明的一部分。所以，单就声明来说，int Stuff;是合法的声明，而void (*)() Stuff;是不合法的声明。


Question: 求大神帮帮忙，甚是感谢！

自己看编译器的错误提示

要学会看这些错误提示啊！ 比如说第一个，语法错误，标识符 book，lz好好检查检查

typedef   后面要有变量名

typedef struct       {     char id[6];     char name[20];     char auther[20];     int  number; }BOOK ; 要么就是 struct    BOOK   {     char id[6];     char name[20];     char auther[20];     int  number; } ;

你这错误太多了，而且基本的语法你都没有掌握，请根据具体的错误信息百度一下吧

你的typdef 用法错误，把出现"typedef "的两个地方去掉就能编译过了！

哥哥,typedef不是你这样用的 这是MSDN上的例子 Examples typedef [public]  long DWORD; This example creates a type description for an alias type with the name DWORD.  typedef enum {       TYPE_FUNCTION = 0,       TYPE_PROPERTY = 1,       TYPE_CONSTANT = 2,       TYPE_PARAMETER = 3    } OBJTYPE; //这个才是可以以后用来定义变量的