Question: 指针错误疑问

引用 5 楼 fengrongtiedi 的回复:我的 疑问是 为什么还要有加一句：head->next = listnode1; listnode1 = head->next;             listnode1 = (ListNode*)malloc(sizeof(ListNode));这两句不足以为head->next分配有效的内存空间吗 head->next并未初始化，指针内容未知，直接listnode1 = head->next肯定不行

你说的是到函数调用的那一步就出现这个错误， listnode2 = s.deleteDuplicates(head); 如果是执行到这句出现问题的话，我觉得可能是你的solution类的写的有问题，碰到野指针啥的。 刚刚搜了下，https://bbs.csdn.net/topics/390804361有个关于solution类的讨论，不过这个solution类是用来删除相邻相同值节点的，应该跟你的不同，不过至少可以供你参考一下。  我把这个套进去，稍微加了几句代码，运行没有出错，以下测试代码供参考，head->val的值分别取0，1，就可以看到listnode2 = s.deleteDuplicates(head);的执行效果了 #include<cstdio> #include<cstdlib> using namespace std;  typedef struct Node{     int val;     Node *next; }ListNode;   class Solution { public:     ListNode *deleteDuplicates(ListNode *head) {         // Start typing your C/C++ solution below         // DO NOT write int main() function         if (head == NULL)             return head;          ListNode* cur = head;         ListNode* pre = head->next;         ListNode* del = NULL;         while(pre != NULL)         {             if (cur->val == pre->val)             {                 del = pre;                 pre = pre->next;    //  这句是有作用的，就是把pre指向next节点                 cur->next = pre;    //                 delete del;  // 如果合并之后，这一句就是delete pre;另外建议你释放内存的时候这么写之后再加一句del = NULL;这样可以防止野指针的出现。             }             else             {                 cur = cur->next;                 pre = pre->next;             }         }         return head;     } };    int main() {     ListNode *head,*listnode1,*listnode2;     head = (ListNode*)malloc(sizeof(ListNode));     //    head = new ListNode;     //     listnode1 = (ListNode*)malloc(sizeof(ListNode));     listnode2 = (ListNode*)malloc(sizeof(ListNode));     head->val = 0;     head->next = NULL;     for(int i = 0;i<3;i++)     {         if(i == 0)         {             listnode1 = head->next;             listnode1 = (ListNode*)malloc(sizeof(ListNode));             head->next = listnode1;         }         listnode1->val = i;         listnode1->next = (ListNode*)malloc(sizeof(ListNode));         listnode1 = listnode1->next;      }     listnode1->next = NULL;       Solution s ;     listnode2 = s.deleteDuplicates(head);      listnode2 = head;     while(listnode2->next != NULL)     {         printf("%d\n",listnode2->val);         listnode2 = listnode2->next;     }      return 0; }

能不能详细解释下，谢谢

少一个head->next = listnode1; int main() {     ListNode *head,*listnode1,*listnode2;     head = (ListNode*)malloc(sizeof(ListNode));     //    head = new ListNode;     //     listnode1 = (ListNode*)malloc(sizeof(ListNode));     listnode2 = (ListNode*)malloc(sizeof(ListNode));     for(int i = 0;i<3;i++)     {         if(i == 0)         {             listnode1 = head->next;             listnode1 = (ListNode*)malloc(sizeof(ListNode));             head->next = listnode1;         }         listnode1->val = i;         listnode1->next = (ListNode*)malloc(sizeof(ListNode));         listnode1 = listnode1->next;      }     listnode1->next = NULL;      Solution s ;     listnode2 = s.deleteDuplicates(head);      return 0; }


Question: 关于C语言中作用域的问题，在看openpilot源码的时候对一处作用域的用法不理解

建议不要这样去看复杂宏展开。用gcc -E main.c来看宏展开的结果，并对结果格式化（就是排排整齐），这样会比较好理解些。  一般来说，如果代码中有*()，那么()中差不多就是个指针类型，而*就是解引用。

参考http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs 好像是返回语句块中最后语句的返回值，你这应该是对&(((type##Array *)dummy)->array); 进行解地址操作吧。


Question: 初学者不明白这个若干行的意思

正如2楼所说，用while()语句判断输入流的流状态位。 输入输出流定义了4个标志位来测试流的状态，badbit、eofbit、failbit和goodbit。其中，badbit位表示了在流缓冲区中发生了致命性错误，流将不能继续使用；eofbit位表示输入结束，例如按下了Ctrl-Z；failbit位表示I/O操作由于非法数据而失败，流可以继续使用；goodbit位表示一切正常，没有错误发生，也没有发生输入结束。 while(!cin.eofbit){ } 请参考《C++中输入流istream》 希望能够帮到你

引用 13 楼 SUNT2018的回复:一行两数，算加减乘除，求出运算结果四个数中不超过100的最大数。 有n行，就算到n行，若干行就是n。

一行两数，算加减乘除，求出运算结果四个数中不超过100的最大数。

样例的判断应该是只要所有的输入都对应有输出，并且输出正确，就能通过

输入若干行的意思可以分开来理解，“输入”，“若干”，“行” 输入就不用说了，那“若干”可以理解为“人为自定义多少”，就是说不确定，是多是少由自己决定。 那“行”就不用说了吧。 总的来说就是“想输入多少行由你自己决定，可以输入一行，也可以输入无数行（前提你要有精力）”。

标题已经说了，他们的值不能超过100，楼主可以多增加一些行数。

引用 1 楼 user-10 的回复：贴一下你的代码吧，不然也没办法帮你看你的问题出在哪里，对吧。 而且，我觉得如果你的代码跑这个样例输入，结果跟这个样例输出一样的话，应该不会有啥问题呀。2楼是正解，不这样写的话会一直提示格式错误之类的

引用 2 楼 Slzde_sub 的回复：while（std::cin>>n>>m） { }  或者  while(scanf("%d%d",&n,&m)) { }  这就是若干行谢谢，这是正解

若干行就是 针对每个输入的一行都输出一行

若干行，就是多个测试用例。若干是一个大概的意思，一般输入3～5行就差不多。如果想测试的更充分，可以考虑多数入一些行数

文字描述的很清楚，求和 差 积不超过100的最大值。

行数不确定。


Question: gcc version 5.1.0 (tdm-1)(32bit) 不能内联 SSE 指令集汇编？

《The Intel 64 and IA-32 Architectures Software Developer's Manual》

The _emit Pseudoinstruction Home |  Overview |  How Do I  The _emit pseudoinstruction is similar to the DB directive of MASM. You use _emit to define a single immediate byte at the current location in the current text segment. However, _emit can define only one byte at a time, and it can only define bytes in the text segment. It uses the same syntax as the INT instruction.   The following fragment places the given bytes into the code:  #define randasm __asm _emit 0x4A __asm _emit 0x43 __asm _emit 0x4B  .  .  . __asm {      randasm      } 不知道gcc汇编有没有类似关键字。

#include <intrin.h>  __m128i a, b;    __asm(     "movdqa %0,%%xmm0\n\t"     "por %1,%%xmm0\n\t"     "movdqa %%xmm0,%0\n\t"     :     :"m"(a), "m"(b)   );


Question: C语言 字符串赋值为题

https://ask.csdn.net/questions/699817 你不是问过了么

char *bpArrayDat="$$$$$$$$$$$$$$$$"; 因为bpArrayDat是指针，指向的内存位置是只读的。因此不能赋值（修改）。  建议通过malloc/free或new/delete来申请空间就可以赋值了。

首先从程序上来说，这两段代码都是不对的， 第一段代码，你说结果是对的，这个是概率发生的，因为你返回了临时变量的地址bArrayDat，很有可能造成崩溃  第二段代码，bpArrayDat指向了一块常量区，并没有分配空间，修改结果也是未定义的，所以也是不正确的做法  正确的做法，自己分配空间，返回后注意free  比如改成char *bpArrayDat = (char*)malloc(1024); 函数返回使用后记得free，其实这样也不太好，需要知道申请了1024大小的空间， 最好是在外边就申请好空间，然后将作为参数传入函数

其实 本来char* pStr = “hello” 这样的赋值在C++是不允许的，之所以可以，是c++为了兼容c而改变的，所以，即便这样可以，也要养成 const char* pStr=“hello” 这样的好习惯

二楼说的有道理，主要原因是一个是字符串常量，一个是字符串变量，所以一个能行，一个不能行！

在一个双引号""内的字符序列或者转义字符序列称为字符串常量  例如："HA HA！"  "abc"  "\n\t"  这些字符串常量是不能改变的，如果试图改变指针所指向的内容是错误的  因为字符串常量是存在静态内存区的，不可以改变的。  如定义字符串常量：  char* a="i love you.";  a[3]='p'(非法操作)。  因为a[3]本来就是一个常量，常量不能被改变。（比如 1=2一样）  如定义字符串变量：   char a[]="i love you.";   a[3]=‘p’是可以的.  因为这个a[3]不同于上例中的 这个是一个 char 类型的变量 。  但是字符指针变量指向是可以改变的。  如：char *a="I love my china"          char *a="I am student"  这个是可以的


Question: Linux平台read-recv-select 84错误-84 EILSEQ

字节序错误。 严格使用hton系列函数调整字节序。

通过了解应该是其他打印格式出错造成，但是超时应该会被重置才对。


Question: CFree调试，怎样显示数组全体成员？

引用 5 楼 qq_39850605 的回复:你想调试的时候看，可以整个全局变量，或者静态局部变量。 为调试，改动程序较大。调试结束后，还得改回来。

在子函数里，形参就是子函数内的变量。而实参传递到子函数内的是地址，因此在子函数里就需要用形参名来访问实参a。

数组自动降级为指针

你想调试的时候看，可以整个全局变量，或者静态局部变量。

那免谈

引用 1 楼 jianwen0529 的回复:函数内已经不是数组了，而是指针int *，并没有记录它的长度。 调试时候可以加个打印函数，比如MyPrintf(int *a, int num);  想用debug方式，不太printf 函数操作源数组，只能指针/别名方式。不能视为自己的变量，调试时，显示比较麻烦。


Question: GetMemory(str);为什么不是传地址

引用 3 楼 XN6666 的回复:我就是搞不清楚为什么非得这么写才行，感觉直接传str也可以啊 你的void GetMemory(char* p) 函数的参数p是一个字符指针变量，那你调用GetMemory(str)；传入的参数是str，但到了调用函数GetMemory内部，实际上却是str的拷贝str'，你在函数中做的任何操作，只影响了str'，但是对str本身是没有任何影响的。 用下面简单的代码做个比较： 调用Get_Add不会改变变量a的值，一个道理，因为传入Get_Add函数的参数，只是a的一份拷贝a'，变量a和a'的值相同，但是在内存中的物理地址不同。所以调用函数的结果只是改变a'的值，但是a是不会改变的，因为a'和a本来就是存在不同物理地址的两个变量。 调用Get_Add_2就不一样了，本身Get_Add_2的参数就是一个整型指针，这时你调用Get_Add_2(&a)，虽然传入的也只是&a的拷贝&a'，但是，&a和&a'的值都是变量a的物理地址，那么通过&a‘对这个物理地址进行的操作，就相当于通过&a在对变量a进行操作，当然也就改变了变量a的值#include<stdio.h>  void Get_Add(int x) {     x++;     printf("x = %d now\n",x); }  void Get_Add_2(int *x) {     (*x)++;     printf("*x = %d now\n",*x); }   int main() {     int a = 1;     Get_Add(a);     printf("after calling Get_Add, a = %d now\n",a);          //     Get_Add_2(&a);     printf("after calling Get_Add_2, a = %d now\n",a);      return 0; }

指针是一种地址变量，既然是变量，想要改变变量的值，就得先知道变量的地址。所以要改变指针的指向，只能把指针的地址传进去，否则改变的只是形参p的指向，而不是实参str

直接传str传入的是指针变量的值， 是一个副本， 不是原指针变量本身， 也不是原指针变量本身的地址

调用GetMemory(str)；时传入参数str，str是一个变量啊，传入后就变成了p，如果str一开始指向有效空间，现在改变p指向的内容是可以的，但是此时p指向的内存是无效的，然后又用了malloc，p指向了一个新的地方，但是这样无法改变str 想改变str，就必须传入str的地址，需要函数参数为char**才可以

我就是搞不清楚为什么非得这么写才行，感觉直接传str也可以啊

void GetMemory(char** p)  {  * p = (char *)malloc(100); } int main(void)  {      char *str = NULL;     GetMemory(&str);     strcpy(str, "hello");      printf(str);  }

这个程序是有问题的。GetMemory传入str后不能获取到申请到的空间首地址，会导致内存泄露。  这个程序运行应该会遇到段错误。因为将"hello"拷贝加NULL开头的内存里。  你的问题没传地址，str也是地址呢


Question: 不太会做这道所谓简单的题，能帮忙解答一下需要详细步骤

不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！

根据C语言运算符优先级，题目中的涉及到的优先级从高到低为~，>>，^。那么 ~(10>>1^~5) = ~(10>>1 ^(~5)) = ~((10>>1)^-6) = ~(5^-6) = ~(-1) = 0

应该是0吧，考察应该是优先级，其中异或^的优先级最低 那就分成10>>1和~5两部分，也就是5^(~5)，应该是0吧

~位求反 >>向右移位 ^位异或 而这三个运算符的优先级是“位求反~”>“向右移位>>”> “位异或^” 因此，~（10>>1^~5)等效为 “~(（10>>1) ^ (~5) )” 最后结果为0


Question: C语言小白问题

看到这代码也是“晕”了

看了半天头都晕了，还是看懂了，涨知识了。建议二级指针问题交给二级指针来做，比较好理解一些，这东西真的晕。

好晕

首选，换顺序是不会挂的（g++5.4)，某些编译器会根据字节对齐等等概念，做优化的：  char * a;  char * s[3]= {"1","2","3"};  比较简单易懂的解释，一句话指针不等于数组首地址。  看下面的程序 char* arrayInt[3] = {xxxxx}; char* ptr = NULL; ptr = *arrayInt; // 这里就是不一样的了。 printf("%d", sizeof(prt));    // 8   (64位机器） printf("%d", sizeof(arrayInt)); // 24   (64位机器）  // 仅仅是指针+1，偏移的地址为（当前指针的地址+ （类型size*1）） // 注意：是指针的地址，不是指针指向内容的地址。 ptr+1;  // 数组首地址+1，相当于从移动到 arrayInt[1]的地址。 这两者的概念，是不一样的！ arrayInt + 1  // 所以，当把数组首地址赋给一个指针后，不要认为两者的概念是一样的。 ---------------------------------------------分割线 所以上述程序输出 1 1 2 3 ， 1，就是 指针指向的内容。 1， 就是指针地址+1，指向的内容。 之后，同理。 给出一个例子，方便理解。程序输出：1 5 1 2 3，因为该程序申请的内存（就是5个Char*），另外字节对齐的概念，请自行补齐。     char* a;     char * s[3]={"1","2","3"};     char* c = "5";     a = *s;      for(int i=0;i <= 4;i++){         printf("%s\n",*((&a)+i));     } -------------------------------分割线 总结： 1. 数组首地址赋给指针后，两者的概念不要混淆。用单一的指针，做数组首地址来用，非常危险，因为很容易访问未知的内存地址，且不越界就不崩溃。 2. 字节对齐，这个概念很重要，同时，有些编译器也会做一些优化。

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

1、数组s有3个元素，所以在for循环时应改为 for(i=0;i<3;i++){ } 2、程序的目的是输出数组s的三个元素，以及3个元素的内容。可以考虑修改为 printf("%s\n", ((a) + i*sizeof(char*))); 		printf("%p\n", ((a)+i * sizeof(char*))); 其中，a表示数组s的第一个元素即字符串“1”的地址；而s的第二个元素的地址并不是a+1，而是a+sizeof(char*)，因为一个地址的大小是4个字节。 3、使用printf()函数输出地址时，使用参数%p 4、VS2015调试通过，输出如下  可以看出，每个字符的地址相差4个字节

不好意思，复制粘贴了一下，这里对应的应该是s[0],s[1],s[2] 然后你的for循环中，当i = 0时，取的实际上是a的地址，自然在我电脑中显示的就是“6356732”，读取的内容，当然指向的就是字符串“1”，后面的理解就简单了： i=1；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356736”，读取的内容，就是s[0]指向的字符串“1”； i=2；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356740”，读取的内容，就是s[1]指向的字符串“2”； i=3；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356744”，读取的内容，就是s[2]指向的字符串“3”； 引用 4 楼 zangfong 的回复:

越界了，野指针

打印出1,1,2,3其实是巧合，(&a)+1这个用法取到的不是s[3]数组中的值，这么用会越界，而刚好越界后访问的地址正是s[3]的地址，所以第一个1是正确的，后面的1,2,3其实是(&a)+1后越界操作到s，所以打印出来的，你在char * s[3]={"1","2","3"};后面不要跟char* a;     char * s[3]={"1a","2b","3c"};     char * c = "ddd";     char * a; 肯定打印出来的有ddd 如果加上int b[] = {1,2,3}，肯定崩了。

申明三个数 非要打四数 闲得蛋疼  楼主的语法一窍不通，建议不要钻牛角尖了

所谓”野指针“，即不确定的地址，即定义了一个指针，但是没有让这个指针指向一个确定的内存位置，此时该指针里存放的是一个随机值（随机地址），所以叫做野指针。

恩，你说得对，的确是越界的，应该也是野指针了，只不过恰好访问到了S，没出错而已。是我想错了，不好意思，呵呵 引用 8 楼 cfjtaishan 的回复:[quote=引用 4 楼 zangfong 的回复:] 不是什么野指针，是没有搞清楚变量在物理内存中的实际位置。按照你的代码，实际上指针变量a以及,s[0],s[1],s[2],s[3]是相邻存放的，一般来说（至少在我的电脑上是这样），先定义的变量存放于高地址，后定义的变量存放于低地址。然后你又有一个a=*s;操作，于是a指针与s[0]指针所指向的地址相等。于是这4个变量在内存中的物理位置，以及对应指针所指向的地址和字符串关系如下图： 然后你的for循环中，当i = 0时，取的实际上是a的地址，自然在我电脑中显示的就是“6356732”，读取的内容，当然指向的就是字符串“1”，后面的理解就简单了： i=1；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356736”，读取的内容，就是s[0]指向的字符串“1”； i=2；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356740”，读取的内容，就是s[0]指向的字符串“2”； i=3；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356744”，读取的内容，就是s[0]指向的字符串“3”； 所以才显示结果为1,1,2,3 参考程序如下#include<stdio.h>  int main() {      char * s[3]= {"1","2","3"};     char * a;     a=*s;     int i=0;     printf("常量字符串\"1\"的地址：%d\n",&"1");     printf("常量字符串\"2\"的地址：%d\n",&"2");     printf("常量字符串\"3\"的地址：%d\n",&"3");     printf("指针a   的物理地址:%d, 指向的内存地址:%d\n",&a,a);     printf("指针s[0]的物理地址:%d, 指向的内存地址:%d\n",s,*s);     printf("指针s[1]的物理地址:%d, 指向的内存地址:%d\n",s+1,*(s+1));     printf("指针s[2]的物理地址:%d, 指向的内存地址:%d\n",s+2,*(s+2));     for(i=0; i<4; i++)     {         printf("%s\n",*((&a)+i));         printf("%d\n",((&a)+i));     }      return 0; } 结果如下图：   再者，如果你的代码中将char *s[3]和char *a的定义的先后顺序换一下（像下面这样），你可以自己试一下，这样就挂了，真的是野指针了。     char * a;     char * s[3]= {"1","2","3"}; 越界了可以确定，但不是野指针。[/quote]  引用 8 楼 cfjtaishan 的回复:[quote=引用 4 楼 zangfong 的回复:] 不是什么野指针，是没有搞清楚变量在物理内存中的实际位置。按照你的代码，实际上指针变量a以及,s[0],s[1],s[2],s[3]是相邻存放的，一般来说（至少在我的电脑上是这样），先定义的变量存放于高地址，后定义的变量存放于低地址。然后你又有一个a=*s;操作，于是a指针与s[0]指针所指向的地址相等。于是这4个变量在内存中的物理位置，以及对应指针所指向的地址和字符串关系如下图： 然后你的for循环中，当i = 0时，取的实际上是a的地址，自然在我电脑中显示的就是“6356732”，读取的内容，当然指向的就是字符串“1”，后面的理解就简单了： i=1；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356736”，读取的内容，就是s[0]指向的字符串“1”； i=2；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356740”，读取的内容，就是s[0]指向的字符串“2”； i=3；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356744”，读取的内容，就是s[0]指向的字符串“3”； 所以才显示结果为1,1,2,3 参考程序如下#include<stdio.h>  int main() {      char * s[3]= {"1","2","3"};     char * a;     a=*s;     int i=0;     printf("常量字符串\"1\"的地址：%d\n",&"1");     printf("常量字符串\"2\"的地址：%d\n",&"2");     printf("常量字符串\"3\"的地址：%d\n",&"3");     printf("指针a   的物理地址:%d, 指向的内存地址:%d\n",&a,a);     printf("指针s[0]的物理地址:%d, 指向的内存地址:%d\n",s,*s);     printf("指针s[1]的物理地址:%d, 指向的内存地址:%d\n",s+1,*(s+1));     printf("指针s[2]的物理地址:%d, 指向的内存地址:%d\n",s+2,*(s+2));     for(i=0; i<4; i++)     {         printf("%s\n",*((&a)+i));         printf("%d\n",((&a)+i));     }      return 0; } 结果如下图：   再者，如果你的代码中将char *s[3]和char *a的定义的先后顺序换一下（像下面这样），你可以自己试一下，这样就挂了，真的是野指针了。     char * a;     char * s[3]= {"1","2","3"}; 越界了可以确定，但不是野指针。[/quote]

引用 4 楼 zangfong 的回复:不是什么野指针，是没有搞清楚变量在物理内存中的实际位置。按照你的代码，实际上指针变量a以及,s[0],s[1],s[2],s[3]是相邻存放的，一般来说（至少在我的电脑上是这样），先定义的变量存放于高地址，后定义的变量存放于低地址。然后你又有一个a=*s;操作，于是a指针与s[0]指针所指向的地址相等。于是这4个变量在内存中的物理位置，以及对应指针所指向的地址和字符串关系如下图： 然后你的for循环中，当i = 0时，取的实际上是a的地址，自然在我电脑中显示的就是“6356732”，读取的内容，当然指向的就是字符串“1”，后面的理解就简单了： i=1；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356736”，读取的内容，就是s[0]指向的字符串“1”； i=2；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356740”，读取的内容，就是s[0]指向的字符串“2”； i=3；根据上图也可以发现，实际上(&a)+i所取出的地址是“6356744”，读取的内容，就是s[0]指向的字符串“3”； 所以才显示结果为1,1,2,3 参考程序如下#include<stdio.h>  int main() {      char * s[3]= {"1","2","3"};     char * a;     a=*s;     int i=0;     printf("常量字符串\"1\"的地址：%d\n",&"1");     printf("常量字符串\"2\"的地址：%d\n",&"2");     printf("常量字符串\"3\"的地址：%d\n",&"3");     printf("指针a   的物理地址:%d, 指向的内存地址:%d\n",&a,a);     printf("指针s[0]的物理地址:%d, 指向的内存地址:%d\n",s,*s);     printf("指针s[1]的物理地址:%d, 指向的内存地址:%d\n",s+1,*(s+1));     printf("指针s[2]的物理地址:%d, 指向的内存地址:%d\n",s+2,*(s+2));     for(i=0; i<4; i++)     {         printf("%s\n",*((&a)+i));         printf("%d\n",((&a)+i));     }      return 0; } 结果如下图：   再者，如果你的代码中将char *s[3]和char *a的定义的先后顺序换一下（像下面这样），你可以自己试一下，这样就挂了，真的是野指针了。     char * a;     char * s[3]= {"1","2","3"}; 越界了可以确定，但不是野指针。

printf("%s\n",*((&a)+i)); 这句打印出来的是1,2,3；最后一个越界访问了。  printf("%d\n",((&a)+i)); 这句打印的是地址值，地址值一般用%p或%x打印

楼上正解，顶


Question: 关于PE相关代码的问题

严格区分32/64位了吗？

引用 1 楼 demoo11的回复:newpSectionHeader->SizeOfRawData =	newpSectionHeader->Misc.VirtualSize=BEISHU*pOptionHeader->SectionAlignment;	(newpSectionHeader-1)->SizeOfRawData > (newpSectionHeader-1)->Misc.VirtualSize? X = (newpSectionHeader-1)->SizeOfRawData :X = (newpSectionHeader-1)->Misc.VirtualSize;	newpSectionHeader->VirtualAddress=	(newpSectionHeader-1)->VirtualAddress+X;	newpSectionHeader->PointerToRawData = (newpSectionHeader-1)->PointerToRawData+(newpSectionHeader-1)->SizeOfRawData;	newpSectionHeader->Characteristics = pSectionHeader->Characteristics; 相关代码，手机复制的，导致排版变形了


Question: 创建窗口类时窗口的位置疑问

搜“关于Windows高DPI的一些简单总结”

Win10中出现异常，换到Win7中又正常了。


Question: 哪位大哥告诉我++group[(int)(value[i]+0.5)/10]这个怎么理解？小弟是个新手，不要打击我啊

引用 4 楼 Slzde_sub 的回复：引用 3 楼 weixin_42526645 的回复:[quote=引用 1 楼 Slzde_sub 的回复：]group 和 value 是数组    ，取出value 下标 i 的值 + 0.5 ，强制转换成int  再整除10，得到group的下标， 取出group 下标所指向的值， 这个值++  结束真是一语点醒梦中人啊！谢了  结个贴吧。。。没分 去散分了[/quote]怎么结贴啊？

引用 1 楼 Slzde_sub 的回复：group 和 value 是数组    ，取出value 下标 i 的值 + 0.5 ，强制转换成int  再整除10，得到group的下标， 取出group 下标所指向的值， 这个值++  结束真是一语点醒梦中人啊！谢了

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


Question: C指针小白问题

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

引用 1 楼 user-13的回复:%d怎么输出字符呀，而且输出数组也不是这么弄的 小白认为楼主是要输出地址的

s和a是两个不同的变量，打印s是数组的首地址，其实就是字符'a'的地址 而a是一个字符指针，&a就是变量a的地址，这两个当然不同了

char * s[3]; 定义的是一个数组，数组中包含3个元素，元素的类型是char*，即字符指针； char s[3]; 定义的是一个数组，数组中包含3个元素，元素的类型是char，即字符； 所以数组s应该用第二种方式定义。 数组名s即表示数组s的起始地址，所以要用 a = s; 最后，printf()函数输出地址时，使用%p。 	char s[3] = { 'a', 'b', 'c' }; 	char *a; 	a = s; 	printf("%p\n", a); 	printf("%p\n", s); 其输出结果为  请参考《C++中字符数组》 《C++中C风格字符串与字符数组》 《C++中指针的数组和数组的指针》 希望能够帮到你

写的什么代码？是故意写成这样找罪受么？

第一个是指针数组

a的地址和s又没关系

引用 楼主 whyseu 的回复:请教各位大神，为何下面的代码&a和s的值是不相等的： 	char * s[3]={'a','b','c'}; 	char * a; 	a=*s; 	printf("%d\n",&a); 	printf("%d\n",s);  两个值不可能一致，一致编译器就出BUG了。//  DD： char* a = s[0]; // 是把s的第一个字符放到a里面，但a是一个地址，此时会把这个s[0]的值通过int to ptr转换成对应值；例如s = "123456"，s[0]='1' 那么A的值就是 '1'。  &a 获取A变量的地址，但这个地址 != s 指向的地址标识符；所以打印的结果是不同的。  dd: char s[] = "abc"; char* a = s; // &s[0] printf("%s\n",  a); printf("%s\n", s);

char * s[3]={"1","2","3"}; 	char * a; 	a=*s; 	int i; 	for(i=0;i<4;i++){ 		printf("%s\n",*((&a)+i)); 		printf("%d\n",((&a)+i)); 	} 为何打印出来的是1,1,2,3？

字符串的赋值才是将地址赋值给左值 而字符的赋值是将该字符赋值给左值 你没有出错是因为编译器智能的发现左边是指针（地址）右边是字符 编译器自作主张的把字符地址给了指针 另外 a 的地址怎么会和 s 的首地址相同呢？应该是 a 所指向的地址是 s 的首地址 简单来说你有两把钥匙可以开同一扇门，但你可以说这两把钥匙是同一把钥匙吗？ 你只能说他们开的门是同一扇。

char * s[3]={'a','b','c'}; char * a; a=*s; printf("%d\n",&a); printf("%d\n",s);  变量a是一个char *类型的变量名。变量s是一个char *类型的数组名。 第一个printf("%d\n", &a);。&a表示取变量a的地址。printf会将变量a的地址按照int类型数值输出。 第二个printf("%d\n", s);。s是一个数组名，数组名表示了数组的首地址。printf会将变量s的首地址按照int类型数值输出。 定义的变量在内存中占用的地址范围不会发生重叠，所以打印出两个变量的地址，其值不一样  char * s[3]={'a','b','c'};这句在赋值的时候有问题。定义的变量s表示定义了一个长度为3的数组，其元素保存的值的数据类型为char *类型，但是赋值时赋值的为char类型

首先，你申请的是指针数组，那么定义就要修改为：char * s[3]={"a","b","c"}; 其次，你比较的是指针a的地址和指针数组的s的地址，这是两个变量，变量本身的地址自然是不相等的。简单举例，#include<stdio.h>  int main() {     char *a;     char *b = "abc";     printf("a:%p b:%p\n",&a,&b);//变量：指针a和指针b本身的地址     a = b;     printf("a:%p b:%p\n",&a,&b);//变量：指针a和指针b本身的地址     printf("a:%p b:%p\n",a,b);//指针a和指针b所指向的字符串常量的首地址     printf("a:%s b:%s\n",a,b);//打印指针a和指针b所指向的字符串常量     return 0; } 结果如图  赋值a=b;只是改变了指针a所指向的地址，使得指针a与b均指向了字符串常量"abc"在内存中的首地址，而并不是改变变量a本身的地址，也正因为如此，指针a和指针b都能打印出字符串"abc"  那么本题也是一样，结果就是上面所述，a和s是两个变量，自身地址当然不一样，赋值a = *s之后，指向的字符串首地址一样，自然打印的字符串也就一样了。 #include<stdio.h>  int main() {      char *s[3]= {"a","b","c"};     char * a;     a=*s;     printf("%p\n",&a);     printf("%p\n",s);     printf("%p,%s\n",a, a);     printf("%p,%s\n",*s, *s);     return 0; } 结果如图：

%d怎么输出字符呀，而且输出数组也不是这么弄的


Question: 【求助】sscanf高效率提取字符串内容求助

引用 9 楼 teleinfor 的回复:[quote=引用 6 楼 DelphiGuy 的回复:] 常规汇编，和#2生成的代码几乎一样，用SSE/AVX，就这么几个字节的复制效率未必高... 我也不确定效率差异，我之前用的是memcpy内存复制。感觉和"="赋值操作是不是应该差不多？[/quote]  差远了，memcpy光调用的开销都比直接赋值大了，直接赋值比用memcpy、sscanf快几十倍到几百倍...

引用 6 楼 DelphiGuy 的回复:常规汇编，和#2生成的代码几乎一样，用SSE/AVX，就这么几个字节的复制效率未必高... 我也不确定效率差异，我之前用的是memcpy内存复制。感觉和"="赋值操作是不是应该差不多？

引用 10 楼 DelphiGuy 的回复:[quote=引用 9 楼 teleinfor 的回复:] [quote=引用 6 楼 DelphiGuy 的回复:] 常规汇编，和#2生成的代码几乎一样，用SSE/AVX，就这么几个字节的复制效率未必高... 我也不确定效率差异，我之前用的是memcpy内存复制。感觉和"="赋值操作是不是应该差不多？[/quote]  差远了，memcpy光调用的开销都比直接赋值大了，直接赋值比用memcpy、sscanf快几十倍到几百倍... [/quote] 好的，多谢。那我修改为直接这么赋值操作，回头测试下海量情况下的效率差异。

这几条指令，profiler啥也分析不出来，要循环重复几百万次...

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

没人用嵌入汇编吗？

嗯，我试试看，谢谢。 引用 2 楼 DelphiGuy 的回复:要效率，可以直接复制，只是几条mov指令而已： inline void FilterDateTimeStr(const char *src, char *dest) {   *(int *)&dest[0] = *(int *)&src[0];   *(short *)&dest[4] = *(short *)&src[5];   *(short *)&dest[6] = *(short *)&src[8];   *(short *)&dest[8] = *(short *)&src[11];   *(short *)&dest[10] = *(short *)&src[14];   *(short *)&dest[12] = *(short *)&src[17];   *(short *)&dest[14] = *(short *)&src[20];   dest[16] = src[22];   dest[17] = 0; }

引用 1 楼 user-3 的回复:效率就要自己测试下了  	char *p = "2018-07-02 03:40:13.090853929"; 	char str[128] = { 0 }; 	sscanf(p, "%4s-%2s-%2s %2s:%2s:%2s.%3s", str, &str[4], &str[6], &str[8], &str[10], &str[12], &str[14]);  嗯，多谢。我试试看吧。总归需要一些技巧吧。


Question: C  一个烫烫烫的问题

加一个rewind(fp);或者fseek(fp, 0, SEEK_SET);

引用 2 楼 zhangchm2018 的回复:[quote=引用 1 楼 zhangchm2018 的回复:] 因为 fprintf 和 fscanf 输入输出的只能是 char 类型的数据，所以它会将你输入的任意数据都转换成 char 类型的 如果你想输入和读取 int, float, double 之类的数据，推荐使用 fwrite 和 fread 函数 fread  http://www.runoob.com/cprogramming/c-function-fread.html fwrite http://www.runoob.com/cprogramming/c-function-fwrite.html比如 float 类型的 88，会转换成 '8' '8'[/quote]3L说的对，是我错了

感觉3楼回答正确

就你这个题目来说，是你的文件指针fp的位置问题引起的，如果要读取你刚刚写入student.txt里的那些数据，你需要把文件指针fp重新移到文件开头#include <stdio.h> #include <memory.h> #include<stdlib.h> struct student {     int num;     char name[10];     float score1;     float score2;     float score3;     float aver; }; main() {     int i,nu;     float sc1,sc2,sc3;     char na[10];     struct student st[1];     FILE *fp;     if((fp=fopen("E:\student.txt","w+"))==NULL)     {         printf("can not open file\n");         exit(0);     }     setbuf(fp,NULL);     for(i=0; i<1; i++)     {         scanf("%d%s%f%f%f",&nu,&na,&sc1,&sc2,&sc3);         fprintf(fp,"%d %s %f %f %f %f",nu,na,sc1,sc2,sc3,(sc1,sc2,sc3)/3);         fflush(fp);     }      fseek(fp,0L,SEEK_SET); // 定位文件读写指针fp到文件开头      for(i=0; i<1; i++)     {         fscanf(fp,"%d%s%f%f%f%f%f",&st[i].num,&st[i].name,&st[i].score1,&st[i].score2,&st[i].score3,&st[i].aver);     }     for(i=0; i<1; i++)     {         printf("%d %s %.2f %.2f %.2f %.2f",st[i].num,st[i].name,st[i].score1,st[i].score2,st[i].score3,st[i].aver);     }     fclose(fp); }

引用 1 楼 zhangchm2018 的回复:因为 fprintf 和 fscanf 输入输出的只能是 char 类型的数据，所以它会将你输入的任意数据都转换成 char 类型的 如果你想输入和读取 int, float, double 之类的数据，推荐使用 fwrite 和 fread 函数 fread  http://www.runoob.com/cprogramming/c-function-fread.html fwrite http://www.runoob.com/cprogramming/c-function-fwrite.html比如 float 类型的 88，会转换成 '8' '8'


Question: 并非所有的代码路径都返回值

错误提示写得很清楚了，网上随便一搜例子一大堆，不明白你的疑问是什么

有没有返回值是看定义的。 如果没有返回值，那么函数怎么退出？（即使void类型函数，那么它也是有退出的路径的）

最后加一个 return true 啊, 提示得这么明显了. 另外, 这里不是 C# 区哦


Question: c语言注意事项

说的好，不如再贴出几个程序大家一起讨论一下，这样会更好～

说的非常好！ 其实我是来接分的

这是要接分的节奏么？

想说明什么？

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


Question: pdu超长短信编码

前面数据的处理我都搞定了，就是后面拆分之后数据的处理还在考虑

大体上是要多发一个udh的头 udh[10]="\x05\x00\x03" udh[3]=(char)(time(NULL)%255); udh[4]=(char)((cstrlen(nr)+66)/67); udh[5]=(char)j; udh头是6个字节，前3个固定，第4个是一个标识，表明是哪一条短信，第5个是总条数，第6个是第几条短信 单条短信每条可发70，长短信每条只能发67，在udh头后面跟这67的编码就可以了


Question: 用scanf输入的double类型的数据不对

说实话    很同意楼上赵四老师的说法，编程真的很需要细心，==写成=，指针忘了释放，数组越界，嵌套的两个for循环搞成死循环了，变量拼错了，编程真的需要细心，编程真的需要细心！编程真的需要细心！

这个问题好坑。真佩服那个能分辨出来1和l的兄弟

1Il|│ 0oO○。°

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

始于此，终于此。

好久没见过VC6.0的界面了

好的  谢谢了


Question: c语言问题 求大神解答

引用 3 楼 lijingswjtu的回复:  #include<stdio.h> void main() { 	int a,b,c,n,x,y,z,m=0; 	printf("请输入红球、白球和黑球个数。\n"); 	scanf("%d %d %d",&a,&b,&c); 	printf("请输入取出球的个数。\n");     scanf("%d",&n); 	if(n<=a+b+c)   //输入的n值不能超过球总数 	{     for(x=0;x<=a;x++)   //x为取红球个数 		for(y=0;y<=b;y++) //y为取白球个数 			for(z=0;z<=c;z++)  //z为取黑球个数 			{ 				if(n==x+y+z) 				{ 					printf("取出红球%d个，取出白球%d个，取出黑球%d个\n",x,y,z); 				    m++; 				} 			} 			printf("一共有%d种不同的颜色搭配。 ",m);  	} 	else 	{printf("取出球的个数超过球的总数，输入错误！");}  } 这是套了三层循环吗？凑十个字

两个for循环不就搞定了？


Question: 这段代码sum的输出结果是-nan（ind）,为什么啊

引用 4 楼 cfjtaishan 的回复:[quote=引用 1 楼 zhangchm2018 的回复:] #include<stdio.h> #include<math.h> int main() { double a[1000]; int i; int m; double sum; while (scanf("%lf", &a[0]) != EOF) { sum = a[0]; scanf("%d", &m); for (i = 0; i < m - 1; i++) { a[i + 1] = sqrt(a[i]); sum += a[i + 1]; }	 printf("%.2f\n", sum); sum = 0; } while (getchar() != '\n') 	continue; getchar(); return 0; } ① sum 初始化错误 ② scanf 的格式控制符使用错误，double 对应 %lf 根据标准，%f可以输入double类型的数据。输出时建议用%lf[/quote] 我用的 VS2012， 输入 double 类型 只能用 %lf 还有我学的书是 《C Primer Plus（第6版）》，书中说的也是 输入 double 用 %lf

引用 1 楼 zhangchm2018 的回复:#include<stdio.h> #include<math.h> int main() { double a[1000]; int i; int m; double sum; while (scanf("%lf", &a[0]) != EOF) { sum = a[0]; scanf("%d", &m); for (i = 0; i < m - 1; i++) { a[i + 1] = sqrt(a[i]); sum += a[i + 1]; }	 printf("%.2f\n", sum); sum = 0; } while (getchar() != '\n') 	continue; getchar(); return 0; } ① sum 初始化错误 ② scanf 的格式控制符使用错误，double 对应 %lf 根据标准，%f可以输入double类型的数据。输出时建议用%lf

double sum = a[0]; 这句改成： double sum = 0.0; 因为a[0]是一个随机值，在没有输入数据之前，它是一个随机值。

楼主，你那个system是什么？


Question: 如何每隔一秒，让已知量与时间之积进行累加？

靜態局部變量+定時器+綫程 定時器每秒啓動綫程調用計算函數，函數中這個纍加值是靜態變量，把乘積類加上去。

求y轴（电流），x轴（时间） 截取段面积？

正如楼上所说，最好在子线程中进行计算。使用定时器，每隔一秒获取当前电流值，并对时间进行累加，最后得到电流值与时间的乘积，累加到一个局部变量中即可。


Question: 求大佬们解答！！！

引用 14 楼 juge0007 的回复:没有搞懂什么是不影响原有顺序，照你这么说的话，输出应该是4312，而不应该是432。还有它输出上写的432应该是说，我输入的这串数字按照它要求的输出应该是432。  首先整形范围-32768----32767，所以输入数据需要用长整形。  其次这题明显是要得到一组去重后的数据，然后比较大小后去最大值。  看列子： 423234去重后  423 432 234 324 324 234 取起其中最大值432  你的程序直接先排序？？？这里肯定错了

应该改成long型估计就没问题了

你是不是没有按照顺序啊 不应该是423吗

引用 9 楼 zangfong 的回复：我觉得是楼主你自己理解错了，题意是不能改变原有数字的顺序，取得消除重复数字后的最大整数，但是你提供的这个界面显示的是自测调试，也就是对你自己的这段程序，输入你自己的测试用例进行调试，而这里出来的结果应该也是你自己程序跑出来的结果，并非标准答案。看了下楼主的代码，如果直接用1234作为测试用例，输出的是4321，如果你拿这个测试用例去网上进行自测调试，出来的应该也是4321。。。那自测输出也应该是4321啊，第一张图是华为考试网页上的自测输出，第二张图是自己编译器的输出

引用 7 楼 niiiloc 的回复：都说长整数了，你还用int不就是找罪受么我用的long，而且我都试过，long和int输进去，通过率还是20%，没区别

按照楼主的意思，并且自测的4312，不知道为什么楼主有排序的过程，感觉不应该有排序的过程，可以利用栈的感觉吧，不断比较是否重复，并且比较大小。蹭分

321423412改变顺序输出结果是4321，不改变顺序输出结果是4312 题目没明示是哪种算法，两种都试试呗

都说长整数了，你还用int不就是找罪受么

引用 1 楼 Slzde_sub 的回复:  首先 既然是长整数， 就用long long吧， 无非就是范围大一些，确又没有直接指明需要字符串解决，所以long long肯定够用  既然是华为的题，，虽然也是签到题，，  应该是在不影响原有的数字顺序的情况下，不然就这题就是真水题了  没有存在的意义  所以你的自测数据只能得到432  你改变了数据原有的排序顺序，在这题意的逻辑上是错误的  这种题一看就是贪心，虽然数据不大，暴力也可以  思路就是先将第一个数push到stack中，然后向后查找，当查找到比该数大的数时候，判断后面是否留有该数，有的话就把较大数替换该数，  例如你先将3 push ，向后查找，到4发现4>3，而4后的数字中又依旧存在3，就把4替换3，然后再从4后的2开始重复这个过程    经过大家的提示，我大概知道为什么了，题目说了注意考虑长整数，不仅是说考虑输入的数是长整数，而且输出的数也可能是长整数： sort(num, i); int count = xiaochu(num, i);  int temp = 0;  for(int j = 0; j < count; j++) temp = temp * 10 + num[j];  printf("%d\n", temp); //system("pause");  return 0;  这里的temp是用来保存最后输出的最大整数的，应该改成long型估计就没问题了

题意的表达也许有问题，不过既然是华为的面试题，网上百度一下，还是有不少代码可以供参考的，先搞一份来试试看，确定题意了之后再按照自己的思路动手写一遍，应该也是有所收获的吧。 引用 12 楼 juge0007 的回复:引用 9 楼 zangfong 的回复：我觉得是楼主你自己理解错了，题意是不能改变原有数字的顺序，取得消除重复数字后的最大整数，但是你提供的这个界面显示的是自测调试，也就是对你自己的这段程序，输入你自己的测试用例进行调试，而这里出来的结果应该也是你自己程序跑出来的结果，并非标准答案。看了下楼主的代码，如果直接用1234作为测试用例，输出的是4321，如果你拿这个测试用例去网上进行自测调试，出来的应该也是4321。。。而且题意并没有表达出不能改变顺序

引用 5 楼 酷冷小少 的回复：不影响原有数字顺序就是  12343===>有两种结果一种是1234，一种是1243，这两种结果都没有影响原有数字顺序，题目没说去掉哪一个重复数字，我的理解是这样，至于你说的你输入的那数字正确答案是432，我是不理解的，一个1都没有，确定这是官方给的正确答案吗。是啊，这也是我困惑的地方

引用 1 楼 Slzde_sub 的回复：  首先 既然是长整数， 就用long long吧， 无非就是范围大一些，确又没有直接指明需要字符串解决，所以long long肯定够用  既然是华为的题，，虽然也是签到题，，  应该是在不影响原有的数字顺序的情况下，不然就这题就是真水题了  没有存在的意义  所以你的自测数据只能得到432  你改变了数据原有的排序顺序，在这题意的逻辑上是错误的  这种题一看就是贪心，虽然数据不大，暴力也可以  思路就是先将第一个数push到stack中，然后向后查找，当查找到比该数大的数时候，判断后面是否留有该数，有的话就把较大数替换该数，  例如你先将3 push ，向后查找，到4发现4>3，而4后的数字中又依旧存在3，就把4替换3，然后再从4后的2开始重复这个过程  三楼

应该如楼上所说，消除重复数字的时候不能改变原有数字的顺序，要不然，去下重，由大到小排出来没多大意义，题目中给出的432 看着像是直接由大到小排出来的，但是仔细看一下，它没有改变原有数字顺序，考点应该在这里。不能改变原有数字顺序也有两种情况，6523555 & 6563555 ，楼上已经给出了具体算法，我只是锦上添点花，蹭蹭分。


Question: C语言openMP调用核心数问题

openmp不能跨节点吧，试试MPI框架

我也遇到同样问题了，四路AMD8365se，16x4共64核，Server2018，显示32核，64线程，用get_num_procs，得到32。运行程序时只有32核工作。不知道是操作系统的限制，还是硬件的问题，用的是intel parallel的openmp。

回复三楼user-3 我也没有解决不能全部调用的问题，只能调用一路最大32核。 建议从程序算法改进着手，你的能够调用48核，改进一下算法一般地科学计算可能也够用了。我的就是改进算法后将计算效率提高到了可以接受的范围

请问楼主问题解决了吗？我也碰到了类似的问题；  我的机器是：四路e7，共96核192线程。openMP程序中设置192核并行计算时，cpu只使用了25%（一路）;  以下是源代码： #include "stdafx.h" #include <iostream> #include <time.h> #include <omp.h> void test() {     int a = 0;     for(int i = 0;i < 100000000;i++)         a++; }  int _tmain(int argc, _TCHAR* argv[]) {     clock_t t1 = clock();     omp_set_num_threads(192);//设置192核并行计算     #pragma omp parallel for     for (int i=0;i<192;i++)         test();     clock_t t2 = clock();     std::cout<<"time: "<<t2-t1<<std::endl;     getchar();     return 0; }


Question: 算法笔记3.2问题C，一直显示答案错误，麻烦各位大神帮忙看看问题在哪！！感谢！！

看你的代码觉得没啥问题呀，直到去codeup上看了这道题及其讨论，测试数据用的是中文(001 张三 男 19)，那你的sex用char肯定不行，而且题目也坑，看了看讨论，说id和name数组开得不够大，开到100就过了。 #include <stdio.h> #include <string.h> struct student {     char id[100];     char name[100];     char sex[10];     int age; } stu[1001]; int main() {     int n,m,flag;     char count[20];     while(scanf("%d",&n)!=EOF)     {         for(int i=0; i<n; i++)         {             scanf("%s %s %s %d",stu[i].id,stu[i].name,&stu[i].sex,&stu[i].age);         }         scanf("%d",&m);         for(int i=0; i<m; i++)         {             scanf("%s",count);             flag=0;             for(int j=0; j<n; j++)             {                 if(strcmp(count,stu[j].id)==0)                 {                     flag=1;                     printf("%s %s %s %d\n",stu[j].id,stu[j].name,stu[j].sex,stu[j].age);                     break;                 }             }             if(flag==0)             {                 printf("No Answer!\n");             }         }     }      return 0; }

你是想录入学生的学号、名字、性别、年龄后，再按学号查询学生信息吗？

题目是要干啥


Question: 如何用二级页表实现虚拟页式存储管理系统

参考Linux源代码中内存管理相关片断？


Question: 如何用C语言编写变上限积分

这个好理论，表示不用c语言我也不会


Question: 想问一个如何在xml节点中添加父节点的问题，还请大神帮忙解答

//创建一个节点，设置节点内容和属性，然后加入根节点 xmlNodePtr pnode = xmlNewNode(NULL, BAD_CAST"node2"); xmlNodePtr content = xmlNewText(BAD_CAST"node2 Content"); xmlAddChild(pRootNode, pnode); xmlAddChild(pnode, content); //属性 xmlNewProp(pnode, BAD_CAST"attribute", BAD_CAST"yes");   //创建一个儿子和孙子节点 pnode = xmlNewNode(NULL, BAD_CAST"son"); xmlNewProp(pnode, BAD_CAST"attribute", BAD_CAST"age"); xmlAddChild(pRootNode, pnode);   xmlNodePtr pGrandson = xmlNewNode(NULL, BAD_CAST"grandson"); xmlAddChild(pnode, pGrandson); xmlAddChild(pGrandson, xmlNewText(BAD_CAST"grandson content"));


Question: 有关malloc和free的一个问题

注意这里 fgets(tmp->trans[0],1024,fp);

printf("%d\n", sizeof(char*));

引用 23 楼 wang0635 的回复：[quote=引用 19 楼 juge0007 的回复:] [quote=引用 18 楼 wang0635 的回复:] 至少这几个地方是有隐患的     p = (word_t **)malloc(sizeof(word_t)); ======>>>>>> p = (word_t **)malloc(sizeof(word_t *));     fp = fopen("dict.txt", "r");	//打开文件dict.txt，只读     if(!fp)     {         puts("数据库文件不存在!");         return 0;     }      word_t *tmp = (word_t *)malloc(sizeof(word_t));     tmp->key = (char *)malloc(100);     tmp->trans = (char **)malloc(sizeof(char **)); ======>>>>>> tmp->trans = (char **)malloc(sizeof(char *));     tmp->trans[0] = (char *)malloc(256 * sizeof(char *));  ======>>>>>> tmp->trans[0] = (char *)malloc(256 * sizeof(char));  里面的sizeof我换成了数字程序就会崩溃[/quote]你把里面sizeof的结果打印出来看看跟你换成的数字是否一样。为什么要用数字呢？老师没有提醒过吗[/quote]一样的，我编译器里sizeof char*也是四个字节

引用 30 楼 ofof2008 的回复：sizeof()是编译器会算出来的，感觉应该不是这里的问题。确实是包含了sizeof就一点问题也没有了

引用 24 楼 liulilittle 的回复：你破坏掉了 malloc 分配的内存块的尾部。什么意思？怎么破坏的啊？

sizeof()是编译器会算出来的，感觉应该不是这里的问题。

我稍稍修改了下你贴的源码，在dict.txt贴了一大段英文，让程序跑起来，然后照你说的将tmp->trans[0] = (char *)malloc(256 * sizeof(char *))修改为tmp->trans[0] = (char *)malloc(1024)，就是把sizeof(char*)换成了4，在windows 32位下codeblocks，以及linux 64位下gcc，运行都没有报错。你确定就是这里的问题吗？看这个源代码，貌似应该还有其他关联的源码（结构体啊之类的），是否问题出在其他地方呢？另外，要么就是功能性的问题了，处理字符串的确有可能越界。我也没招了。以下是我瞎改的测试源代码#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h>  #define KEYSIZE 100 #define MAXSIZE 1024  typedef struct{     char *key;     char **trans;     int n;  }word_t;  word_t **p; int pos = 0; int alpha = 0;  void insert_array(word_t *,int);   int read_txtfile(void) {     FILE *fp;      p = (word_t **)malloc(sizeof(word_t *));     printf("sizeof word_t = %d\n",sizeof(word_t));//我瞎编的结构体，windows32位运行结果是12，linux 64位运行结果是24     printf("sizeof word_t* = %d\n",sizeof(word_t *));//windows32位运行结果是4，linux 64位运行结果是8     printf("sizeof char = %d\n",sizeof(char));//windows32位运行结果是1，linux 64位运行结果当然也是1     printf("sizeof char* = %d\n",sizeof(char *));//windows32位运行结果是4，linux 64位运行结果是8     printf("sizeof char ** = %d\n",sizeof(char **));//windows32位运行结果是4，linux 64位运行结果是8      fp = fopen("dict.txt", "r");	//打开文件dict.txt，只读     if(!fp)     {         puts("数据库文件不存在!");         return 0;     }      word_t *tmp = (word_t *)malloc(sizeof(word_t));     tmp->key = (char *)malloc(KEYSIZE+1);     tmp->trans = (char **)malloc(sizeof(char *) * 1);     tmp->trans[0] = (char *)malloc(MAXSIZE * 1);      while(fgets(tmp->key,KEYSIZE,fp))     {          fgets(tmp->trans[0],MAXSIZE,fp);	//单词解释中@前后没有换行符，所以将整个解释读入了trans[0]中         insert_array(tmp,pos);         pos++;      }      free(tmp->trans[0]);     free(tmp->trans);     free(tmp->key);     free(tmp);     fclose(fp);      return 1; }  void insert_array(word_t *tmp,int pos) {     extern word_t **p;     int count = 0;     //word_t **temp_ads = NULL;      if(*(tmp->key + strlen(tmp->key) - 1) == '\n')         *(tmp->key + strlen(tmp->key) - 1) = '\0';     if(*(tmp->trans[0] + strlen(tmp->trans[0]) - 1) == '\n')         *(tmp->trans[0] + strlen(tmp->trans[0]) - 1) = '\0';      p = (word_t **)realloc(p, sizeof(word_t*) * (pos + 1));      p[pos] = (word_t *)malloc(sizeof(word_t));     p[pos]->key = (char *)malloc(strlen(tmp->key) + 1);      strcpy(p[pos]->key,tmp->key + 1);	//读入字符串第一位是#，所以从key+1开始拷贝      if(tolower(*p[pos]->key) >= 'a' && tolower(*p[pos]->key) <= 'z')         alpha++;      char str[1024];     strcpy(str,tmp->trans[0]);     char *token = strtok(str,";");	//将文本中的Trans过滤掉     p[pos]->trans = NULL;      while((token = strtok(NULL,"@")))	//将@以前Trans以后的内容放入token中     {         p[pos]->trans = (char **)realloc(p[pos]->trans, sizeof(char *) * (count + 1));	//调整指针的大小,每个指针大小为4         p[pos]->trans[count] = (char *)malloc(strlen(token) + 1);         strcpy(p[pos]->trans[count],token);         count++;     }      p[pos]->n = count; }  int main() {     read_txtfile();     return 0; }

先打印sizeof(char *)，再用打印出来数字替换，如果还是有问题，清空整个工程再试试，或换编译器试试。如果不同编译器都是sizeof(char *) OK，sizeof(数字)有问题，那只能有请楼下大神了

这个上下两个都是一样的，看着没有问题

你破坏掉了 malloc 分配的内存块的尾部。

引用 19 楼 juge0007 的回复:[quote=引用 18 楼 wang0635 的回复:] 至少这几个地方是有隐患的     p = (word_t **)malloc(sizeof(word_t)); ======>>>>>> p = (word_t **)malloc(sizeof(word_t *));     fp = fopen("dict.txt", "r");	//打开文件dict.txt，只读     if(!fp)     {         puts("数据库文件不存在!");         return 0;     }      word_t *tmp = (word_t *)malloc(sizeof(word_t));     tmp->key = (char *)malloc(100);     tmp->trans = (char **)malloc(sizeof(char **)); ======>>>>>> tmp->trans = (char **)malloc(sizeof(char *));     tmp->trans[0] = (char *)malloc(256 * sizeof(char *));  ======>>>>>> tmp->trans[0] = (char *)malloc(256 * sizeof(char));  里面的sizeof我换成了数字程序就会崩溃[/quote]你把里面sizeof的结果打印出来看看跟你换成的数字是否一样。为什么要用数字呢？老师没有提醒过吗

引用 13 楼 shihengzhen101 的回复:32位程序没有任何区别，但是64位上指针就是8个字节了，大小就有所不同 感觉是空间没申请够，将1024改成2048试试

32位程序没有任何区别，但是64位上指针就是8个字节了，大小就有所不同

申請空間盡量避免直接指明數字，這不是個好習慣啊

引用 6 楼 juge0007 的回复:[quote=引用 4 楼 zangfong 的回复：]sizeof(char *)在64位系统下应该是8个字节吧，32位系统是4个字节。 在32位系统中，只是将tmp->trans[0] = (char *)malloc(1024)修改成tmp->trans[0] = (char *)malloc(256 * sizeof(char *))提高了程序的可读性和可移植性，不应该影响最后的free。 如果free出错，个人感觉还是动了tmp->trans[0]，没有指向申请内存的首地址，或者是free了两次。  另外，不管怎样，动态申请内存，还是带上sizeof更好。我明天试试[/quote] 我觉得跟系统的位数无关，64位char*虽然占8字节，32位占4字节，但是我同样申请1024空间一样，管它是多少位的，只要是4的倍数，就可以正常存储数据。那么他说到free的时候有问题，所以基本可以确定是trans[0]这有问题，释放的时候不是释放的首地址。这样的问题贴点源码上来看一看，分析分析呀。

为什么要用数组指向一个地址空间呢

指针的长度，最好不要假设与int一样。有的机器上是3字节的呢（keil C51）

64位下指针长度是8字节，32位下指针长度是4字节 或者你自己printf下sizeof(char *)的值不就好了 一定要多调试，而不是脑补

引用 4 楼 zangfong 的回复:sizeof(char *)在64位系统下应该是8个字节吧，32位系统是4个字节。 在32位系统中，只是将tmp->trans[0] = (char *)malloc(1024)修改成tmp->trans[0] = (char *)malloc(256 * sizeof(char *))提高了程序的可读性和可移植性，不应该影响最后的free。 如果free出错，个人感觉还是动了tmp->trans[0]，没有指向申请内存的首地址，或者是free了两次。  另外，不管怎样，动态申请内存，还是带上sizeof更好。 64位的程序是8字节 64位系统 32位程序是4字节

叫不醒一个装睡的楼主


Question: Misra C 2012 +PC Lint的一个问题

PWM->CTRL = (uint8)0x21; 试试看。

C++ Integer Constants Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.  Syntax  integer-constant :  decimal-constant integer-suffixopt octal-constant integer-suffixopt hexadecimal-constant integer-suffixopt 'c-char-sequence'  decimal-constant :  nonzero-digit decimal-constant digit  octal-constant :  0 octal-constant octal-digit  hexadecimal-constant :  0x hexadecimal-digit 0X hexadecimal-digit hexadecimal-constant hexadecimal-digit  nonzero-digit : one of  1 2 3 4 5 6 7 8 9  octal-digit : one of  0 1 2 3 4 5 6 7  hexadecimal-digit : one of  0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F  integer-suffix :  unsigned-suffix long-suffixopt long-suffix unsigned-suffixopt  unsigned-suffix : one of  u U  long-suffix : one of  l L  64-bit integer-suffix :  i64  To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.  To specify a decimal constant, begin the specification with a nonzero digit. For example:  int i = 157;   // Decimal constant int j = 0198;  // Not a decimal number; erroneous octal constant int k = 0365;  // Leading zero specifies octal constant, not decimal  To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:  int i = 0377;   // Octal constant int j = 0397;   // Error: 9 is not an octal digit  To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the “x” does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:  int i = 0x3fff;   // Hexadecimal constant int j = 0X3FFF;   // Equal to i  To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:  unsigned uVal = 328u;             // Unsigned value long lVal = 0x7FFFFFL;            // Long value specified                                    //  as hex constant unsigned long ulVal = 0776745ul;  // Unsigned long value


Question: 进程间读写锁问题( windows  linux )

楼主，在网上查查"windows进程同步"相关字眼，应该会找到你的所要答案。

Mutex 互斥量


Question: 新人求教

引用 2 楼 chunzhuyitou 的回复:题主补充一句，我有部分用例是对的，不可能是某些问题32位内的就没问题。再大的不行

没看出那不对

为啥不用>>  ，移位运算符

他说保证它们长度<=10^5 并且没有前导 0，2^16<10^5<2^17，那你a[17]、b[17]、c[18]不就足够了吗

题主补充一句，我有部分用例是对的，不可能是某些问题

长度<=10^5 ，不能保证int型的sum1、sum2能保存的


Question: 5. 最长回文子串

引用 9 楼 zangfong 的回复:不好意思，我仔细看了代码，用不同的编译器调试了一下，确实是有问题的。你说的两个问题都是用指针模拟数组时引起的访问越界。 free(intAry)这个报错是因为申请空间不够，既然后面的for循环中i都取到(strlen(s) * 2 + 1)了，那你申请的intAry空间自然是不够了，最后访问越界了。因此要跟上面的newStr一样(strlen(s) * 2 + 2) intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));  至于你说的本地运行能够出bb，提交之后是空串，我觉得是下面的访问越界引起的： 你的代码中for循环里面的while循环中mvp--;这句在执行的时候，也一样越界了，你可以自己单步调试一下看看，就明白了         while(*mvp == *mvq)         {             len+=1;             mvp--;             mvq++;         } 因此这里需要加一个限制条件，以下的测试代码供参考 #include<stdio.h> #include<string.h> #include<stdlib.h>  char* longestPalindrome(char* s) {     char *newStr = NULL;     char *newStrStart = NULL;     char *mvp = NULL;     char *mvq = NULL;     int  *intAry = NULL;     int   len = 0, maxlen = 0, pos = 1;      if(strlen(s) < 2)         return s;      /*set new str  [aba] => [#a#b#a#] */     newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));     memset(newStr,0,sizeof(newStr));     mvp = s;     mvq = newStr;     while(*mvp != '\0')     {         *mvq = '#';         *(mvq+1) = *mvp;          mvp++;         mvq = mvq + 2;     }     *mvq = '#';     *(mvq+1) = '\0';      /*cal len[i]*/     intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));     memset(intAry,0,sizeof(intAry));     for(int i = 0 ; i < (strlen(s) * 2 + 2); i++)     {         len = 1;         intAry[i] = 1;         mvp = newStr + i - 1;         mvq = newStr + i + 1;         if(mvp < newStr || mvq >= (newStr + strlen(newStr)))         {             continue;         }          while( (*mvp == *mvq) &&(mvp - newStr >= 0))         {             len+=1;             mvp--;             mvq++;         }          intAry[i] = len;          if(len > maxlen)         {             maxlen = len;             pos = i;         }     }      /*cal start pos*/     if(pos % 2 == 0)     {         newStrStart = s + pos/2 - maxlen/2;     }else     {         newStrStart = s + pos/2 - (maxlen/2 - 1);     }      free(newStr);     free(intAry);  //2.为什么这个free会出错     newStr = (char*)malloc(sizeof(char) * maxlen);     memcpy(newStr, newStrStart, maxlen - 1 );     newStr[maxlen-1] = '\0';      return newStr; }  int main() {     char str[] = "bb";     printf("%s\n",longestPalindrome(str));     return 0; } [quote=引用 8 楼 qimi_and_softkitty 的回复:]  哎?是我编译工具有问题吗。。。 上传的时候显示input为"bb"时结果不对。。。不懂。。。 [/quote]   谢谢谢谢。通过了呢。 确实是 while(*mvp == *mvq)         {             len+=1;             mvp--;             mvq++;         } 这里越界了。我默认为越界他们取值会不等然后退出。没有考虑到同时越界的话取值会相等。  但是 intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 1)); for(int i = 0 ; i < (strlen(s) * 2 + 1); i++) 这个是没有越界的哦~  总而言之，多谢了。

不好意思，我仔细看了代码，用不同的编译器调试了一下，确实是有问题的。你说的两个问题都是用指针模拟数组时引起的访问越界。 free(intAry)这个报错是因为申请空间不够，既然后面的for循环中i都取到(strlen(s) * 2 + 1)了，那你申请的intAry空间自然是不够了，最后访问越界了。因此要跟上面的newStr一样(strlen(s) * 2 + 2) intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));  至于你说的本地运行能够出bb，提交之后是空串，我觉得是下面的访问越界引起的： 你的代码中for循环里面的while循环中mvp--;这句在执行的时候，也一样越界了，你可以自己单步调试一下看看，就明白了         while(*mvp == *mvq)         {             len+=1;             mvp--;             mvq++;         } 因此这里需要加一个限制条件，以下的测试代码供参考 #include<stdio.h> #include<string.h> #include<stdlib.h>  char* longestPalindrome(char* s) {     char *newStr = NULL;     char *newStrStart = NULL;     char *mvp = NULL;     char *mvq = NULL;     int  *intAry = NULL;     int   len = 0, maxlen = 0, pos = 1;      if(strlen(s) < 2)         return s;      /*set new str  [aba] => [#a#b#a#] */     newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));     memset(newStr,0,sizeof(newStr));     mvp = s;     mvq = newStr;     while(*mvp != '\0')     {         *mvq = '#';         *(mvq+1) = *mvp;          mvp++;         mvq = mvq + 2;     }     *mvq = '#';     *(mvq+1) = '\0';      /*cal len[i]*/     intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 2));     memset(intAry,0,sizeof(intAry));     for(int i = 0 ; i < (strlen(s) * 2 + 2); i++)     {         len = 1;         intAry[i] = 1;         mvp = newStr + i - 1;         mvq = newStr + i + 1;         if(mvp < newStr || mvq >= (newStr + strlen(newStr)))         {             continue;         }          while( (*mvp == *mvq) &&(mvp - newStr >= 0))         {             len+=1;             mvp--;             mvq++;         }          intAry[i] = len;          if(len > maxlen)         {             maxlen = len;             pos = i;         }     }      /*cal start pos*/     if(pos % 2 == 0)     {         newStrStart = s + pos/2 - maxlen/2;     }else     {         newStrStart = s + pos/2 - (maxlen/2 - 1);     }      free(newStr);     free(intAry);  //2.为什么这个free会出错     newStr = (char*)malloc(sizeof(char) * maxlen);     memcpy(newStr, newStrStart, maxlen - 1 );     newStr[maxlen-1] = '\0';      return newStr; }  int main() {     char str[] = "bb";     printf("%s\n",longestPalindrome(str));     return 0; } 引用 8 楼 qimi_and_softkitty 的回复:哎?是我编译工具有问题吗。。。 上传的时候显示input为"bb"时结果不对。。。不懂。。。

引用 7 楼 zangfong 的回复:我用codeblocks运行没错 呀貌似#include<stdio.h> #include<string.h> #include<stdlib.h>  char* longestPalindrome(char* s) {     char *newStr = NULL;     char *newStrStart = NULL;     char *mvp = NULL;     char *mvq = NULL;     int  *intAry = NULL;     int   len = 0, maxlen = 0, pos = 1;      if(strlen(s) < 2)         return s;      /*set new str  [aba] => [#a#b#a#] */     newStr = (char*)malloc(sizeof(char) * (strlen(s)*2 +2));     mvp = s;     mvq = newStr;     while(*mvp != '\0')     {         *mvq = '#';         *(mvq+1) = *mvp;          mvp++;         mvq = mvq + 2;     }     *mvq = '#';     *(mvq+1) = '\0';      /*cal len[i]*/     intAry = (int *)malloc(sizeof(int) * (strlen(s) * 2 + 1));      for(int i = 0 ; i < (strlen(s) * 2 + 1); i++)     {         len = 1;         intAry[i] = 1;         mvp = newStr + i - 1;         mvq = newStr + i + 1;         if(mvp < newStr || mvq >= (newStr + strlen(newStr)))         {             continue;         }          while(*mvp == *mvq)         {             len+=1;             mvp--;             mvq++;         }          intAry[i] = len;          if(len > maxlen)         {             maxlen = len;             pos = i;         }     }      /*cal start pos*/     if(pos % 2 == 0)     {         newStrStart = s + pos/2 - maxlen/2;     }else     {         newStrStart = s + pos/2 - (maxlen/2 - 1);     }      free(newStr);     free(intAry);  //2.为什么这个free会出错     newStr = (char*)malloc(sizeof(char) * maxlen);     memcpy(newStr, newStrStart, maxlen - 1 );     newStr[maxlen-1] = '\0';      return newStr; }  int main() {     char str[] = "abcdabcba";     //char *res=longestPalindrome(str);     printf("%s\n",longestPalindrome(str));     return 0; } 哎?是我编译工具有问题吗。。。 上传的时候显示input为"bb"时结果不对。。。不懂。。。

看来是我想错呢，抱歉

引用 2 楼 user-2 的回复:newStrStart = s + pos/2 - maxlen/2;你这行代码有什么用？你赋值给newstrstart的都是数字吧。  后面这里。newstrstart被用来指向回文起点~

引用 3 楼 user-2 的回复:抱歉看错呢，应该是pos和maxlen的值与s指向的地址想加超出s的范围newStrStart=s+pos/2-maxlen/2以上只是我的猜测  没有呢。我有debug哦~

你的newStr字符指针为什么会传会空指针是因为你在传回去之前就已经释放掉呢


Question: 新手求救

引用 4 楼 sghcpt 的回复:楼主，把相应代码改为下面代码看看~~~~ if (flag3 == 1)printf("Your password is tai luan le.\n"); else if (flag1 == 1 && flag2 == 1)printf("Your password is wan mei.\n"); else if (flag1 == 1 && flag2 == 0)printf("Your password needs zi mu.\n"); else if (flag2 == 1 && flag1 == 0)printf("Your password needs shu zi.\n");谢谢，就是这里出错了

引用 5 楼 zjjone 的回复:不好意思说反了，应该把(flag1==0&&flag2==1)修改为(flag1 == 1 && flag2 == 0)谢谢，就是这里出错了

(flag1==0&&flag2==1)和(flag1&&!flag2)这能一样吗？改为(!flag1&&flag2) 你这是在考大家眼力啊

else if(a[i]=='.') ;  //这个括号是中文吧

什么错误提示？


Question: 新手求救

难不成你想说你输入完成后程序智淑初一个结果就结束了，没办法继续输入？

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


Question: gets函数的一些问题

引用 5 楼 qq_35194071 的回复:[quote=引用 4 楼 wang0635 的回复:] 因为前面 scanf("%d",&n); 输入最后的回车，也会被后面的 gets(a); 得到，成一个空字符串，所以实际要多循环一次，第一次就是处理空串的 哦，所以就要用getchar()来释放回车，然后就可以正常了是吧。[/quote] 可以的，那样n就不用加一了

引用 4 楼 wang0635 的回复:因为前面 scanf("%d",&n); 输入最后的回车，也会被后面的 gets(a); 得到，成一个空字符串，所以实际要多循环一次，第一次就是处理空串的 哦，所以就要用getchar()来释放回车，然后就可以正常了是吧。

如果，没有n+1，他只能输出7行

输入 8 A-T B-F C-F D-F C-T B-F A-F D-F A-F D-F C-F B-T B-T A-F C-F D-F B-F D-T A-F C-F A-T C-F B-F D-F D-T B-F C-F A-F C-T A-F B-F D-F 输出 13224143

不知道爲啥，這樣其實比n多出了一次循環。也許要看原題目的要求吧，或者這句根本就是錯的。


Question: C/C++ 这段代码什么意思啊

0xc0 | (wch >> 6)这个是计算下表的。 wch先先向右偏移6位，得到的值在与0xc0取或。最后得到的结果就是数组的下表。通过数组下表找到对应的数组值，然后在与encoded求和，将得到的结果赋值给encoded.  下一句同理

从 if (wch <= 0x07FF) {        // non-ASCII <= 0x7FF 这行代码的注释来看，是处理非ASCII字符的，至于下面的代码是什么意思，应该要根据代码上下文或者函数功能说明来判断比较吧。。

具体不知道什么含义，就代码而言就是把一个小于0x07FF的数字，拆成前5位后6位的的两段，然后再对应到hexenc中的编码 形如110XXXXX，10XXXXXX这样的两部分，然后和hexenc对应 这个结构看起来和UTF8的定义是一样的，你可以参考一下UTF8的定义

谢邀。 楼主代码是截了urlencode的一部分吧。 如果楼主想问这个干吗用的，我能回答是url转码用的。防止中文乱码的。 具体为啥要这么写，本人对字符的定义没有咋研究过，帮不上忙哈。


Question: void *类型强制转换输出数据有问题

void test(void * handle) { 	printf("%d\n", ((AAA *)handle)->a); }  格式问题


Question: 关于typedef

实际效果是一样的，只是可读性的区别

这个根据情况定的，比如typedef char *a[5]与typedef char（*a)[5]这两个意思就不同

看你自己怎麽理解方便了，效果一樣的。 一般來説我習慣於給一個長運算式子加一些括號，以方便閲讀，即使不加括號不影響運算順序。

第二个没必要加括号，加了括号似乎更不好理解了。

个人感觉这种typedef (int *) test 更清晰一点

需要括号的时候必须有括号，不需要的时候最好不写

test1 my_test1; 	test my_test; 	 	int a = 1; 	my_test = &a; 	my_test1 = my_test; my_test和my_test1的值相同，所以说以上两个typedef定义的类型别名等价。


Question: 数组逆序代码求教

个数为奇数的时候，中间那个根本就不用处理，所以直接  i<N/2 就可以了

#include<iostream> using namespace std;  // 打印 void printArr(int *arr, int len) {     int i = 0;     for (i=0; i<len; i++) {         cout << arr[i] << " ";           }     cout << endl; }   // 反转数组 void reverse(int *arr, int len) {     int i = 0;     int n = len/2;      for (i = 0; i<n; i++) {         int tmp = arr[i];         arr[i] =  arr[len-i-1];         arr[len-i-1] = tmp;     } }  int main() {     int arr[] = {4,1,9,2,10,0};     int len = sizeof(arr)/sizeof(int);     int n = len / 2;     int i = 0;      printArr(arr, len);      reverse(arr, len);      cout << "逆序后的结果是：" << endl;     printArr(arr, len);      return 0; }

1.原代码中变量j未使用，会有warning一处，可删除变量j； 2.原代码中只有当i=0时发生了交换，可将2修改为2.0. 新代码： #define N 5 #include<stdio.h> void main() { 	int nums[N]={16,25,9,90,23}; 	int i,temp; 	for(i=0;i<=N/2.0-1;i++) 	{ 		temp=nums[i]; 		nums[i]=nums[N-i-1]; 		nums[N-i-1]=temp; 	} 	printf("逆序后的结果是:\n"); 	for(i=0;i<N;i++) 		printf("%d  ",nums[i]); 	    printf("\n"); }

引用 7 楼 hdt 的回复:[quote=引用 6 楼 cfjtaishan 的回复:] 注意考虑到N是奇数是的问题。  for (i = 0; i < N / 2; i++) 偶数也是一样。 证明如下 一个序列是偶数 N 可以表示为 2M; 从1开始计数的话是 1,2,3....m,m+1...2m; 1到m的数量与m+1到2m的数量一致。 因为c++/c数组是从0开始计数，所以上边的序列依次减1 ，0，1，2。。。。m-1,m......2m-1 所以程序循环是从 0到 m-1; m=N/2  for( int i=0;i<m/2;i++)====>for(int i=0;i<N/2;i++)  以下留作业，证明 N为奇数上题循环依然是 for( int i=0;i<N/2;i++) [/quote] 偶数好说，主要是奇数的情况

正如楼上几位朋友所说，把交换数组元素位置的for循环代码改为 for (i = 0; i < N / 2; i++) 即可，此时无需考虑N是奇数还是偶数，如下图所示  可以看出，无论N是奇数还是偶数，交换N/2次即可实现数组的逆序

引用 14 楼 cfjtaishan 的回复:[quote=引用 7 楼 hdt 的回复:] [quote=引用 6 楼 cfjtaishan 的回复:] 注意考虑到N是奇数是的问题。  for (i = 0; i < N / 2; i++) 偶数也是一样。 证明如下 一个序列是偶数 N 可以表示为 2M; 从1开始计数的话是 1,2,3....m,m+1...2m; 1到m的数量与m+1到2m的数量一致。 因为c++/c数组是从0开始计数，所以上边的序列依次减1 ，0，1，2。。。。m-1,m......2m-1 所以程序循环是从 0到 m-1; m=N/2  for( int i=0;i<m/2;i++)====>for(int i=0;i<N/2;i++)  以下留作业，证明 N为奇数上题循环依然是 for( int i=0;i<N/2;i++) [/quote] 偶数好说，主要是奇数的情况[/quote] 真是没办法，什么东西都要讲透了，才能明白？不知道举一反三吗？ 设 N 为奇数，基数可以表示为2m+1； 序列的下标为 1，2，3,....m,m+1,m+2.....2m+1; 可以知道 1到m ,和 m+2到 2m+1 数量相同。 c/c++ 数组从0开始计数 所以 上边序列计数为 0，1，2，3...m-1,m,m+1......2m; 要把上述序列依此对调，所以循环为 for( int i=0;i<m;i++)   又知 x 为整型情况下 c/c++ (2*x+1)/2 = x m = (2m+1)/2 2m+1=N 因此 循环为 for(int i=0;i<N/2;i++)

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

引用 2 楼 zhangchm2018 的回复：[quote=引用 1 楼 zhangchm2018 的回复:] for (i = 0; i < (N / 2.0 - 1); i++) / 左右两边都是 int，结果为 int，5 / 2 = 2 / 左右两边有一个是 double，结果自动转换为 double，5 / 2 = 2.5[/quote]感谢

引用 1 楼 zhangchm2018 的回复:for (i = 0; i < (N / 2.0 - 1); i++) / 左右两边都是 int，结果为 int，5 / 2 = 2 / 左右两边有一个是 double，结果自动转换为 double，5 / 2 = 2.5

for (i = 0; i < (N / 2.0 - 1); i++)

引用 10 楼 真相重于对错 的回复：[quote=引用 9 楼 zhangchm2018 的回复:] [quote=引用 3 楼 qq_38786775 的回复:] [quote=引用 2 楼 zhangchm2018 的回复：][quote=引用 1 楼 zhangchm2018 的回复:] for (i = 0; i < (N / 2.0 - 1); i++) / 左右两边都是 int，结果为 int，5 / 2 = 2 / 左右两边有一个是 double，结果自动转换为 double，5 / 2 = 2.5[/quote]感谢[/quote] 想了想偶数的情况，应该 for (i = 0; i <= (N / 2.0 - 1); i++)[/quote] 看我上边的证明[/quote]感谢

引用 9 楼 zhangchm2018 的回复:[quote=引用 3 楼 qq_38786775 的回复:] [quote=引用 2 楼 zhangchm2018 的回复：][quote=引用 1 楼 zhangchm2018 的回复:] for (i = 0; i < (N / 2.0 - 1); i++) / 左右两边都是 int，结果为 int，5 / 2 = 2 / 左右两边有一个是 double，结果自动转换为 double，5 / 2 = 2.5[/quote]感谢[/quote] 想了想偶数的情况，应该 for (i = 0; i <= (N / 2.0 - 1); i++)[/quote] 看我上边的证明

引用 3 楼 qq_38786775 的回复:[quote=引用 2 楼 zhangchm2018 的回复：][quote=引用 1 楼 zhangchm2018 的回复:] for (i = 0; i < (N / 2.0 - 1); i++) / 左右两边都是 int，结果为 int，5 / 2 = 2 / 左右两边有一个是 double，结果自动转换为 double，5 / 2 = 2.5[/quote]感谢[/quote] 想了想偶数的情况，应该 for (i = 0; i <= (N / 2.0 - 1); i++)

引用 7 楼 hdt 的回复:[quote=引用 6 楼 cfjtaishan 的回复:] 注意考虑到N是奇数是的问题。  for (i = 0; i < N / 2; i++) 偶数也是一样。 证明如下 一个序列是偶数 N 可以表示为 2M; 从1开始计数的话是 1,2,3....m,m+1...2m; 1到m的数量与m+1到2m的数量一致。 因为c++/c数组是从0开始计数，所以上边的序列依次减1 ，0，1，2。。。。m-1,m......2m-1 所以程序循环是从 0到 m-1; m=N/2  for( int i=0;i<m/2;i++)====>for(int i=0;i<N/2;i++)  以下留作业，证明 N为奇数上题循环依然是 for( int i=0;i<N/2;i++) [/quote] for( int i=0;i<m;i++)====>for(int i=0;i<N/2;i++)

引用 6 楼 cfjtaishan 的回复:注意考虑到N是奇数是的问题。  for (i = 0; i < N / 2; i++) 偶数也是一样。 证明如下 一个序列是偶数 N 可以表示为 2M; 从1开始计数的话是 1,2,3....m,m+1...2m; 1到m的数量与m+1到2m的数量一致。 因为c++/c数组是从0开始计数，所以上边的序列依次减1 ，0，1，2。。。。m-1,m......2m-1 所以程序循环是从 0到 m-1; m=N/2  for( int i=0;i<m/2;i++)====>for(int i=0;i<N/2;i++)  以下留作业，证明 N为奇数上题循环依然是 for( int i=0;i<N/2;i++)

用STL最方便  #include <iostream> #include <list> #include <algorithm> #include <iterator> using namespace std; int main() { 	list<int> a{1,2,3,4,5,6}; 	reverse(a.begin(),a.end()); 	ostream_iterator<int> it(cout," "); 	copy(a.begin(),a.end(),it); }  输出：  6 5 4 3 2 1 按 <RETURN> 来关闭窗口...

for (i = 0; i < N / 2; i++) {      }


Question: ubuntu16编译vlc3的win32库make时报 undefined reference to '_imp____acrt_iob_func' 求解

长时间没登录了，抱欠，这个问题一般在2.几的版本用CONTROLB不匹配时产生的，3.0版本以上不用CONTROLB，不会产生这个问题，3版本以上看我的博客里有相关编译说明，依路子编译基本都能编译出来

楼主请问，你这个问题在你帖子中没看明白具体怎么解决的，能简单说一下吗？

长时间没来，解决办法可以看我的贴子啦

楼主解决了么,,我在ubuntu16下编译vlc3.0.4也遇到同样的问题

自已再顶下，求高手

有人能帮看下吗？

楼上请问下，我依据UBUNTU编译VLC的WIN32库，  所有的源码都是在GIT上获取的，需要有改动吗？

win32 是windows下的，  API 不兼容呀呀，应该选linux 或者平台通用项目

请高手帮看下VLC编译的问题，

是提示找不到符号，但所有代码都是在VLC官网上DWON的，试了多个版本，编译也是按上面的步骤做的，  现在这个错误不知道怎么解决，谁能帮看下，不胜感激

提示找不到符号

有高手能帮忙看下吗？多谢


Question: 结构体指针做形参，实参可用结构体数组访问？？

引用 9 楼 qq_34991245 的回复:[quote=引用 1 楼 wang0635 的回复:] 以数组形式出现的形参，实际上就是指针。写成数组形式只是为了好看。真正的数组自己是无法作为参数用的 这里的确是可以用指针访问，但是在访问超过temp[0].a的时候，并没有对其他的temp[i].a赋值，如果temp[i].a的地址刚好被其他数据占用，就会发生一些意想不到的错误。[/quote] ① 没有对 temp[i].a 赋值，因为系统并没有给该程序分配这块内存，所以当你赋值后，该值仍然不确定，因为有可能这块内存的值被其他程序改变过，也有可能这块程序未被其他程序改变，像你的结果一样。 ②  因为 C 语言对指针不做限制，所以能利用指针访问到未分配的内存，如果这块内存已经被占用，就会发生冲突。

引用 1 楼 wang0635 的回复:以数组形式出现的形参，实际上就是指针。写成数组形式只是为了好看。真正的数组自己是无法作为参数用的 这里的确是可以用指针访问，但是在访问超过temp[0].a的时候，并没有对其他的temp[i].a赋值，如果temp[i].a的地址刚好被其他数据占用，就会发生一些意想不到的错误。

数组确实可以作为参数，传递是指针 不过楼主想问的估计是为什么结构体能用下表访问

指针可以作为数组

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

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

你传递进去的是指针  了解一下 形参 值传递 和 指针传递吧

形参是： ①数组名，传递的是地址； ②指针，   传递的是地址。 所以，传递的都是相同的东西，只是表达方式不同。


Question: 关于fgetc(stdin)返回负数

引用 12 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  //test.c #include <stdio.h> int main() {     int c;     unsigned char uc;     while (1) {         c=fgetc(stdin);         if (EOF==c) break;         uc=(unsigned char)c;         printf("0x%02X ",uc);     }     return 0; } //C:\tmp>hexdump ff.dat //00000000 - 01 02 81 82 ff fe ff ff // //C:\tmp>test < ff.dat //0x01 0x02 0x81 0x82 0xFF 0xFE 0xFF 0xFF   赵老师您太厉害了，用您的确实没问题，我也回过头去看了我之前的代码，可能是当时熬夜太晚脑子糊涂了，本来没问题的代码被注释了，然后有问题的代码是先赋值给了char数组再判断的，真的是糊涂了，多谢老师您醍醐灌顶！话说老师您真活跃，经常看到您的身影呢！

int fgetc(FILE *stream)   你需要注意的是 fgetc 返回的是 int 类型的值，在正常读取的情况下，返回的整数均小于 256，即 0x00~0xFF，而结束符 EOF通常定义为 -1，其值是 0xFFFF 或者 0xFFFFFFFF。  引用 楼主 weixin_39158150 的回复:用fgetc读文件流，每个字节都是正数，因此可以用-1表示结尾，但是用fgetc读标准输入，得到的值不是0-255了，而是-128-127，为什么会这样？这样无法判断输入的结束了吗？   事情的起因是我想直接把手机截图存进数组，代码为 adb shell screencap | 我的程序 ，当输入的图片数据全部结束后，它就会一直输入-1， 用echo abc | 我的程序 测试了也一样。求助，想判断输入的结尾。

引用 2 楼 sghcpt 的回复:楼主，能不能先把你截图的图片保存到文件中，然后再调用fgetc读取文件流，看看是否也有负数出现，如果是，那么应该就是图片中数据涉及到使用负数表示的值了。。那么就想其它办法解决了。。 “想判断输入的结尾”至于判断结尾，如果上面都不好判断，那么还是把数据保存到文件，判断读取文件是否结束比较好处理点。 这个方法肯定可以，二进制文件都差不多，只是fgetc读文件的取的每个字节是0-255，所以能正常用EOF判断结尾，但直接输入的方式可以为负数，这样EOF就没有了意义。方法是可以，就是效率太低了。

引用 3 楼 zhao4zhong1 的回复:int c; unsigned char uc; whie (1) {  c=fgetc(stdin);  if (EOF==c) break;  uc=(unsigned char)c;  printf("0x%02X ",uc); }  赵老师，这个应该是不可以的吧，接收标准输入的范围在-128 - 127，每个字节都有可能出现-1，怎么能用-1来判断结尾呢？

引用 1 楼 Slzde_sub 的回复:  应该是signed char  和 unsigned char的关系  你可以尝试转换一下，，我没用过这个函数  不太清楚 不可能的，用unsigned就不可能得到-1，也就是得不到EOF

引用 10 楼 turingo 的回复:看我7楼的回复，要按照16位或者32位来理解-1，一个字节0xff是255而不要理解为-1。  [quote=引用 9 楼 weixin_39158150 的回复:] [quote=引用 8 楼 user-4 的回复:] 连续读取到与图片大小相同数量的-1，作为结尾。 也就是读取两张图片，一张是原图，一张是全是-1的图。 如果事先知道图片有多大的话，那我直接获取图片大小的数据就行了，何必再获取多一倍的数据来判断[/quote][/quote] fgetc(stdin)从标准输入读取，-1可太多了，如果是白色图片，基本上全是-1，范围都只要-127 - 128，没有255

看我7楼的回复，要按照16位或者32位来理解-1，一个字节0xff是255而不要理解为-1。  引用 9 楼 weixin_39158150 的回复:[quote=引用 8 楼 user-4 的回复:] 连续读取到与图片大小相同数量的-1，作为结尾。 也就是读取两张图片，一张是原图，一张是全是-1的图。 如果事先知道图片有多大的话，那我直接获取图片大小的数据就行了，何必再获取多一倍的数据来判断[/quote]

引用 8 楼 user-4 的回复:连续读取到与图片大小相同数量的-1，作为结尾。 也就是读取两张图片，一张是原图，一张是全是-1的图。 如果事先知道图片有多大的话，那我直接获取图片大小的数据就行了，何必再获取多一倍的数据来判断


Question: vs2010   error C4430 怎么解决？

引用 2 楼 m0_37690319 的回复:vs   需要预编译头 #include "stdafx"    还有    int  main(){} 谢谢，已解决，stdafx用windows.h代替了，然后main前加了int，程序就不再报错了

#include<stdio.h> main (void) { int x,y; printf("x="); y=scanf("%d",&x); printf("x=%d,y=%d",x,y); return 0; }  改为 int main(void)


Question: leetcode第三题《无重复字符的最长子串》

引用 1 楼 user-1 的回复:int lengthOfLongestSubstring(char* s) {     int maxLen = 0;     int len = 0;     char *p = s;   //当前位置     char *ps = s;  //当前子串起始位置     char *pc = s;  //循环比较       while('\0' != *p)     {         while(pc != p)         {             if(*pc == *p)             {                 maxLen = maxLen > len?maxLen:len;                 len = 0;                 ps = ps++;                 pc = ps;                 p = ps;                 break;             }             pc++;         }           p++;         len++;         pc = ps;     }     maxLen = maxLen > len?maxLen:len;     return maxLen; } ① 标红出的逻辑不对，ps++就好，不然就变成： ps = ps; ps++; ② 当找到重复字符的时候，len不用清0，p也不用重置，因为剩余的字符串肯定不会重复。  多谢。已解决。


Question: Linux c AES/ CBC/PKCS7/PKCS5加密代码有个接口函数没有看懂。

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


Question: C语言 短信pdu解码编码 USC2

对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A  void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }


Question: c语言是否可以实现根据#define定义的不同level使高于这个level的代码参与编译

log分等级是鸡肋。个人意见。

引用 4 楼 boxmanstan 的回复:[quote=引用 2 楼 杀意已决的回复:]你的思路是对的，区分了不同等级的log，只需要在你的PRINT里处理一下就可以了 参照一楼，用几个宏就行了[/quote] 你好，参照我的回复，能详细解释一下吗？谢谢

引用 1 楼 zhao3132453 的回复:调试输出放到条件中，就只有debug下才会输出 #ifdef  _DEBUG printf(...); printf(...); #endif 没有太明白你的做法，也可能是我没有说清楚 目前所有的调试输出都是基于PRINT这个函数，至于debug level也是在这个函数内部进行判断的，所以如果编译所有的debug level都会参与编译，无法做到部分编译，如下  PRINT(debug_level Level, const char *outString, ...) {     if(IsOutput(Level))     {         printf(outString,...);     } }

引用 2 楼 杀意已决的回复:你的思路是对的，区分了不同等级的log，只需要在你的PRINT里处理一下就可以了 参照一楼，用几个宏就行了

可以的，在PRINT中這麽用：  #if //符合某個條件時執行 #endif  編譯時指定debug級別，就可以控制編譯的内容 但是，你依然無法全部打開。 也可以考慮在編譯時指定優化級別使目標代碼更小

引用 13 楼 huchuanbin0110 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 为什么不使用代码生成技术呢？ 能否详细说一下如何实现，一头雾水。。。[/quote] 仅供参考：//codegen.c // 输入一组字符串，比如 // aa ss ddd dd 33 dd // 然后自动生成一个函数 int A(const char*); // 实现A("aa")返回0  A("ss")返回1 依次类推 #include <stdio.h> int main(int argc,char **argv) {     int i;     if (argc<2) {         printf("%s p1 [p2 ...] [>result.c]\nGenerate code int A(const char *a); 0==A(\"p1\") 1==A(\"p2\") ...",argv[0]);         return 1;     }     //printf("#include <string.h>\n");     printf("int A(const char *a) {\n");     for (i=0;i<argc-1;i++) {         printf("    if (0==strcmp(a,\"%s\")) return %d;\n",argv[i+1],i);     }     printf("    return -1;\n");     printf("}\n");     return 0; } //C:\test\Debug>codegen.exe //codegen.exe p1 [p2 ...] [>result.c] //Generate code int A(const char *a); 0==A("p1") 1==A("p2") ... //C:\test\Debug>codegen.exe aa ss ddd dd 33 dd //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} // //c:\test\Debug>codegen.exe aa ss ddd dd 33 dd >result.c // //c:\test\Debug>type result.c //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} //

引用 16 楼 DelphiGuy 的回复:见你另一贴... 完美的解决了我的问题，已在另一帖中加分了，多谢

见你另一贴...

按模塊打開debug信息也是可行的，改一下函數的架構吧，你要使PRINT函數在模塊中就決定調用與否：   ... #if _DEBUG_THIS_MOD PRINT(...); #endif ...

引用 12 楼 hzy_76 的回复:某些條件下代碼無效，正是你要的效果——有條件的編譯。這樣才能但這麽改的前提是IsOoutput是一個宏而不是函數。 但是你要的其實是完整的debug信息？那你開頭的思路就不通了，還是想想辦法優化代碼吧。 是的，我是想要完整的debug信息，但因为code size的问题，不得不将debug信息分级，在调试到哪个模块就开启哪个模块的debug信息，从而达到在有限的资源下实现debug的目标。

引用 11 楼 zhao4zhong1 的回复:为什么不使用代码生成技术呢？ 能否详细说一下如何实现，一头雾水。。。

为什么不使用代码生成技术呢？

引用 8 楼 zhao4zhong1 的回复:log分等级是鸡肋。个人意见。 求大神指点，如何实现能满足我的需求，即代码size可以减小，debug信息还可以正常输出？

引用 7 楼 hzy_76 的回复:代碼改成這樣  PRINT(debug_level Level, const char *outString, ...) { #if (IsOutput(Level))     {         printf(outString,...);     } #endif }  这样定义之后，#if 与 #endif之间的代码都无效了，即没有被编译，所以永远也无法执行#if之内的代码了。 即使将level定义一个固定的值，#if 与 #endif之间的代码同样无效


Question: 能否实现通过判断函数入参的值决定代码是否参与编译？

引用 4 楼 DelphiGuy 的回复:如果你要不满足LOG级别的输出部分彻底不生成代码，可以把LogOutput用宏实现： #define LogOutput(LogLevel, Msg) LogLevel <= LOG_LEVEL ? printf("%s\n", Msg) : 0  多谢大神！简单查了一下，搞定了！多谢多谢！

引用 4 楼 DelphiGuy 的回复:如果你要不满足LOG级别的输出部分彻底不生成代码，可以把LogOutput用宏实现： #define LogOutput(LogLevel, Msg) LogLevel <= LOG_LEVEL ? printf("%s\n", Msg) : 0  您提供的方法可行！ 我们的LogOutput函数入参要支持不定参数，请问#define的表达式该怎么写？ #define LogOutput(LogLevel, Msg,...) LogLevel <= LOG_LEVEL ? Output(LogLevel, Msg,...) : 0 Output函数中封装了printf，上边的宏定义编译报错，请问要怎么修改？

引用 1 楼 DelphiGuy 的回复:#define LOG_CRITICAL 0 #define LOG_ERROR    1 #define LOG_WARNING  2 #define LOG_INFO     3 #define LOG_DEBUG    4  #define LOG_LEVEL LOG_ERROR  void LogOutput(int LogLevel, const char *OutStr) {   if (LogLevel <= LOG_LEVEL) printf("%s\n", OutStr); } 这种方式还是会使所有打印的地方参与编译，所以不会减小代码的size，只是不满足条件的不输出而已，不会省多少空间 我想实现的是通过某种方式，使不满足一定level的输出不参与编译，这样才能节省非常可观的size

一楼方法可以 不过也只是省了一个参数入栈/寄存器和函数调用的指令 你确定真的能省很多空间？


Question: 请教c函数参数入栈的问题

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

如果你测试的可以这么写，如果是项目代码，这样写是很危险的，不同的编译器会编译出不同的结果，vs的话可以显式的定义函数调用约定，gcc不是很清楚了

看编译器不同，编译的方法不同，如果你用的gcc编译链接的，默认函数调用约定是stdcall，参数是从右至左压入栈的

个人观点：感觉是Windows下的编译器跟linux下的编译器在处理函数参数时，在栈中的处理方式不一样了，导致这样的结果。。

楼主，下面的是我在windows vs2013 控制台的输出： 你的第一个问题，add_normal2 和 add_normal3 输出如下(崩溃了)：  你的第二问题，这边输入的值如上：   可见是否你那边的linux编译器在代码中做了什么处理跟windows不一样，这样能不能认为是编译器不同导致的。

调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx

这个行为完全取决于平台、编译器。 一、最左边的参数，到底是在栈顶还是栈底，取决于环境。 二、栈元素之间的字节对齐，C标准里也没有规定。 还是建议用变参的辅助函数 va_list做，就安全了。 https://blog.csdn.net/dengzhilong_cpp/article/details/54944676


Question: 自定义函数声明时，形参为指针变量，指针变量名为什么可以为空？？

我突然想起来声明中可以不写形参，ok啦

聲明處只需要有類型，確實是這樣的。


Question: static STATUS_VAL ai是static的什么用法？

感谢各位，明白了

声明了一个名为 ai 的变量，该变量具有以下性质： ① 静态存储类型（在程序执行过程一直存在） 第一次进入到 ai() 函数时，定义一个类型为 STATUS_VAL 的变量 ai，并且在跳出 ai() 函数时不丢弃该变量。 第二次以及之后进入到 ai() 函数时不再定义变量 ai。STATUS_VAL 是定义的结构类型名，相当于 int，char，double 之类的。 ② 块作用域（从 ai() 函数的 左花括号{ 到 ai 函数的 右花括号} ）       只能在 ai() 函数的代码块中访问变量 ai。

函数定义了两个静态变量，1个 unsigned char 类型，1个自定义的结构体类型

引用 3 楼 user-3 的回复:静态变量 和局部变量不同 出了函数的定义域还是有效的中间的STATUS_VAL作用是什么呢？

静态变量 和局部变量不同 出了函数的定义域还是有效的

用的pic单片机

ai已定义为函数


Question: 请教大神为什么*p占用空间大小为8个字节，而*p+1 指向数组中第二个元素3

*p 指的是包含两个int的数组  你可以想象跟b 一样  所以两个int大小是8.   *p同时指向数组的[0]位置，它 + 1 指向的是[1] 所以 *（*p +1） 是 3  其实你把*p 当成整体去看 就相当于 int (*p)[2] 就跟申请了一个int 数组一样 c[2]  你sizeof(c) 不就得到8 么， 同时c + 1 指向的不就是数组的第二个值么。

int (*p)[2]                 类型 p     int ** *p   int*  所以sizeof(*p)    64位系统下 为8个字节，32位为4个字节 所以  *p+1  是下一个int的地址

A[B] *(A+B) *(B+A) B[A] //以上四行等价  "abc"[1] *("abc"+1) *(1+"abc") 1["abc"] //以上四行等价  A[0] *(A) 0[A] //以上三行等价

引用 6 楼 zhangchm2018 的回复:① 一维数组    int a[2]; 数组指针    int (*p)[2]； 所以，可以看成  a == *p，*p 就相当于一维数组的数组名，a[1] == a + 1 == *p + 1。  ② (*p)[2] 是数组指针， *p 指向的是一个含有 2 个 int 元素的数组，一个 int 占 4 个字节，两个占8个字节； 而理解上 * 和 [] 可以互换，所以 (*p)[2] 可以变成 p[][2]，当成一个二维数组，p = b，所以 p == b[0] == &b[、][0]，p 只占一个 int 字节，即 4。 输入错误，是 p == b[0] == &b[0][0]

因为p里面保存着b[0]的地址，而b[0](也就是*p)里保存着b[0][0]的地址，所以*p的大小是两个int的大小，而因为*p里是b[0][0]的地址，所以*p+1也就保存了b[0][1]的地址，在经过间接运算符取出该地址保存的值，得出结果就是b[0][1]。

*解引用，*p指向数组首地址，为啥它大小是8，我也理解的不是很透彻

引用 1 楼 user-6 的回复:因为P是数组指针，*p是数组首个元素，*p+1,相当于移向下一个地址。  既然是首个元素为什么占用空间为sizeof（int）*2

因为P是数组指针，*p是数组首个元素，*p+1,相当于移向下一个地址。


Question: STM32系列芯片可以直接通过输入捕获正弦波来计算正弦波的频率吗？

谢谢各位！问题我已经解决了，虽然测得频率不是非常准。对于前辈们说的FFT，因为我没用过FFT，不知道该怎么搞，所以这几天一直想通过其它方式来达到目的，最近才想用施密特触发器或者电压比较器来做，后来我发现我用的STM32F072CBT6这个芯片本身就自带比较器，所以我就尝试用比较器来转换成方波再来测频率，发现可行。之前一直不知道原来STM32芯片还有的自带比较器的，之前一直接触的是F1,F4，现在才知道F05,F07,F09这些系列的芯片自带比较器。

引用 13 楼 wqq995的回复:我试一下，不知道是我配置的AD是不是有问题，0V和3.3V的电压可以准确采样输出，但是0V-3.3V之间的电压就一直输出0.1V-0.2V之间的电压值，用AD来采样正弦波的时候采到的数据一直是：我也不知道哪里出了问题 信号频率多少，采样率多少? 其实你可以使用MATLAB仿真一下，确定好合适的采样率，这样可以确定你的代码是不是有问题

如果只是测频率，可以考虑使用adc采集信号，然后fft计算出频率。

刚才没看清楚，原来是要求底电平那些正弦啊，，这个频率太高了。应该像楼上说的， 不能在线分析。看你ADC能不能达到这么高的采样频率了。

这个目测有300kHz以上了，STM32的话可用ADC模块采数据，然后离线分析，在线实时处理可能不太现实，毕竟运算能力有限。 建议UP换个示波器。

电压比较已经把电压变成0，1状态，当然能捕获。当然正弦波型的offset不能变，幅度也不能变得太明显。 使用捕获就可以啊，计算两个高电平或者低电平开始点的间隙就是周期。基本上M3，M0 系列的都有这个功能。

用·STM32系列芯片有什么办法捕获如下图所示的方波低电平时间段内的正弦波并计算出频率吗？

这个正弦波已经是经过放大的了，把这个正弦波转化为方波之后幅值应该还是小吧？还能捕获到吗？

幅值太小了。 可以外面加一个电压比较器转成方波。

配置如下： 那个clock prescaler只有同步四分频和异步模式两种选择，已开启DMA中断，一直奇怪采样不到0V-3.3V之间的电压数据

用DMA应该能达到 这个速率吧。

STM32不是普遍支持1MHz以上采样吗

那个正弦波的频率大概在500K左右，用的是F0芯片，用ADC的话它的采样周期加上转化周期已经将近2us，差不多是这个正弦波的一个周期时间了，ADC应该搞不定，才接触这个STM32cubeMX,用的是HAL库，公司因为要与其它公司对接要求用这个cube来做，各位前辈有什么办法？

底部波形的频率大概是多少，采样频率要满足奈奎斯特吧，你在用是stm32自带的dsp库，里面有fft算法，查看幅值，应该能求出大概的频率

引用 7 楼 DelphiGuy 的回复:他这图方波频率3.35KHz，低电平那部分占比大约1/3，理论上来说用10KHz采样就可以了。他说的是低电平那个蜜蜜麻麻的。


Question: HTTP/1.1 400 Bad Request   大神 救命啊

建议学会使用wireshark抓包工具。

发送数据的问题，用Fiddler等工具先找正确的数据！

加上Host:，先试试主页。

bad request只是一个结果。如同上面回复的，你用fidder或者wireshark抓个包，学会看你那个请求，从你发出，到每个网关，到返回。看哪个环节出了问题。

引用 5 楼 focuslight 的回复:你截取一下发送数据分析一下， socket工具利用上啊..........  GET /api? q=happy&from=EN&to=zh_CHS&appKey=03890ba142bc8320&salt=5&sign=4c38fd44d0f62bc1cbd3e419881a87c0 HTTP/1.1 Content-Type: application/x-www-form-urlencoded Connection:close      这就是发送的数据。有不对的地方嘛

你截取一下发送数据分析一下， socket工具利用上啊..........

引用 3 楼 user-7 的回复:你也是牛，有现成的http客户端api 不用，自己socket实现客户端。  = =就是想写一个，这个不是重点。重点是该怎么解决啊

你也是牛，有现成的http客户端api 不用，自己socket实现客户端。

有没有大神来帮忙看看

找了好久了。脑子都炸了


Question: C语言，有个问题没有琢磨清楚，请大神帮忙

前面缓冲区没清干净，变成了 "后四位\n身份证18位" ，%d读数遇空白字符停止，所以%14d读了“后四位”

需要清理缓存区，setbuf(stdin, NULL);或者在输入前面加getchar();

是输入的缘由吧

你的第二个scanf语句再看看

还是输入问题吧

第一个“scanf”这样样scanf("%*6%4d%2d%2d%*s",&year,&month,&day);

你的第二个scanf语句再看看

输入合法性校验的路很长，水很深。

谢谢大神的解答，我看了之后，在原代码上又增加了一个字段，弄清楚了这个问题。 #include<stdio.h>  void main(void) {  int year,month,day,num,wrong; scanf("%*6d%4d%2d%2d",&year,&month,&day); printf("你的生日是:%4d-%02d-%02d\n",year,month,day);  scanf("%14d%4d",&wrong,&num); printf("%014d,%04d\n",wrong,num);  }  这个代码很清楚了显示了错误原因。wrong的输出内容是之前一次还在缓存区内的后四位，并且在这四位数前面补的全部为0，之后才开始显示第二次SCANF的内容。 所以有两种方式解决： 1、在第一次SCANF后清除缓存；（参考一楼） 2、在第一次SCANF时就把后四位*清除。（参考三楼）

感觉好多道道啊

你的第二个scanf语句再看看

多学习，程序后面是不是缺少了结束语，返回

输入输出还真是有很多门道啊。

输入合法性校验的路很长，水很深。

还是输入问题吧

输入检验够程序员吃一辈子了。

楼上正解，原因是你输入的内容是先传送到缓存区，然后再传送给程序，比如身份证号有23位，你在第一个scanf里只接收了16位，余下的位数就会作为第二个scanf的输入。我记得c标准库里有一个函数是自动抛弃余下的位数(好像是gets_s)。

楼上正解  第一个输入的只有14位，不是一个完整的身份证号

引用 3 楼 user-17 的回复:#include<stdio.h>  void main(void) {  	int year,month,day,num[4];	// num[4]考虑末尾带X的情况 	scanf("%*6d%4d%2d%2d%*4s",&year,&month,&day); 	printf("你的生日是:%4d-%02d-%02d\n",year,month,day);  	scanf("%*14d%4s",num); 	printf("%04s\n",num);   }第一次scanf的时候少读取了身份证后四位，导致它在第二个scanf被认为是%*14d的部分


Question: 请问微信PC段怎么快速发起联系人对话。QQ用下面的代码可以，微信是否能实现呢？

引用 1 楼 user-2 的回复:楼主，可以试试参照QQ这种方式写注册表的方式，试试能不能放在微信上使用：可参考下面链接. https://www.cnblogs.com/phinecos/archive/2009/03/06/1404951.html  不过，感觉要实现楼主你说的问题，估计需要微信支持方式才行~~~ 你能可以实现先吗？可以有偿，麻烦了！


Question: c 语言串口发送接受问题

把sizeof(a) 和sizeof(s)的大小打印出来看一下应该就知道了。

感觉发到嵌入式板块比较好


Question: 链式堆栈出现中断错误

不去学习如何调试，每次遇到中断都来论坛问，就永远没有提高

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

引用 4 楼 qq894040717 的回复:[quote=引用 3 楼 qq_32579021 的回复:] 132行这里，你在for循环中调用了(ListStackPop(&head, &x) == 0)，这个方法循环后，head当前已经移动到最后一个，所以在释放时，出错。 你应该在释放前，让head取第一个节点，这样应该就没有问题了谢谢。解决思路是这样的。 但是把for循环用判空函数替换后，还是出现中断。请问怎么解决呢？ “while (ListStackEmpty(&head)!=0)”  [/quote]  你再“while (ListStackEmpty(&head)!=0)”  [/quote]之前，使用一个变量来保存head,之后就算head指向的路径不是第一个了，但是保存的那个变量还是指向头，最后释放的时候，将这个变量放入，而不是head.这样就又是从头开始遍历了。

再帮我看看吧，总是在链式队列或者堆栈中出现这样的问题。 #include <stdio.h> #include <stdlib.h> #include <malloc.h>  //定义抽象数据 typedef int DataType; typedef struct queue{ 	DataType data; 	struct  queue *next; }Queue;  //定义链式队列的头尾指针 typedef struct{ 	Queue *front; 	Queue *rear; }ListQueue;  //链式队列初始化 void ListQueueInit(ListQueue *myQ) { 	myQ->front = NULL; 	myQ->rear = NULL; }  //链式队列判断是否为空 int ListQueueNoEmpty(ListQueue myQ) { 	if (myQ.front==NULL) 	{ 		return 1; 	} 	else 	{ 		return 0; 	} }  //链式队列的入队操作 int ListQueuePush(ListQueue *myQ, DataType x) { 	Queue *pTemp; 	if ((pTemp=(Queue*)malloc(sizeof(Queue)))==NULL) 	{ 		return 0; 	} 	pTemp->data = x; 	if (myQ->rear!=NULL)    //第一次入队的时候rear为null所以不执行。 	{ 		myQ->rear->next = pTemp; 	} 	myQ->rear = pTemp;     //将队尾指针指向第一个入队的元素。 	if (myQ->front==NULL) 	{ 		myQ->front = pTemp;//将队头指针指向第一个入队的元素，然后不再移动。 	} 	return 1; }  //链式队列的出队操作 int ListQueuePop(ListQueue *myQ, DataType *x) { 	ListQueue *del; 	if ((del = (ListQueue*)malloc(sizeof(ListQueue))) == NULL) 	{ 		return 0; 	} 	if (myQ->front==NULL&&myQ->rear==NULL) 	{ 		return 0; 	} 	*x = myQ->front->data; 	del->front = myQ->front; 	myQ->front = myQ->front->next; 	if (myQ->front==NULL)//如果只有一个节点 	{ 		myQ->rear = NULL; 	} 	free(del); 	return 1; }  //链式队列取队头 int ListQueueTop(ListQueue *myQ,DataType *num) { 	if (myQ->front==NULL) 	{ 		return 0; 	} 	*num = myQ->front->data; 	return 1; }   //销毁队列内存 void ListQueueDes(ListQueue **myQ) { 	ListQueue *temp,*pre; 	if ((temp = (ListQueue*)malloc(sizeof(ListQueue))) == NULL) 	{ 		exit(1); 	} 	pre = *myQ; 	while (pre!=NULL) 	{ 		temp = pre->front; 		pre->front = pre->front->next; 		free(temp); 		temp = NULL; 	} 	(*myQ)->front = NULL; 	(*myQ)->rear = NULL; }  //主函数 int main() { 	ListQueue *Q; 	int i,m; 	DataType x;  	ListQueueInit(&Q); 	for ( i = 0; i < 10; i++) 	{ 		if ((ListQueuePush(&Q, i + 1)) == 0) 		{ 			printf("1error"); 			getchar(); 			return; 		} 	} 	if ((ListQueueTop(&Q,&m))==0) 	{ 		printf("2error"); 		getchar(); 		return; 	} 	else 	{ 		printf("队头：%d\n", m); 	} 	/*while ((ListQueueNoEmpty(Q)) != 1)*/ 	i = 10; 	while (i--) 	{ 		if ((ListQueuePop(&Q,&x))==0) 		{ 			printf("3error"); 			getchar(); 			return; 		} 		else 		{ 			printf("%d    ", x); 		} 	} 	ListQueueDes(&Q); 	getchar(); 	return 0; } 引用 1 楼 user-4 的回复:楼主，有几处代码不对，可以参考参考下面代码： //这是一个链式堆栈的判空、压栈、出栈、取栈顶等操作 #include <stdio.h> #include <stdlib.h> #include <malloc.h>   #define MaxSize 100 #define T 1 #define F 0  typedef int DataType; typedef struct stack{ 	DataType data; 	struct stack *next; }ListStack;  //堆栈初始化  void ListStackInit(ListStack** stack) { 	if (((*stack) = (ListStack*)malloc(sizeof(ListStack))) == NULL) 	{ 		exit(1); 	} 	(*stack)->next = NULL; }  //堆栈判断是否为空  int ListStackEmpty(ListStack *stack) { 	if (stack->next == NULL) 	{ 		return 0; 	} 	else 	{ 		return 1; 	} }  //堆栈进栈  int ListStackPush(ListStack *stack, DataType x) { 	ListStack *pTemp; 	if ((pTemp = (ListStack*)malloc(sizeof(ListStack))) == NULL) 	{ 		return 0; 	} 	pTemp->data = x;  	pTemp->next = stack->next; 	stack->next = pTemp; 	return 1; }  //堆栈出栈  int ListStackPop(ListStack *stack, DataType *x) { 	ListStack *del; 	del = stack->next;//赋值 	if (del == NULL) 	{ 		return 0; 	}  	stack->next = del->next; 	*x = del->data; 	free(del); 	return 1; }  //堆栈取出栈顶  int ListStackTopPop(ListStack *stack, DataType *n) { 	if (stack->next == NULL) 	{ 		return 0; 	} 	else 	{ 		*n = stack->next->data; 		return 1; 	} }  //链表销毁 void ListDestroy(ListStack** stack) { 	ListStack *pTemp, *del;  	pTemp = *stack; 	pTemp = pTemp->next; 	while (pTemp != NULL) 	{ 		del = pTemp; 		pTemp = pTemp->next; 		free(del); 		del = NULL; 	} 	free(*stack); 	*stack = NULL; }  //主函数  int main() { 	ListStack* head; 	int x, i, m;  	ListStackInit(&head); 	for (i = 0; i < 10; i++) 	{ 		if ((ListStackPush(head, i + 1)) == 0) 		{ 			printf("插入错误\n"); 			getchar(); 			return 0; 		} 	} 	ListStackTopPop(head, &m); 	printf("栈顶=%d\n", m); 	 	for (i = 0; i < 10; i++) 	{ 		if ((ListStackPop(head, &x) == 0)) 		{ 			printf("取出错误\n"); 			getchar(); 			return 0; 		} 		else 		{ 			printf("%d   ", x); 		} 	}  	free(head); //因为前面调用了ListStackPop函数，已经把一些元素释放掉内存了，所以这里直接调用free头就可以了。 	head = NULL;  	getchar(); 	return 0; }

引用 1 楼 user-4 的回复:楼主，有几处代码不对，可以参考参考下面代码： //这是一个链式堆栈的判空、压栈、出栈、取栈顶等操作 #include <stdio.h> #include <stdlib.h> #include <malloc.h>   #define MaxSize 100 #define T 1 #define F 0  typedef int DataType; typedef struct stack{ 	DataType data; 	struct stack *next; }ListStack;  //堆栈初始化  void ListStackInit(ListStack** stack) { 	if (((*stack) = (ListStack*)malloc(sizeof(ListStack))) == NULL) 	{ 		exit(1); 	} 	(*stack)->next = NULL; }  //堆栈判断是否为空  int ListStackEmpty(ListStack *stack) { 	if (stack->next == NULL) 	{ 		return 0; 	} 	else 	{ 		return 1; 	} }  //堆栈进栈  int ListStackPush(ListStack *stack, DataType x) { 	ListStack *pTemp; 	if ((pTemp = (ListStack*)malloc(sizeof(ListStack))) == NULL) 	{ 		return 0; 	} 	pTemp->data = x;  	pTemp->next = stack->next; 	stack->next = pTemp; 	return 1; }  //堆栈出栈  int ListStackPop(ListStack *stack, DataType *x) { 	ListStack *del; 	del = stack->next;//赋值 	if (del == NULL) 	{ 		return 0; 	}  	stack->next = del->next; 	*x = del->data; 	free(del); 	return 1; }  //堆栈取出栈顶  int ListStackTopPop(ListStack *stack, DataType *n) { 	if (stack->next == NULL) 	{ 		return 0; 	} 	else 	{ 		*n = stack->next->data; 		return 1; 	} }  //链表销毁 void ListDestroy(ListStack** stack) { 	ListStack *pTemp, *del;  	pTemp = *stack; 	pTemp = pTemp->next; 	while (pTemp != NULL) 	{ 		del = pTemp; 		pTemp = pTemp->next; 		free(del); 		del = NULL; 	} 	free(*stack); 	*stack = NULL; }  //主函数  int main() { 	ListStack* head; 	int x, i, m;  	ListStackInit(&head); 	for (i = 0; i < 10; i++) 	{ 		if ((ListStackPush(head, i + 1)) == 0) 		{ 			printf("插入错误\n"); 			getchar(); 			return 0; 		} 	} 	ListStackTopPop(head, &m); 	printf("栈顶=%d\n", m); 	 	for (i = 0; i < 10; i++) 	{ 		if ((ListStackPop(head, &x) == 0)) 		{ 			printf("取出错误\n"); 			getchar(); 			return 0; 		} 		else 		{ 			printf("%d   ", x); 		} 	}  	free(head); //因为前面调用了ListStackPop函数，已经把一些元素释放掉内存了，所以这里直接调用free头就可以了。 	head = NULL;  	getchar(); 	return 0; }  谢谢你，又是你来回答了。 但是把for循环用判空函数替换后，还是出现中断。请问怎么解决呢？ “while (ListStackEmpty(&head)!=0)”

引用 3 楼 qq_32579021 的回复:132行这里，你在for循环中调用了(ListStackPop(&head, &x) == 0)，这个方法循环后，head当前已经移动到最后一个，所以在释放时，出错。 你应该在释放前，让head取第一个节点，这样应该就没有问题了谢谢。解决思路是这样的。 但是把for循环用判空函数替换后，还是出现中断。请问怎么解决呢？ “while (ListStackEmpty(&head)!=0)”


Question: 好像对最基本的if都理解有误了……

写错一个true ——>false

这是代码，不是数学公式 if没有这样用的

编程语言不是数学语言

谁告诉你if可以这么用的

基本语法没有掌握          double n, output = 0.0; 	scanf("%lf", &n); 	if (100000<n && n<= 200000) 		output += (n - 100000)*0.075; 	if (0<n && n<= 100000) 		output += n*0.1; 	printf("%lf", output);  lz写法从数学角度是对的， 但从c的角度来说是不对的


Question: 二维动态数组的内存分配错误

当局者迷旁观者清。 引用 2 楼 user-2 的回复:在int **ApplyTwo( int row, int col)函数中的下面代码：  if ((array[i] = (DataType *)malloc(col * sizeof(DataType))) == NULL); 再最后面多了一个分号，把分号去掉试试~~~~~~~~~应该改为如下代码：  if ((array[i] = (DataType *)malloc(col * sizeof(DataType))) == NULL)

学习而已，没必要用库函数。 引用 1 楼 Slzde_sub 的回复:   #include<vector> using std::vector;  vector<vector<int>> vecValueArray;   这不就完事了吗。。。你写了一大堆还怕错

if ((array[i] = (DataType *)malloc(col * sizeof(DataType))) == NULL); 注意这条语句的后面多一个分号


Question: openssl报错error:140A6041:SSL routines:ssl_create_cipher

楼主，您好!     我也遇到该问题了，我的错误打印是： 4062180368:error:140A604[ 2483.884425@3] invalid toddr src 1:SSL routines:ssl_create_cipher_list:malloc failure:ssl/ssl_ciph.c:1334: 4062180368:error:140A90A1:SSL routines:SSL_CTX_new:library has no ciphers:ssl/ssl_lib.c:2583  请问您是怎么解决的，希望能得到你的回复，谢谢。

https://www.cnblogs.com/crunchyou/archive/2013/01/23/2872722.html 仅供参考


Question: 用C语言这样写哪里错了啊？？

引用 1 楼 cfjtaishan 的回复:内存不满足条件？C语言的版本很明显占用的内存比较大，建议使用动态申请空间的形式。 我发现，<br data-filtered="filtered">是浏览器问题。。

引用 1 楼 cfjtaishan 的回复:内存不满足条件？C语言的版本很明显占用的内存比较大，建议使用动态申请空间的形式。  但是题目内存限制是64MB，测试结果内存是远远不到的，还有<br data-filtered="filtered">这个东西我没写过怎么会显示的？

引用 4 楼 user-2 的回复:不是内存的问题，对比了一下你的两段代码，我觉得应该是你自己在写C版本的时候，一个条件写错了else if(t.de<H&&t.cai<H&&t.de>t.cai)这里应该是else if(t.de<H&&t.cai<H&&t.de>=t.cai)哇，厉害啊大神，膜拜膜拜，还是我自己不够仔细，非常感谢！


Question: 关于RC4加密抵御“已知明文攻击”的疑惑

rc4本来就弱, 用rc4就是不太在乎被解密, 只要成本高一点, 有能力解密的人不愿意去解密就行了.

一般通信头部是不加密的, 可以附加crc校验.

引用 3 楼 qq510015356 的回复:[quote=引用 1 楼 donjin9 的回复:] 看它密钥流生成的算法，确实是固定的。知道足够长的密钥流，就能解密了。  之前自己理解错了，以为每次加密前都要重新初始化S盒，现在看资料，应该是只在第一连接时初始化S盒，之后S盒不断往后滚动  但这又存在另一个问题，如果中间丢包怎么办，一旦丢包了，通信双方的S盒就不同步了，不就无法实现解密了吗？ 这样岂不是像UDP这样的协议就无法应用RC4了。[/quote] 中间丢包本来就是很严重的问题。所有的分组加密算法中间丢了包，组可能都混乱了，解密当然很麻烦。

哦，是直接使用之前重排过的S啊。我也是理解不够。

引用 1 楼 donjin9 的回复:看它密钥流生成的算法，确实是固定的。知道足够长的密钥流，就能解密了。  之前自己理解错了，以为每次加密前都要重新初始化S盒，现在看资料，应该是只在第一连接时初始化S盒，之后S盒不断往后滚动  但这又存在另一个问题，如果中间丢包怎么办，一旦丢包了，通信双方的S盒就不同步了，不就无法实现解密了吗？ 这样岂不是像UDP这样的协议就无法应用RC4了。

奉劝楼主不要把有限的生命浪费在无限的加密解密死循环中！

看它密钥流生成的算法，确实是固定的。知道足够长的密钥流，就能解密了。


Question: 数数并说——数据存储，内存分配问题

但是这样以来，我分配的内存都没有释放。好吧，不知道咋搞了，先放着吧。记一下。

#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h>  char* countAndSay(int n); int _tmain(int argc, _TCHAR* argv[]) { 	char * final_sa = countAndSay(21); 	printf("%s\n", final_sa);  	system("PAUSE"); 	//free(final_sa); 	return 0; } char* countAndSay(int n)  {	 	char *final_say;//可以把定义和初始化分配内存分开处理，这样就好了。还是怪自己基础太差了。。 	int length = 0; 	int count = 0, id = 0;	 	if (n > 1) 	{ 		char * before_say = countAndSay(n - 1); 		length = strlen(before_say); 		final_say = (char*)malloc((length * 2 + 1) * sizeof(char));//单独分配； 		char temp = before_say[0]; 		for (size_t i = 0; i < length; i++) 		{ 			if (before_say[i] == temp && i < length - 1) 			{ 				count++; 			} 			else if (before_say[i] != temp && i < length - 1) 			{ 				final_say[id] = count + '0'; 				id++; 				final_say[id] = temp; 				id++; 				temp = before_say[i];				 				count = 1; 			} 			if (before_say[i] == temp && i == length - 1) 			{ 				count++; 				final_say[id] = count + '0'; 				id++; 				final_say[id] = temp; 				id++; 			} 			else if(before_say[i] != temp && i == length - 1) 			{			 				final_say[id] = count + '0'; 				id++; 				final_say[id] = temp; 				id++; 				final_say[id] ='1'; 				id++; 				final_say[id] = before_say[i]; 				id++; 			} 		} 		final_say[id] = '\0'; 		//free(before_say); 	} 	else 	{ 		final_say = (char*)malloc(2 * sizeof(char));//单独分配； 		final_say[0] = '1'; 		final_say[1] = '\0'; 	} 	return final_say; }

简单一点，char *final_say = new char; 这个是看你电脑里剩余多少内存去分配的，比较大，但是你用的太大可能会new失败或者奔溃，比如你在循环里一直new就容易出错

参考输出： 1.     1 2.     11 3.     21 4.     1211 5.     111221 6.     312211 7.     13112221 8.     1113213211 9.     31131211131221 10.    13211311123113112211 11.    11131221133112132113212221 …… 2147483647

题目： 报数序列是指一个整数序列，按照其中的整数的顺序进行报数，得到下一个数。其前五项如下：  1.     1 2.     11 3.     21 4.     1211 5.     111221 1 被读作  "one 1"  ("一个一") , 即 11。 11 被读作 "two 1s" ("两个一"）, 即 21。 21 被读作 "one 2",  "one 1" （"一个二" ,  "一个一") , 即 1211。  给定一个正整数 n ，输出报数序列的第 n 项。  注意：整数顺序将表示为一个字符串。  示例 1:  输入: 1 输出: "1" 示例 2:  输入: 4 输出: "1211"

引用 4 楼 Slzde_sub 的回复:另外针对这个题，，  你用string多好呀。。。 他这个题目给的函数返回值就是char*。 另外，这个函数，输入的值越大，最后输出的字符串就越长。输入11就已经是27的长度了，最大输入值是2147483647，具体输出是多长我还没算出来。所以我想的是，长度的定义，可以根据输入判断，或者可以自行分配啥的。不然，如果所有的输入都被付这么大的空间，还用到递归，很浪费的。


Question: 求助，关于C语言字符串数组函数问题

你可以想一下，在功能函数的内部 指针（st+1）到底是指向本行的下一个元素，还是下一行呢？如果按照你的逻辑，它指向下一行，那么它是如何知道指针+1的操作是指针偏移了多少个char?

谢谢楼上各位，讲解得很细致，我已经明白了

1.void print_string(char (*st)[256], int lim)； 2.void print_string(char [LIM][256], int lim); 3.void print_string(char [ ][256], int lim); 这三种方式均可以。 二维数组传参自然可以用二维数组来接收。所以2,3成立  print_string(input, LIM);中input指的是二维数组首元素的地址，二维数组首元素的地址为第一行的地址，但第一行为一个字符串数组，需要用数组指针来接收。所以1成立。

楼主，可以查查“二维数组传参”相关字眼，有相应的文章说明二维数组传参的方法。下面是其中一种方法： #include <stdio.h> #include <string.h>  #define SIZE 256 #define LIM 2  void print_string(char st[][SIZE], int lim);  int main(void) { 	char input[LIM][SIZE] = { 		"my", 		"be" 	}; 	print_string(input, LIM);  	return 0; }  void print_string(char st[][SIZE], int lim) { 	int i; 	for (i = 0; i < lim; i++) 		puts(st[i]); }  而至于你上面说的为什么不能用char**str作为参数，因为当把这种二维数组的指针直接作为参数传递时，数组名退化为指针，函数并不知道数组的列数，SIZE对它来说是不可见的，所以第一层解引用会失败。这时，编译器可能会报warning，或者运行生成的文件会发生segment fault。引用网友在文章的图说明：(链接:http://www.cnblogs.com/wuyuegb2312/archive/2013/06/14/3135277.html)  栈上分配的二维数组数组名int array[3][3]的真实类型是int [ ][ ]，在作为右值时才被转化为(int *array)[N]，和int **是不同的。把前者进行强制转换为后者，在函数中对元素操作也会导致段错误，上图面用图来说明二者区别。

正确的写法是void print_string(char (*st)[256], int lim)，你用char**也是不严谨的，因为你的input是个二维数组，char*只能表示一维数组  况且**叫指向指针数据的指针，char (*st)[256]叫数组指针，char *st[256]叫指针数组


Question: 帮我看看是不是realloc出的问题

对于你的代码，我做了简单修改，但是基本上原文不变，只是为了我容易调试代码而改的。代码后加了些注释，表示我对代码修改的意见。    #include<stdio.h> #include<stdlib.h> int main() { 	int n; 	int i; 	int m,k; 	char c; 	char *t;  	printf("How many STRING will you input\n"); 	scanf("%d",&n); 	fflush( stdin ); 	printf("Input STRING and end with #\n");  	for( i=0;i<n;i++) 	{ 		m=1; 		k=0; 		c=getchar(); 		fflush( stdin );  //TODO: stdin是系统的输入缓存，所有键盘输入的字符暂存在这里，不清除多余的字符就会影响下次读取，这里是将多余的字符清理掉，最好选择性使用这个 		t=(char *)malloc(0); //TODO: 这里做没什么作用，等同：t=NUll 		while(c!='#') 		{ 			t=(char*)realloc((void *)t,m);  //TODO: 这里的m似乎永远只等于1，那就没必要再声明一个变量了，直接写1，程序看起来就好多了 			t[k]=c;  //TODO: 字符串需要以'\0'结束，因为打印时需要以'\0'作为结束符 			c=getchar();	 			fflush( stdin ); 		} 		printf("%s\n",t); 	} 	return 0; }

t=(char*)realloc((void *)t,m); t[k]=c; m为1，那么这个t已经是越界了，少个用于存放'\0'的空间，因为后面你是printf 按照%s输出的。 可能t[k++] = c;才是真是逻辑。但是这样以来就更越界了。  t=(char *)malloc(0);  这条语句没有意义，和t = NULL;没有区别。

t[k++]=c 另外，你的输入的\n貌似没有没有处理。

仅供参考：//文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; }


Question: 初学C语言, 一个简单的问题求解.

调用约定 https://msdn.microsoft.com/zh-cn/magazine/9b372w95.aspx

引用 5 楼 kaixindzl 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素  谢谢!  看了几分钟提示要会员才能看了.[/quote] 怪CSDN为维持生存而利欲熏心喽。

终于搞清楚了.  是C函数参数传递方式与delphi不同引起的.   printf 函数数值类型参数是一股脑压入栈中,  然后把控制权转移到printf, 但读取时是根据转换说明符指定的长度去栈中依次读取. 如果对应数据长度不对就会发生指针错位, 取错值.  还是一错到底..    随便说一下:  delphi参数一般不是压栈的方式传递. 很多时候是把参数指针传递给 EAX EDX ECX之类的寄存器, 调用时按指针值去内存地址中读取(除非用 stdcall 标明用C形式调用.)

引用 3 楼 zhao4zhong1 的回复:http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素  谢谢!  看了几分钟提示要会员才能看了.

引用 2 楼 user-2 的回复: 上图为在内存中，t值的储存方式。 通过第一个printf语句可以推出，%#llx取8个字节的数据，然后倒序输出（我是这么理解的）。 通过第三个printf语句可以推出，%#x取4个字节的数据，然后倒序输出。 两个t值的全部内容：        88 77 66 55 44 33 22 11 88 77 66 55 44 33 22 11 第一个printf语句的解释方式：        88 77 66 55 44 33 22 11 | 88 77 66 55 44 33 22 11|（全部都已解释） 第二个printf语句的解释方式：        88 77 66 55 | 44 33 22 11 88 77 66 55 |（44 33 22 11 这部分不被解释） 第三个printf语句的解释方式：        88 77 66 55 | 44 33 22 11 | （88 77 66 55 44 33 22 11 这部分不被解释）  谢谢耐心解释, 不明白的是, printf取参数时, 难道不是按变量的对应指针地址来取的吗?  按理说 %#x取4个字节的数据时, 应该从t指针的低32位取值啊. 为啥在同一函数时第二次取值时取了高32位的值呢?

提醒：printf是开源的。 参考crt\src\output.c


Question: 关于一个程序中含有多个scanf的问题

第一个scanf，应该是lf，不是1f，1f是输出格式


Question: free函数删除卡壳

需要加判断是否为空后才 free

既然是最后一个节点，那么是不是应该删除p，而不应该是q，需要确认下q是否为NULL

如果你删除的是最后一个结点，那么p指向最后一个结点，，q=p->next q就为空 p->next=q->next就会崩溃

分配内存要判断 是否为空 而释放内存依然要判断 并且确保该指针没有被 free 过 (如果该指针被 free 过，你就要看该指针是否为空 还要看它是否为野指针)

在free()函数之前，加一个对q指针的判断  if(q != NULL) free(q);

引用 楼主 qq_36358731 的回复: 我是删除链表的最后一个结点出的问题，删除其他地方的结点都是好的。 为什么在free这一行卡壳了，是free函数不能删除最后一个结点，还是什么问题，或者说free函数有什么使用条件  楼主，应该是free(q)导致的,而q这时值应该空值了，所以会崩溃。

扯

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

如果i是从0开始排位置的话，没看出什么问题呀