Question: 对指针常量取址的问题

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

引用 5 楼 u010087712 的回复:值是一样的，因为它们在内存所处的位置一样。 &a是数组的地址，a是数组第一个元素的地址， 就好比有一排房屋，a第一个房间的地址，&a是这排房屋的起始地址， 都是在同一个地方。 正解

引用 1 楼 user-5 的回复:老生常谈, int a[100]; &a 获取数组自己本身的地址(的指针), a获取数组第一个元素的地址(的指针), 两者的差别就是"类型", 这两个的类型不同, 前者是int(*)[100], 后者是int*    引用 2 楼 sinat_24674017 的回复:int(*)[100]是个什么类型，没有见过  指向数组的指针

int(*)[100]是个什么类型，没有见过


Question: 关于单链表

int initList(LNode *&A) {//初始化     A=(LNode*)malloc(sizeof(LNode));//申请A的头结点空间     A->next=NULL;//初始时头结点后面指向NULL     return 0; }  时A->data未赋值。 for(int i=0;i<n;++i)     {         s=(LNode*)malloc(sizeof(LNode));//开辟新插入的结点s的空间         s->data=e[i];         r->next=s;         r=r->next;     } A->next->data=e[0];(即‘@’） A->next->next->data=e[1];（即‘t')

不知道*&2个一起用是要闹哪样

C语言也用引用了?


Question: C语言的字面值问题

int型也是一样，被存放在.rodata区域，也就是只读区。

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533


Question: C语言有没有全面完整的在线“官方文档”，谢谢

引用 4 楼 learnc2015 的回复:[quote=引用 1 楼 lianshaohua 的回复:] http://en.cppreference.com/w/c 这个链接是哪家公司维护的，其中的把() 说成是function all显然不准确，或者说不完整 [/quote] 作为operator,  () 有两种形式  () function call (type) Type cast   当然括号还有其他的用途，比如 Syntax            primary-expression:                   identifier                   constant                   string-literal                   (  expression )

引用 4 楼 learnc2015 的回复:[quote=引用 1 楼 lianshaohua 的回复:] http://en.cppreference.com/w/c 这个链接是哪家公司维护的，其中的把() 说成是function all显然不准确，或者说不完整 [/quote] 是function call  LZ是不是还想说(type)这个？下面有的啊。  另外这个链接不是哪家公司维护的，是“热心的开源人士”维护的。 想必C也不是“哪家公司”就能维护的吧。  其实这个参考算是不错的了，基本上就这几个： http://en.cppreference.com/w/ http://www.cplusplus.com/reference/ 然后就是MSDN了  如果LZ要“官方”，去下标准吧。

//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 | //+------------------+-----------------------------------------+---------------+

引用 4 楼 learnc2015 的回复:[quote=引用 1 楼 lianshaohua 的回复:] http://en.cppreference.com/w/c 这个链接是哪家公司维护的，其中的把() 说成是function all显然不准确，或者说不完整 [/quote] 什么意思，没看明白

引用 1 楼 lianshaohua 的回复:http://en.cppreference.com/w/c 这个链接是哪家公司维护的，其中的把() 说成是function all显然不准确，或者说不完整

c的，c++的，都有

引用 1 楼 lianshaohua 的回复:http://en.cppreference.com/w/c 谢谢，你这个是C++吧？


Question: 输入一组学生信息提示0xC0000005: 读取位置时发生冲突，输入多组学生信息没问题

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

引用 2 楼 baidu_26773407 的回复:[quote=引用 1 楼 adlay 的回复:] 第一个的 next 没有初始化  linklist Input_info() { 	linklist p, tail = NULL; 	long int Num; 	p = (linklist)malloc(sizeof(Student)); 	p->next = NULL;  // 这里增加一个初始化操作 	printf("请输入学生的学号:"); 	scanf("%ld", &Num); 	if (Num == 0) 		return NULL;  .... 怎么进行初始化。 p->next=NULLl;不就是初始化吗[/quote] 是啊，但是你没写啊，那一句是我给你加上的。

引用 1 楼 adlay 的回复:第一个的 next 没有初始化  linklist Input_info() { 	linklist p, tail = NULL; 	long int Num; 	p = (linklist)malloc(sizeof(Student)); 	p->next = NULL;  // 这里增加一个初始化操作 	printf("请输入学生的学号:"); 	scanf("%ld", &Num); 	if (Num == 0) 		return NULL;  .... 怎么进行初始化。 p->next=NULLl;不就是初始化吗


Question: 请问C语言可变参数后面的类型怎么能像printf函数那样，不是固定的，表达不清楚，希望有人可以懂我的意思？

比尔·盖茨没请示我就把“VS2010Express简体中文学习版”的下载和谐掉了！ 也难怪微软公司江河日下了！

引用 8 楼 u014626834 的回复:我晕，找不到  去私赵老师要

引用 12 楼 u014626834 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 还好有百度！ https://www.baidu.com/s?wd=VS2010Express%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%E5%AD%A6%E4%B9%A0%E7%89%88&rsv_spt=1&rsv_iqid=0xd9da5137000037c3&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_n=2&rsv_sug3=1   我的意思是找不到printf函数的在文件中的地方额...[/quote] File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\printf.c"       62:         retval = _output_l(stdout,format,NULL,arglist); File: "C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c"      940: int __cdecl _output_l (

没有什么高深的东西，声明函数的时候用  ...  就代表它接受可变参数了。 实现的时候，调用方会把实际传递的参数按照从右到左的顺序 push 到堆栈里面（可变参数只能使用 cdecl, 不能使用 stdcall 的），函数里面只要获得了第一个参数的地址，加上第一个参数的大小就可以获得第二个参数的地址了，后面的参数一样，只要知道了前面个参数的地址后大小，就可以得到后面一个参数了。 在 printf 中，每一个参数的大小是由其中的 %d 这种类型来获取的，实际上，绝大多的类型在传递的时候都是按 4 个字节来传递的。  在上面的基础上，标准库定义的一组处理可变参数的宏其实是很简单的。  va_list argptr;           // 定义一个指针 va_start(argptr, i);    // 通过第一个固定参数的地址来初始化指针为可变参数的起始地址 int n = va_arg( argptr, int );   // 取出一个值，并把指针加上这个类型的大小 va_end(argptr);         // 把指针置为 NULL

引用 11 楼 zhao4zhong1 的回复:还好有百度！ https://www.baidu.com/s?wd=VS2010Express%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%E5%AD%A6%E4%B9%A0%E7%89%88&rsv_spt=1&rsv_iqid=0xd9da5137000037c3&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_n=2&rsv_sug3=1   我的意思是找不到printf函数的在文件中的地方额...

我晕，找不到

为什么不直接参考printf的源代码呢？  先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\output.c

你还是先告诉我为什么吧？

这个问题比较深…… 建议先学会使用，在弄清楚为什么？

你这个代码是实现如果不是0就把下个参数当做字符串处理吗？

void testit ( int i, ...) {    va_list argptr;    va_start(argptr, i);     if ( i == 0 ) {       int n = va_arg( argptr, int );       printf( "%d\n", n );    } else {       char *s = va_arg( argptr, char* );       printf( "%s\n", s);    } }

搜过了，没有

lz都知道叫做"可变参数"了，为什么不去网上搜一下.


引用 3 楼 user-2 的回复:试试 if\s*?\([\s\w]+?=[^=]  我试了,当if中有多个条件时不能用.我自已看了一下正则教程,写了一个,简单测试一下,能用  搜索if或while条件中的单个等号 含有单个等号但不含有分号和换行符的行 [^<>!=]=[^=][^;\n]*\n   搜索for条件中的单个等号 ;.*[^<>!=]=[^=][^)\n]*;

将常量写在==的左边，变量或表达式写在==的右边，这样万一错将==写成=的时候，编译器会报错的。  使用pc_lint软件。

试试 if\s*?\([\s\w]+?=[^=]

引用 1 楼 user-2 的回复:正则表达式当然可以, 编译器自然也提供了,项目属性-C/C++ - 常规, 把警告等级调到等级4就行了. 不过自己经常在if中赋值, 使所以屏蔽了这个警告.GCC可以使用双括号来取消, 比如: if(( a = b ))......微软编译不认, 只能屏蔽了。  我把警告等级改成W4或Wall都不行,但是很久以前有印像会提示,不知道是不是哪个设置把这个给去掉了,我代码分析的时候使用"所有规则"都不提示这个问题  我用if.*={1}查找,不过这个正则不对,所有if都选中了,


Question: 求大神这程序哪里错了，快疯了。

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

C99之前不允许在语句之后出现声明。

int i; i = 0; int pos[MAX];  改为：  int i; int pos[MAX]; i = 0;

引用 7 楼 unprince 的回复:第10行的  i = 0;  要放到所有变量定义的后面 标准C不允许这样做   正解，请写成int i = 0;

第10行的  i = 0;  要放到所有变量定义的后面 标准C不允许这样做

引用 5 楼 qq_30239507 的回复:引用 3 楼 q3733353520 的回复:重新手打一遍我都换了一台电脑了，别的程序都好好的，这个一弄就这样。 看看各种符号((,;)，有没错，注意输入法

引用 1 楼 user-7 的回复:那里有错了?

重新手打一遍

引用 1 楼 user-7 的回复:那里有错了?+1但就是报错！

那里有错了?


Question: 到底什么是流式输入输出，和非流式有啥区别?

引用 14 楼 adlay 的回复:[quote=引用 13 楼 cc_mugiwala 的回复:] 反正意思是，不管多少udp客户端连进来，他们sendto发送完数据都是立即返回，服务端如果在线(建立socket，绑定端口)就会接收所有客户端的数据；然后服务端用recvfrom一个数据包一个数据包的读，其实在recvfrom之前服务器就已经接收到数据了，对不对？  你说tcp的recv可能只是某个send的一部分，意思是，在一个tcp连接里，我要用多次recv吗，，但是好像一般写代码好像也没有用多次recv啊。  1. 是的 2. 总之是你一次 recv 的数据和你一次 send 的数据没有对应关系，而 UDP 是对应的。要怎么样 recv 得看具体的情况，比如，你在传送一个文件，那么你把每次 recv 的内容依次写入文件就行了，不用管哪一次 recv 了多少字节；但是如果你要传送协议，比如每一个协议包是固定大小的，发送端虽然每次 send 了一个完整的包，接受端的一次 recv 就不一定是一个完整的包了，有可能只有半个，有可能是一个半， 这时你就需要把所有 recv 的内容先放到一个缓冲区，直到缓冲区里面的内容组成了一个完整的包后再从缓冲区里面取出包来处理。[/quote]  最后一个问题，如果服务器不在线，对于tcp来说，客户端连接肯定就失败；对于udp，由于没有连接，sendto还是会成功返回，那发送的数据去哪了，客户端发送数据完后，过了一天，服务器上线还可以收到数据吗

引用 13 楼 cc_mugiwala 的回复:反正意思是，不管多少udp客户端连进来，他们sendto发送完数据都是立即返回，服务端如果在线(建立socket，绑定端口)就会接收所有客户端的数据；然后服务端用recvfrom一个数据包一个数据包的读，其实在recvfrom之前服务器就已经接收到数据了，对不对？  你说tcp的recv可能只是某个send的一部分，意思是，在一个tcp连接里，我要用多次recv吗，，但是好像一般写代码好像也没有用多次recv啊。  1. 是的 2. 总之是你一次 recv 的数据和你一次 send 的数据没有对应关系，而 UDP 是对应的。要怎么样 recv 得看具体的情况，比如，你在传送一个文件，那么你把每次 recv 的内容依次写入文件就行了，不用管哪一次 recv 了多少字节；但是如果你要传送协议，比如每一个协议包是固定大小的，发送端虽然每次 send 了一个完整的包，接受端的一次 recv 就不一定是一个完整的包了，有可能只有半个，有可能是一个半， 这时你就需要把所有 recv 的内容先放到一个缓冲区，直到缓冲区里面的内容组成了一个完整的包后再从缓冲区里面取出包来处理。

引用 8 楼 adlay 的回复:[quote=引用 5 楼 cc_mugiwala 的回复:] [quote=引用 4 楼 jiqiang01234 的回复:] [quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  引用 4 楼 jiqiang01234 的回复:[quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  突然想到一个问题：         一般tcp服务端代码是这样的：首先循环监听一个套接字，如果有客户端连接进来，服务端就新建一个子进程，然后在这个子进程里再建一个套接字，用这个新的套接字交互，这样，可以同时接收多个连接；         但是udp服务端怎么同时和多个客户端交互，一般udp服务端都是用一个循环，然后循环里直接与客户端交互，并没有子进程，如果有一个客户端发了报文过来了，这时候服务端进入循环开始处理，这时候又有另外一个客户端发过来了，由于循环已经开始处理，那这另外一个客户端发的报文去哪了，丢掉了吗。。。。         还是说udp服务端就直接开N个进程，每个进程一个循环？？？感觉不科学。。。[/quote] 1. tcp 服务端的子进程里不是再创建一个套接字，而是使用 accept 返回的套接字。 2. udp 在处理的时候，后面来的包会排队的，超过一定的数量系统才会丢弃。      udp 没有连接状态，是直接处理包的。 服务器收到一个包，处理返回，然后继续读下一个包。 并不存在一个客户端的包来了就要循环处理这个客户端直到这个客户端退出。  -----------------  upd 的数据发送端一个 sendto 是什么数据，recvfrom 得到的就是什么数据，这是就是一个数据包，是上层的处理单位。 tcp 的 send 发送的数据，recv 的时候可能从只是某个 send 的一部分，也可能是多个 send 连在一起的，也可能是一个 send 有一半的数据，另一个又有一半的数据。  所以说，tcp 传递的数据是有序的，连续的，这就是流 udp 传递的数据是无序的，离散的，这就是数据报[/quote]  反正意思是，不管多少udp客户端连进来，他们sendto发送完数据都是立即返回，服务端如果在线(建立socket，绑定端口)就会接收所有客户端的数据；然后服务端用recvfrom一个数据包一个数据包的读，其实在recvfrom之前服务器就已经接收到数据了，对不对？  你说tcp的recv可能只是某个send的一部分，意思是，在一个tcp连接里，我要用多次recv吗，，但是好像一般写代码好像也没有用多次recv啊。

引用 11 楼 cc_mugiwala 的回复:[quote=引用 7 楼 jiqiang01234 的回复:] 如果正在处理器中一个udp连接，同时又有其他客户端啊发送数据。此时操作系统内部会保存其他udp的数据，等到下个循环再处理，当然如果有太多的客户端发送导致服务端没时间处理，就会丢掉 意思是，对于每个客户端就是一个循环。一个客户端连进来，发送数据，下一个客户端必须等到第一个客户端发送完(循环完)，在下一个循环中发送数据。。。这样理解对吗？[/quote]  我可能理解错了，应该是这样：  第一个客户端连进来，正在发送数据；此时第二个客户端也连进来了，它并不会等一个循环完，第二个客户端的sendto不会阻塞，也是立即返回的，发送的数据其实已经被服务器接收掉了，并存在系统里。只是在服务端必须用两次recvfrom循环的读出这两个客户端的数据，一个循环读一个客户端。。这样？

引用 7 楼 jiqiang01234 的回复:如果正在处理器中一个udp连接，同时又有其他客户端啊发送数据。此时操作系统内部会保存其他udp的数据，等到下个循环再处理，当然如果有太多的客户端发送导致服务端没时间处理，就会丢掉 意思是，对于每个客户端就是一个循环。一个客户端连进来，发送数据，下一个客户端必须等到第一个客户端发送完(循环完)，在下一个循环中发送数据。。。这样理解对吗？

引用 15 楼 cc_mugiwala 的回复:[quote=引用 14 楼 adlay 的回复:] [quote=引用 13 楼 cc_mugiwala 的回复:] 反正意思是，不管多少udp客户端连进来，他们sendto发送完数据都是立即返回，服务端如果在线(建立socket，绑定端口)就会接收所有客户端的数据；然后服务端用recvfrom一个数据包一个数据包的读，其实在recvfrom之前服务器就已经接收到数据了，对不对？  你说tcp的recv可能只是某个send的一部分，意思是，在一个tcp连接里，我要用多次recv吗，，但是好像一般写代码好像也没有用多次recv啊。  1. 是的 2. 总之是你一次 recv 的数据和你一次 send 的数据没有对应关系，而 UDP 是对应的。要怎么样 recv 得看具体的情况，比如，你在传送一个文件，那么你把每次 recv 的内容依次写入文件就行了，不用管哪一次 recv 了多少字节；但是如果你要传送协议，比如每一个协议包是固定大小的，发送端虽然每次 send 了一个完整的包，接受端的一次 recv 就不一定是一个完整的包了，有可能只有半个，有可能是一个半， 这时你就需要把所有 recv 的内容先放到一个缓冲区，直到缓冲区里面的内容组成了一个完整的包后再从缓冲区里面取出包来处理。[/quote]  最后一个问题，如果服务器不在线，对于tcp来说，客户端连接肯定就失败；对于udp，由于没有连接，sendto还是会成功返回，那发送的数据去哪了，客户端发送数据完后，过了一天，服务器上线还可以收到数据吗[/quote] 不可能一天后还能收到数据的。。。 服务器没在的话数据就丢失了，UDP 本来就是不可靠的

流式就是，抛开底层细节， 直接按照 一个字节（字节流）， 或者固定大小（块流）输入输出  实现上就是带缓冲的输入输出。 流的意思是连续不断，像流水一样。 C语言 有两套以上的输入输出函数 其中底层接口，就有两套 例如文件操作 面向句柄的：  _creat,_read,_write,_close creat,open,read,write,close C标准库的流操作 使用 FILE指针 函数为 fopen,fread,fwrite,fclose 以及其他函数，文件操作函数。    C++ 流就是 fstream 这些类  至于 TCP/UDP  TCP 是面向连接的，UDP 不是 他的流，和 文件流 不太一样。大致意思相仿佛，但不是一样的

引用 6 楼 cc_mugiwala 的回复:[quote=引用 5 楼 cc_mugiwala 的回复:] [quote=引用 4 楼 jiqiang01234 的回复:] [quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  引用 4 楼 jiqiang01234 的回复:[quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  突然想到一个问题：         一般tcp服务端代码是这样的：首先循环监听一个套接字，如果有客户端连接进来，服务端就新建一个子进程，然后在这个子进程里再建一个套接字，用这个新的套接字交互，这样，可以同时接收多个连接；         但是udp服务端怎么同时和多个客户端交互，一般udp服务端都是用一个循环，然后循环里直接与客户端交互，并没有子进程，如果有一个客户端发了报文过来了，这时候服务端进入循环开始处理，这时候又有另外一个客户端发过来了，由于循环已经开始处理，那这另外一个客户端发的报文去哪了，丢掉了吗。。。。         还是说udp服务端就直接开N个进程，每个进程一个循环？？？感觉不科学。。。[/quote]  我贴一个udp服务端的例子：  int main(){      int sockfd;      int len;      int z;      char buf[256];      struct sockaddr_in adr_inet;      struct sockaddr_in adr_clnt;      printf("waiting for client...\n");      adr_inet.sin_family=AF_INET;      adr_inet.sin_port=htons(port);      adr_inet.sin_addr.s_addr=htonl(INADDR_ANY);      bzero(&(adr_inet.sin_zero),8);      len=sizeof(adr_clnt);      sockfd=socket(AF_INET,SOCK_DGRAM,0);      if(sockfd==-1){        perror("socket error_1");        exit(1);      }      z=bind(sockfd,(struct sockaddr *)&adr_inet,sizeof(adr_inet));      if(z==-1){        perror("bind error_1");        exit(1);      }      while(1){        z=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&adr_clnt,&len);        if(z<0){          perror("recvfrom error_1");          exit(1);        }        buf[z]=0;        printf("接收：%s",buf);        if(strncmp(buf,"stop",4)==0){          printf("结束....\n");          break;        }      }      close(sockfd);      exit(0);   }  这个就是单独一个循环里面直接recvfrom，一次只能接收一个客户端的报文吗？？[/quote]  每一次调用 recvfrom 返回的都可能是不同的客户端的包 这个服务器是可以服务任意数量的客户端的，只要服务器性能够。

引用 5 楼 cc_mugiwala 的回复:[quote=引用 4 楼 jiqiang01234 的回复:] [quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  引用 4 楼 jiqiang01234 的回复:[quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  突然想到一个问题：         一般tcp服务端代码是这样的：首先循环监听一个套接字，如果有客户端连接进来，服务端就新建一个子进程，然后在这个子进程里再建一个套接字，用这个新的套接字交互，这样，可以同时接收多个连接；         但是udp服务端怎么同时和多个客户端交互，一般udp服务端都是用一个循环，然后循环里直接与客户端交互，并没有子进程，如果有一个客户端发了报文过来了，这时候服务端进入循环开始处理，这时候又有另外一个客户端发过来了，由于循环已经开始处理，那这另外一个客户端发的报文去哪了，丢掉了吗。。。。         还是说udp服务端就直接开N个进程，每个进程一个循环？？？感觉不科学。。。[/quote] 1. tcp 服务端的子进程里不是再创建一个套接字，而是使用 accept 返回的套接字。 2. udp 在处理的时候，后面来的包会排队的，超过一定的数量系统才会丢弃。      udp 没有连接状态，是直接处理包的。 服务器收到一个包，处理返回，然后继续读下一个包。 并不存在一个客户端的包来了就要循环处理这个客户端直到这个客户端退出。  -----------------  upd 的数据发送端一个 sendto 是什么数据，recvfrom 得到的就是什么数据，这是就是一个数据包，是上层的处理单位。 tcp 的 send 发送的数据，recv 的时候可能从只是某个 send 的一部分，也可能是多个 send 连在一起的，也可能是一个 send 有一半的数据，另一个又有一半的数据。  所以说，tcp 传递的数据是有序的，连续的，这就是流 udp 传递的数据是无序的，离散的，这就是数据报

引用 5 楼 cc_mugiwala 的回复:[quote=引用 4 楼 jiqiang01234 的回复:] [quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  引用 4 楼 jiqiang01234 的回复:[quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  突然想到一个问题：         一般tcp服务端代码是这样的：首先循环监听一个套接字，如果有客户端连接进来，服务端就新建一个子进程，然后在这个子进程里再建一个套接字，用这个新的套接字交互，这样，可以同时接收多个连接；         但是udp服务端怎么同时和多个客户端交互，一般udp服务端都是用一个循环，然后循环里直接与客户端交互，并没有子进程，如果有一个客户端发了报文过来了，这时候服务端进入循环开始处理，这时候又有另外一个客户端发过来了，由于循环已经开始处理，那这另外一个客户端发的报文去哪了，丢掉了吗。。。。         还是说udp服务端就直接开N个进程，每个进程一个循环？？？感觉不科学。。。[/quote]  我贴一个udp服务端的例子：  int main(){      int sockfd;      int len;      int z;      char buf[256];      struct sockaddr_in adr_inet;      struct sockaddr_in adr_clnt;      printf("waiting for client...\n");      adr_inet.sin_family=AF_INET;      adr_inet.sin_port=htons(port);      adr_inet.sin_addr.s_addr=htonl(INADDR_ANY);      bzero(&(adr_inet.sin_zero),8);      len=sizeof(adr_clnt);      sockfd=socket(AF_INET,SOCK_DGRAM,0);      if(sockfd==-1){        perror("socket error_1");        exit(1);      }      z=bind(sockfd,(struct sockaddr *)&adr_inet,sizeof(adr_inet));      if(z==-1){        perror("bind error_1");        exit(1);      }      while(1){        z=recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&adr_clnt,&len);        if(z<0){          perror("recvfrom error_1");          exit(1);        }        buf[z]=0;        printf("接收：%s",buf);        if(strncmp(buf,"stop",4)==0){          printf("结束....\n");          break;        }      }      close(sockfd);      exit(0);   }  这个就是单独一个循环里面直接recvfrom，一次只能接收一个客户端的报文吗？？

引用 4 楼 jiqiang01234 的回复:[quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  引用 4 楼 jiqiang01234 的回复:[quote=引用 3 楼 cc_mugiwala 的回复:] [quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到[/quote]  突然想到一个问题：         一般tcp服务端代码是这样的：首先循环监听一个套接字，如果有客户端连接进来，服务端就新建一个子进程，然后在这个子进程里再建一个套接字，用这个新的套接字交互，这样，可以同时接收多个连接；         但是udp服务端怎么同时和多个客户端交互，一般udp服务端都是用一个循环，然后循环里直接与客户端交互，并没有子进程，如果有一个客户端发了报文过来了，这时候服务端进入循环开始处理，这时候又有另外一个客户端发过来了，由于循环已经开始处理，那这另外一个客户端发的报文去哪了，丢掉了吗。。。。         还是说udp服务端就直接开N个进程，每个进程一个循环？？？感觉不科学。。。

引用 3 楼 cc_mugiwala 的回复:[quote=引用 2 楼 jiqiang01234 的回复:] “面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。[/quote] udp超过报文长度也会拆分发送，但udp是面向无连接的，如果被拆分的包有丢失，对方就没办法知道了。  如果想验证多次收发，建议用公网，局域网不容易看到

引用 2 楼 jiqiang01234 的回复:“面向流”就是源源不断地，分不清开始和结束的字节。每次的收发量不确定 ”面向报文“就是每次的收发都有最大的长度限制(即报文长度)，接收端每次都会接收到一个报文，也就能分清每次报文的开始和结束。 意思是tcp可以不管发送信息的大小，而udp超过一定的长度，就发送不了了吗？或者说，就接收不了or分几次接收？ 但是一般写socket程序，也没有看到有分几次接收的啊。。

非流即包


Question: c语言文件操作部分

fp=fopen(filename,"rb");	//以只读的的方式打开指定的文件 ch=fgetc(fp); while(ch=!EOF)      //当读入的字符值等于EOF时结束循环 { putchar(ch);	//将读入的字符显示 ch=fgetc(fp);	//fgetc函数继续返回一个字符给ch* }  改为:  fp=fopen(filename,"rb");    //以只读的的方式打开指定的文件     if (NULL==fp) {         printf("Can not open file %s!\n",filename);         return 1;     } while(!feof(fp))      //当读入的字符值等于EOF时结束循环 { ch=fgetc(fp);	//fgetc函数继续返回一个字符给ch* putchar(ch);	//将读入的字符显示 }

写C语言都不舍得把缓存弄大点. 原来fgetc返回的是char啊. 原来判断是否EOF用ch=!EOF啊.

#include <stdio.h> int main() {     FILE *fp;     char filename[256];     int ch;     printf("Please input filename:\n");     gets(filename); //输入文件名及其路径     fp=fopen(filename,"rb");    //以只读的的方式打开指定的文件     if (NULL==fp) {         printf("Can not open file %s!\n",filename);         return 1;     }     ch=fgetc(fp);     while (ch=!EOF) {         putchar(ch);    //将读入的字符显示         ch=fgetc(fp);   //fgetc函数继续返回一个字符给ch*     }     fclose(fp);     printf("\n");     return 0; }


Question: 需要一个C的下载软件纯代码

这里搞错了：if (CreateProcessA(NULL, "test.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {     WaitForSingleObject(pi.hProcess, INFINITE);     CloseHandle(pi.hProcess);     CloseHandle(pi.hThread); }

curl ？

C语言实现HTTP下载： http://blog.csdn.net/yellow_bug/article/details/6575470  c语言执行exe文件的方法很多，你自己百度下哪种适合你。

纯C的话需要通过底层的socket来操作，参考 http://www.dingguofeng.com/?p=424 。

看看wget的代码吧；

适用于 Windows 平台，Linux/UNIX 的话，则不需要 WSAStartup 和 WSACleanup，CreateProcess 也需修改。编译器需支持 C99，否则所有声明提前至所在块首。 #include <stdio.h> #include <stdlib.h>  #define WIN32_LEAN_AND_MEAN #define WIN32_DEFAULT_LIBS  #define WINVER          0x0501 #define _WIN32_WINNT    0x0501 #define _WIN32_WINDOWS  0x0410 #define _WIN32_IE       0x0600  #include <windows.h> #include <winsock2.h>  int main(int argc, char *argv[]) {     WSADATA wsaData = { 0 };     int ret = WSAStartup(MAKEWORD(1, 1), &wsaData);     if (ret != 0) {         return (-1);     }     __try {         SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);         if (sockfd != INVALID_SOCKET) {             __try {                 char *url_host = "www.163.com";                 char *url_path = "/test.exe";                  struct hostent *host = gethostbyname(url_host);                 if (host == NULL) {                     return (-1);                 }                 struct sockaddr_in addr = { 0 };                 addr.sin_family = AF_INET;                 addr.sin_port = htons(80);                 addr.sin_addr.s_addr = *((unsigned long*)*host->h_addr_list);                 ret = connect(sockfd, (SOCKADDR*)&addr, sizeof(addr));                 if (ret == SOCKET_ERROR) {                     return (-1);                 }                  char header[256] = { 0 };                 char format[] = "GET %s HTTP/1.1\r\n"                                 "Host: %s\r\n"                                 "Connection: close\r\n"                                 "\r\n";                 int cch = sprintf(header, format, url_path, url_host);                 ret = send(sockfd, header, cch, 0);                 if (ret == SOCKET_ERROR) {                     return (-1);                 }                 char buf[1024] = { 0 };                 char *status_ok = "HTTP/1.1 200";                 int len = recv(sockfd, buf, sizeof(buf), 0);                 if (strncmp(buf, status_ok, strlen(status_ok)) != 0) {                     return (-1);                 }                 FILE *fp = fopen("test.exe", "wb");                 if (fp != NULL) {                     while (1) {                         len = recv(sockfd, buf, sizeof(buf), 0);                         if (len == 0 || len == SOCKET_ERROR) {                             break;                         }                         fwrite(buf, sizeof(char), len, fp);                     }                     fclose(fp);                      STARTUPINFO si = { 0 };                     PROCESS_INFORMATION pi = { 0 };                     si.cb = sizeof(STARTUPINFO);                     if (!CreateProcessA(NULL, "test.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {                         WaitForSingleObject(pi.hProcess, INFINITE);                         CloseHandle(pi.hProcess);                         CloseHandle(pi.hThread);                     }                 }             }             __finally {                 closesocket(sockfd);             }         }     }     __finally {         WSACleanup();     }     return 0; }

curl是开源的吧。


Question: 同样的程序用VS2013和gcc编译的不一样

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

double a=0;//由于浮点数在存储中无法精确表示，所以它的存储不是你所预期的那样 if(a == b);//实质上是if( a == (double)b)，另外浮点数的存储方式和整型的是不一样的，所以99%应该是不想等的，如果相等，那么说明编译器有其它处理

不同的编译器有不同的实现.... 不过gcc下是应该有输出的

比较的时候会有隐式类型转换，理论上应该是相等的 我用gcc测试没有问题


Question: 各位大神,如何读取主板厂商信息(求助)

搞定了谢谢各位

简单的就是 CMD ---》WMIC---->/?

C:\>devcon /? Device Console Help: devcon [-r] [-m:\\<machine>] <command> [<arg>...] -r if specified will reboot machine after command is complete, if needed. <machine> is name of target machine. <command> is command to perform (see below). <arg>... is one or more arguments if required by command. For help on a specific command, type: devcon help <command> classfilter          Allows modification of class filters. classes              List all device setup classes. disable              Disable devices that match the specific hardware or instance ID. driverfiles          List driver files installed for devices. drivernodes          Lists all the driver nodes of devices. enable               Enable devices that match the specific hardware or instance ID. find                 Find devices that match the specific hardware or instance ID. findall              Find devices including those that are not present. help                 Display this information. hwids                Lists hardware ID's of devices. install              Manually install a device. listclass            List all devices for a setup class. reboot               Reboot local machine. remove               Remove devices that match the specific hardware or instance ID. rescan               Scan for new hardware. resources            Lists hardware resources of devices. restart              Restart devices that match the specific hardware or instance ID. sethwid              Modify Hardware ID's of listed root-enumerated devices. stack                Lists expected driver stack of devices. status               List running status of devices. update               Manually update a device. updateni             Manually update a device (non interactive).

表示不能明白这个devcon和我问的有什么关系

搜"devcon"

不是封装好的接口函数读取,这个不通用,能不能介绍一下主板厂商信息存放在主板的什么地址上面,如何通过in 或者 out读取，谢谢了

WMI中的Win32类监控和管理系统的硬件和特征信息，这些类一般在root/cimv2 WMI 命名空间中。 Win32类主要有一下几类：   ·Computer System Hardware Classes    ·Operating System Classes    ·Installed Applications Classes    ·WMI Service Management Classes    ·Performance Counters Classes    ·Security Descriptor Helper Class 下面列出了常用信息的类： Win32_Processor                        // CPU 处理器 Win32_PhysicalMemory                   // 物理内存 Win32_Keyboard                         // 键盘 Win32_PointingDevice                   // 点输入设备，如鼠标 Win32_DiskDrive                        // 硬盘驱动器 Win32_CDROMDrive                       // 光盘驱动器 Win32_BaseBoard                        // 主板 Win32_BIOS                             // BIOS 芯片 Win32_ParallelPort                     // 并口 Win32_SerialPort                       // 串口 Win32_SoundDevice                      // 多媒体设置 Win32_USBController                    // USB 控制器 Win32_NetworkAdapter                   // 网络适配器 Win32_NetworkAdapterConfiguration      // 网络适配器设置 Win32_Printer                          // 打印机 Win32_PrinterConfiguration             // 打印机设置 Win32_PrintJob                         // 打印机任务 Win32_TCPIPPrinterPort                 // 打印机端口 Win32_POTSModem                        // MODEM Win32_POTSModemToSerialPort            // MODEM 端口 Win32_DesktopMonitor                   // 显示器 Win32_VideoController                  // 显卡细节。 Win32_VideoSettings                    // 显卡支持的显示模式。 Win32_TimeZone                         // 时区 Win32_SystemDriver                     // 驱动程序 Win32_DiskPartition                    // 磁盘分区 Win32_LogicalDisk                      // 逻辑磁盘 Win32_LogicalMemoryConfiguration       // 逻辑内存配置 Win32_PageFile                         // 系统页文件信息 Win32_PageFileSetting                  // 页文件设置 Win32_BootConfiguration                // 系统启动配置 Win32_OperatingSystem                  // 操作系统信息 Win32_StartupCommand                   // 系统自动启动程序 Win32_Service                          // 系统安装的服务 Win32_Group                            // 系统管理组 Win32_GroupUser                        // 系统组帐号 Win32_UserAccount                      // 用户帐号 Win32_Process                          // 系统进程 Win32_Thread                           // 系统线程 Win32_Share                            // 共享 Win32_NetworkClient                    // 已安装的网络客户端 Win32_NetworkProtocol                  // 已安装的网络协议


Question: {求助}java这种des加密方式 可以用c写出的

仅供参考：#pragma comment(lib, "crypt32.lib") #pragma comment(lib, "advapi32.lib") #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include <wincrypt.h> #define KEYLENGTH  0x00800000 void HandleError(char *s); //-------------------------------------------------------------------- //  These additional #define statements are required. #define ENCRYPT_ALGORITHM CALG_RC4 #define ENCRYPT_BLOCK_SIZE 8 //   Declare the function EncryptFile. The function definition //   follows main. BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword); //-------------------------------------------------------------------- //   Begin main. void main(void) {     CHAR szSource[100];     CHAR szDestination[100];     CHAR szPassword[100];     printf("Encrypt a file. \n\n");     printf("Enter the name of the file to be encrypted: ");     scanf("%s",szSource);     printf("Enter the name of the output file: ");     scanf("%s",szDestination);     printf("Enter the password:");     scanf("%s",szPassword);     //--------------------------------------------------------------------     // Call EncryptFile to do the actual encryption.     if(EncryptFile(szSource, szDestination, szPassword)) {         printf("Encryption of the file %s was a success. \n", szSource);         printf("The encrypted data is in file %s.\n",szDestination);     } else {         HandleError("Error encrypting file!");     } } // End of main //-------------------------------------------------------------------- //   Code for the function EncryptFile called by main. static BOOL EncryptFile(     PCHAR szSource,     PCHAR szDestination,     PCHAR szPassword) //-------------------------------------------------------------------- //   Parameters passed are: //     szSource, the name of the input, a plaintext file. //     szDestination, the name of the output, an encrypted file to be //         created. //     szPassword, the password. {     //--------------------------------------------------------------------     //   Declare and initialize local variables.     FILE *hSource;     FILE *hDestination;     HCRYPTPROV hCryptProv;     HCRYPTKEY hKey;     HCRYPTHASH hHash;     PBYTE pbBuffer;     DWORD dwBlockLen;     DWORD dwBufferLen;     DWORD dwCount;     //--------------------------------------------------------------------     // Open source file.     if(hSource = fopen(szSource,"rb")) {         printf("The source plaintext file, %s, is open. \n", szSource);     } else {         HandleError("Error opening source plaintext file!");     }     //--------------------------------------------------------------------     // Open destination file.     if(hDestination = fopen(szDestination,"wb")) {         printf("Destination file %s is open. \n", szDestination);     } else {         HandleError("Error opening destination ciphertext file!");     }     //以下获得一个CSP句柄     if(CryptAcquireContext(                 &hCryptProv,                 NULL,               //NULL表示使用默认密钥容器，默认密钥容器名                 //为用户登陆名                 NULL,                 PROV_RSA_FULL,                 0)) {         printf("A cryptographic provider has been acquired. \n");     } else {         if(CryptAcquireContext(                     &hCryptProv,                     NULL,                     NULL,                     PROV_RSA_FULL,                     CRYPT_NEWKEYSET))//创建密钥容器         {             //创建密钥容器成功，并得到CSP句柄             printf("A new key container has been created.\n");         } else {             HandleError("Could not create a new key container.\n");         }     }     //--------------------------------------------------------------------     // 创建一个会话密钥（session key）     // 会话密钥也叫对称密钥，用于对称加密算法。     // （注: 一个Session是指从调用函数CryptAcquireContext到调用函数     //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程）     //--------------------------------------------------------------------     // Create a hash object.     if(CryptCreateHash(                 hCryptProv,                 CALG_MD5,                 0,                 0,                 &hHash)) {         printf("A hash object has been created. \n");     } else {         HandleError("Error during CryptCreateHash!\n");     }     //--------------------------------------------------------------------     // 用输入的密码产生一个散列     if(CryptHashData(                 hHash,                 (BYTE *)szPassword,                 strlen(szPassword),                 0)) {         printf("The password has been added to the hash. \n");     } else {         HandleError("Error during CryptHashData. \n");     }     //--------------------------------------------------------------------     // 通过散列生成会话密钥     if(CryptDeriveKey(                 hCryptProv,                 ENCRYPT_ALGORITHM,                 hHash,                 KEYLENGTH,                 &hKey)) {         printf("An encryption key is derived from the password hash. \n");     } else {         HandleError("Error during CryptDeriveKey!\n");     }     //--------------------------------------------------------------------     // Destroy the hash object.     CryptDestroyHash(hHash);     hHash = NULL;     //--------------------------------------------------------------------     //  The session key is now ready.     //--------------------------------------------------------------------     // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的，所以被加密的     // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的     // 数据长度。     dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;     //--------------------------------------------------------------------     // Determine the block size. If a block cipher is used,     // it must have room for an extra block.     if(ENCRYPT_BLOCK_SIZE > 1)         dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;     else         dwBufferLen = dwBlockLen;     //--------------------------------------------------------------------     // Allocate memory.     if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {         printf("Memory has been allocated for the buffer. \n");     } else {         HandleError("Out of memory. \n");     }     //--------------------------------------------------------------------     // In a do loop, encrypt the source file and write to the destination file.     do {         //--------------------------------------------------------------------         // Read up to dwBlockLen bytes from the source file.         dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);         if(ferror(hSource)) {             HandleError("Error reading plaintext!\n");         }         //--------------------------------------------------------------------         // 加密数据         if(!CryptEncrypt(                     hKey,           //密钥                     0,              //如果数据同时进行散列和加密，这里传入一个                     //散列对象                     feof(hSource),  //如果是最后一个被加密的块，输入TRUE.如果不是输.                     //入FALSE这里通过判断是否到文件尾来决定是否为                     //最后一块。                     0,              //保留                     pbBuffer,       //输入被加密数据，输出加密后的数据                     &dwCount,       //输入被加密数据实际长度，输出加密后数据长度                     dwBufferLen))   //pbBuffer的大小。         {             HandleError("Error during CryptEncrypt. \n");         }         //--------------------------------------------------------------------         // Write data to the destination file.         fwrite(pbBuffer, 1, dwCount, hDestination);         if(ferror(hDestination)) {             HandleError("Error writing ciphertext.");         }     } while(!feof(hSource));     //--------------------------------------------------------------------     //  End the do loop when the last block of the source file has been     //  read, encrypted, and written to the destination file.     //--------------------------------------------------------------------     // Close files.     if(hSource)         fclose(hSource);     if(hDestination)         fclose(hDestination);     //--------------------------------------------------------------------     // Free memory.     if(pbBuffer)         free(pbBuffer);     //--------------------------------------------------------------------     // Destroy session key.     if(hKey)         CryptDestroyKey(hKey);     //--------------------------------------------------------------------     // Destroy hash object.     if(hHash)         CryptDestroyHash(hHash);     //--------------------------------------------------------------------     // Release provider handle.     if(hCryptProv)         CryptReleaseContext(hCryptProv, 0);     return(TRUE); } // End of Encryptfile //-------------------------------------------------------------------- //  This example uses the function HandleError, a simple error //  handling function, to print an error message to the standard error //  (stderr) file and exit the program. //  For most applications, replace this function with one //  that does more extensive error reporting. void HandleError(char *s) {     fprintf(stderr,"An error occurred in running the program. \n");     fprintf(stderr,"%s\n",s);     fprintf(stderr, "Error number %x.\n", GetLastError());     fprintf(stderr, "Program terminating. \n");     exit(1); } // End of HandleError


Question: 为什么《C程序设计语言》（Brain W.Kernigham著）中的程序很多都在vc++6.0中实现不了？

引用 30楼moyac 的回复:[quote=引用 18 楼 weixin_41760634 的回复:] [quote=引用 15 楼 moyac 的回复:] [quote=引用 11 楼 weixin_41760634 的回复:] 我也想知道为什么实现不了，比如下面这个代码，就是1.6数组中的，我用vc6.0试了，vs2010也试了，能运行，就是实现不了书中说的结果。 #include <stdio.h> /* count digits, white space, others */ main() { int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; ++i) ndigit[i] = 0; while ((c = getchar()) != EOF) if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; printf("digits ="); for (i = 0; i < 10; ++i) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); }  你说的这个例子，我看过，也试过，没有问题的，我也是新手，刚开始学，用的是devc++，比较简单一点[/quote] 我用的vc6.0，他们说Windows下这个比较简单，然后我用vs2010，他们说这个软件在Windows下强大，可我怎么运行后就表示不出书中说的这个结果呢，都折腾好几天了，另外还有一个例子也是这样。求解答，不然，我这个初学者看了书上写的这个程序都执行不到最后结果，都不知道怎么去学习，也不知道这个程序到底要怎么写才是对。[/quote]尴尬 刚开始学习的话，建议你下载一个devc++吧，比较便捷一点哦，先入入手[/quote]嗯嗯，谢谢

引用 18 楼 weixin_41760634 的回复:[quote=引用 15 楼 moyac 的回复:] [quote=引用 11 楼 weixin_41760634 的回复:] 我也想知道为什么实现不了，比如下面这个代码，就是1.6数组中的，我用vc6.0试了，vs2010也试了，能运行，就是实现不了书中说的结果。 #include <stdio.h> /* count digits, white space, others */ main() { int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; ++i) ndigit[i] = 0; while ((c = getchar()) != EOF) if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; printf("digits ="); for (i = 0; i < 10; ++i) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); }  你说的这个例子，我看过，也试过，没有问题的，我也是新手，刚开始学，用的是devc++，比较简单一点[/quote] 我用的vc6.0，他们说Windows下这个比较简单，然后我用vs2010，他们说这个软件在Windows下强大，可我怎么运行后就表示不出书中说的这个结果呢，都折腾好几天了，另外还有一个例子也是这样。求解答，不然，我这个初学者看了书上写的这个程序都执行不到最后结果，都不知道怎么去学习，也不知道这个程序到底要怎么写才是对。[/quote]尴尬 刚开始学习的话，建议你下载一个devc++吧，比较便捷一点哦，先入入手

引用 22楼donjin9 的回复:必须ctrl+z回车明白了，谢谢

引用 20楼幻夢之葉 的回复:[quote=引用 19 楼 weixin_41760634 的回复:] 我试过了，也不行 这是你的操作问题吧？ EOF是判断文件结束的，Windows下CTRL+Z，再Enter健是输入结束符[/quote]明白了，谢谢

引用 14 楼 jianwen0529 的回复: while ((c = getchar()) != EOF) { if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; } //加上大括号试试 printf("digits ="); 我试过了，也不行

引用 15 楼 moyac 的回复:[quote=引用 11 楼 weixin_41760634 的回复:] 我也想知道为什么实现不了，比如下面这个代码，就是1.6数组中的，我用vc6.0试了，vs2010也试了，能运行，就是实现不了书中说的结果。 #include <stdio.h> /* count digits, white space, others */ main() { int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; ++i) ndigit[i] = 0; while ((c = getchar()) != EOF) if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; printf("digits ="); for (i = 0; i < 10; ++i) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); }  你说的这个例子，我看过，也试过，没有问题的，我也是新手，刚开始学，用的是devc++，比较简单一点[/quote] 我用的vc6.0，他们说Windows下这个比较简单，然后我用vs2010，他们说这个软件在Windows下强大，可我怎么运行后就表示不出书中说的这个结果呢，都折腾好几天了，另外还有一个例子也是这样。求解答，不然，我这个初学者看了书上写的这个程序都执行不到最后结果，都不知道怎么去学习，也不知道这个程序到底要怎么写才是对。

引用 19 楼 weixin_41760634 的回复:我试过了，也不行 这是你的操作问题吧？ EOF是判断文件结束的，Windows下CTRL+Z，再Enter健是输入结束符

引用 26楼幻夢之葉 的回复:引用 23 楼 weixin_41760634 的回复:[quote=引用 22楼donjin9 的回复:]必须ctrl+z回车ctrl+z会再enter 就结束了 while循环的结束条件就是那个[/quote]这个程序是用来统计输入字符中数字，空白符，其他字符出现的次数的。要是一运行，就按你说的操作，那这个程序写来有何用？

引用 23 楼 weixin_41760634 的回复:引用 22楼donjin9 的回复:必须ctrl+z回车ctrl+z会再enter 就结束了 while循环的结束条件就是那个

引用 17楼流浪小狗 的回复:getchar的行为和回车换行的处理有关系吧！ windows下，\n\r是回车换行，而老外的程序估计基于unix或者linux，是\n 这样，在控制台格式化输入时，因为多了\r，结果逻辑不对了。  记得ACM比赛时，为了不出现这种问题，都是先 fgets一行，再 sscanf来做保险。或者你教教我要怎么才能在vs下运行，这样以后我碰到书中的例子都执行不了结果的时候就不用在范愁了，谢谢

引用 17楼流浪小狗 的回复:getchar的行为和回车换行的处理有关系吧！ windows下，\n\r是回车换行，而老外的程序估计基于unix或者linux，是\n 这样，在控制台格式化输入时，因为多了\r，结果逻辑不对了。  记得ACM比赛时，为了不出现这种问题，都是先 fgets一行，再 sscanf来做保险。那你的意思是这个程序只能在Unix 或者linx 系统下执行了？

必须ctrl+z回车

引用 20 楼 jianwen0529 的回复:[quote=引用 19 楼 weixin_41760634 的回复:] 我试过了，也不行 这是你的操作问题吧？ EOF是判断文件结束的，Windows下CTRL+Z，再Enter健是输入结束符[/quote] 我没有按ctrl+z啊，我是输入完成后直接按得enter

引用 10 楼 lm_whales 的回复:引用 5 楼 sholber 的回复:在中国，控制等级考试的人，以及大学教授，他们和微软公司的笔儿盖子在1995年达成协议，只有他们能用VC编译C程序，别人是不可以的。早该摆脱VC6了

引用 11 楼 weixin_41760634 的回复:我也想知道为什么实现不了，比如下面这个代码，就是1.6数组中的，我用vc6.0试了，vs2010也试了，能运行，就是实现不了书中说的结果。 #include <stdio.h> /* count digits, white space, others */ main() { int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; ++i) ndigit[i] = 0; while ((c = getchar()) != EOF) if (c >= '0' && c <= '9') ++ndigit[c-'0']; else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; printf("digits ="); for (i = 0; i < 10; ++i) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); }  你说的这个例子，我看过，也试过，没有问题的，我也是新手，刚开始学，用的是devc++，比较简单一点

引用 12 楼 jianwen0529 的回复:结果不对那是逻辑问题，不是编译问题！ 为什么不对，那就需要你继续学习掌握程序分析的能力了！ 或者你该换一本教程？


Question: 二级指针的问题求帮助

(*mot)[i].age mot指向p，而不是数组

i 的地址没错，为什么 j=i+1就错了 在排序时直接档掉了，，j内存指向0xcccccccc


Question: 求解为什么同样的表达式在第一个if里可以，同组的else if里就会报错呢？

基础语法、代码逻辑……

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

引用 2 楼 paschen 的回复:运算符有优先级，请用括号来实现想要的顺序，你要这样写：else if((c != ' ')  &&   ( nb=((nb/8)>0))   ) 优先级的问题啊，是没考虑

你把nb / 8 > 0赋值给c != '' && nb是几个意思...？

看不太你想干嘛


Question: progress returned -1073741571<0xC00000FD>是什么意思。求大神帮助

引用 1 楼 搁浅的贝的回复:明显的程序递归是以m的值判断的，但m的值就没变化过，照这样会无限递归，栈溢出什么的都有可能了。  你可以考虑把 m 声明为全局变量 谢谢大神!程序能成功运行了


Question: 请问C语言char s[20]="hello";和char s[]="hello"，这两条语句谁对谁错？

都对，第一个分配好了数组内存大小，第二个自动分配

建议lz自己试下就知道了……

都对

不要在意第二条没有分号...

前一个，数组长度是20， 后一个数组长度是6。

都对。只是数组长度不同。


Question: sendmsg函数报90-Message too long错

引用 3 楼 ewolfe163 的回复:32位Redhat上可正常执行，到64位就失败了，是系统安装问题？还是程序问题？ 放在64位机上的32位虚拟机中运行。

单步到sendmsg内部一探究竟。

将长消息分为多条短消息发送。


Question: C语言regex库正则匹配问题

引用 5 楼 user-2 的回复:regcomp 应该加 REG_EXTENDED 标志,  \\d 应该用 [[:digit:]]+ 或者类似的.. 还是用 DFA 的引擎吧,  这些NFA 的都太难用了... DFA？ NFA？ 什么意思

还有就是用boost::regex能匹配正确，而regex.h和pcre.h都匹配不出且结果一样

就是使用./regex abc\\d+ abc123  也还是没匹配出来

linux的bash参考： Learning.the.bash.Shell.3rd.Edition.chm 高级Bash脚本编程指南--中文版.pdf

命令行参数中有很多字符需要转义。  命令行解释器概述 命令行解释器是一个单独的软件程序，它可以在用户和操作系统之间提供直接的通讯。非图形命令行解释器用户界面提供运行基于字符的应用程序和实用程序的环境。通过使用类似于 MS-DOS 命令解释程序 Command.com 的单独字符，命令行解释器执行程序并在屏幕上显示其输出。Windows 服务器操作系统命令行解释器使用命令解释程序 Cmd.exe（该程序加载应用程序并指导应用程序之间的信息流动）将用户输入转换为操作系统可理解的形式。 可以使用命令行解释器创建和编辑可自动执行常规任务的批处理文件（也称作脚本）。例如，可以使用脚本自动管理用户帐户或夜间备份。还可以使用 Windows 脚本宿主 CScript 的命令行版本在命令行解释器中运行更高级的脚本。详细信息，请参阅运行 Windows 脚本宿主。通过使用批处理文件来执行操作，可比使用用户界面更有效率。批处理文件接受命令行上可用的所有命令。有关批处理文件和脚本的详细信息，请参阅使用批处理文件。 您可以自定义命令提示符窗口以易于查看并增强对程序运行方式的控制。有关自定义命令提示符窗口的详细信息，请参阅配置命令提示符。  使用命令语法 语法按命令及所带参数必须遵循的键入顺序出现。下面的 xcopy 命令示例显示了各种语法文本格式：  xcopy Source [Destination] [/w] [/p] [/c] [/v] [/q] [/f] [/l] [/g] [/d[:MM-DD-YYYY]] [/u] [/i] [/s [/e]] [/t] [/k] [/r] [/h] [{/a | /m}] [/n] [/o] [/x] [/exclude:File1[+[File2]][+[File3]] [{/y | /-y}] [/z]  下表说明如何解释不同的文本格式。  格式化图例 格式                                             含义 斜体                                             用户必须提供的信息 粗体                                             用户必须准确键入的要显示的元素 省略号(...)                                      在命令行中可多次重复的参数 中括号([])                                       可选项 大括号({})；选项用竖线(|)分隔。例如：{even|odd}  用户必须从选项集合中选择一个 Courier字体                                      代码或程序输出  使用多个命令和条件处理符号 使用条件处理符号可以在单个命令行或脚本中运行多个命令。通过条件处理符号运行多个命令时，条件处理符号右边的命令根据条件处理符号左边命令的执行结果来发挥作用。例如，只有在前一个命令失败的情况下才可能需要运行一个新命令。或者，只有在前一个命令成功时才可能需要运行一个新命令。 可以使用下表列出的特殊字符来传递多个命令。  字符       语法                            定义 & [...]    Command1 & Command2             用来分隔一个命令行中的多个命令。Cmd.exe 运行第一个命令，然后运行第二个命令。 && [...]   Command1 && Command2            只有在符号 && 前面的命令成功时，才运行该符号后面的命令。Cmd.exe 运行第一个命令，然后只有在第一个命令运行成功时才运行第二个命令。 || [...]   Command1 || Command2            只有在符号 || 前面的命令失败时，才运行符号 || 后面的命令。Cmd.exe 运行第一个命令，然后只有在第一个命令未能运行成功（接收到大于零的错误代码）时才运行第二个命令。 ( ) [...]  (Command1 & Command2)           用来分组或嵌套多个命令。 ;或者,     Command1 Parameter1;Parameter2  用来分隔命令参数。  注意 “与”符号 (&)、管道符号 (|) 以及括号 () 是特殊字符，将它们作为参数传递时，必须在其前面加上转义字符 (^) 或引号。 如果某个命令成功完成操作，该命令就返回零 (0) 退出代码或不返回任何退出代码。有关退出代码的详细信息，请参阅 Microsoft Windows 部署和资源工具包。  嵌套命令行解释器 通过在命令提示符下打开新的 Cmd.exe 实例，可以在 Cmd.exe 内嵌套命令行解释器。默认情况下，Cmd.exe 的每个实例继承其父 Cmd.exe 应用程序的环境。通过嵌套 Cmd.exe 的实例，可以更改局部环境，而不会影响 Cmd.exe 的父应用程序。这使您能够保留 Cmd.exe 的原始环境，并在终止嵌套的命令行解释器之后返回到原始环境。但是在嵌套的命令行解释器中所做的更改将不会被保存。 要嵌套命令行解释器，请在命令提示符下键入：  cmd  出现类似于下面内容的消息：  Microsoft (R) Windows Server 2003 Standard Edition (TM) (C) 版权所有 1985-2002 Microsoft Corp. 要关闭嵌套的命令行解释器，请键入 exit。  使用 setlocal 和 endlocal 命令，可以在 Cmd.exe 的实例中（或在脚本中）进一步将更改局部化。Setlocal 创建局部作用范围，而 endlocal 终止局部作用范围。在 setlocal 和 endlocal 作用范围内所做的更改将会被放弃，从而保持原始环境不变。这两个命令的嵌套最高可达到 32 级。有关 setlocal 和 endlocal 命令的详细信息，请参阅 Setlocal 和 Endlocal。  将环境变量与 Cmd.exe 一起使用 Cmd.exe 命令行解释器环境由确定命令行解释器和操作系统行为的变量进行定义。可以使用两种类型的环境变量（系统和局部）来定义命令行解释器环境或整个操作系统环境的行为。系统环境变量定义全局操作系统环境的行为。局部环境变量定义 Cmd.exe 当前实例环境的行为。 系统环境变量预置于操作系统之中，并可用于所有 Windows 服务器操作系统进程。只有具有管理凭据的用户才可以更改系统变量。这些变量最常用于登录脚本。 局部环境变量只有在创建变量时针对的目标用户登录到计算机时才有效。HKEY_CURRENT_USER 配置单元中设置的局部变量只对当前用户有效，但它们可定义全局操作系统环境的行为。  下表按优先顺序的降序描述变量的各种类型： 1.内置系统变量 2.在 HKEY_LOCAL_MACHINE 配置单元中找到的系统变量 3.在 HKEY_CURRENT_USER 配置单元中找到的局部变量 4.在 Autoexec.bat 文件中设置的所有环境变量和路径 5.在登录脚本（如果有的话）中设置的所有环境变量 6.在脚本或批处理文件中交互使用的变量  在命令行解释器中，Cmd.exe 的每个实例都继承其父应用程序的环境。因此，可以在不影响父应用程序环境的情况下更改新的 Cmd.exe 环境中的变量。 下表列出 Windows server operating system 的系统和本地环境变量。  变量                     类型       描述 %ALLUSERSPROFILE%        本地       返回“所有用户”配置文件的位置。 %APPDATA%                本地       返回默认情况下应用程序存储数据的位置。 %CD%                     本地       返回当前目录字符串。 %CMDCMDLINE%             本地       返回用来启动当前的Cmd.exe的准确命令行。 %CMDEXTVERSION%          系统       返回当前的“命令处理程序扩展”的版本号。 %COMPUTERNAME%           系统       返回计算机的名称。 %COMSPEC%                系统       返回命令行解释器可执行程序的准确路径。 %DATE%                   系统       返回当前日期。使用与date/t命令相同的格式。由Cmd.exe生成。有关date命令的详细信息，请参阅Date。 %ERRORLEVEL%             系统       返回上一条命令的错误代码。通常用非零值表示错误。 %HOMEDRIVE%              系统       返回连接到用户主目录的本地工作站驱动器号。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 %HOMEPATH%               系统       返回用户主目录的完整路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 %HOMESHARE%              系统       返回用户的共享主目录的网络路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 %LOGONSERVER%            本地       返回验证当前登录会话的域控制器的名称。 %NUMBER_OF_PROCESSORS%   系统       指定安装在计算机上的处理器的数目。 %OS%                     系统       返回操作系统名称。Windows2000显示其操作系统为Windows_NT。 %PATH%                   系统       指定可执行文件的搜索路径。 %PATHEXT%                系统       返回操作系统认为可执行的文件扩展名的列表。 %PROCESSOR_ARCHITECTURE% 系统       返回处理器的芯片体系结构。值：x86或IA64（基于Itanium）。 %PROCESSOR_IDENTFIER%    系统       返回处理器说明。 %PROCESSOR_LEVEL%        系统       返回计算机上安装的处理器的型号。 %PROCESSOR_REVISION%     系统       返回处理器的版本号。 %PROMPT%                 本地       返回当前解释程序的命令提示符设置。由Cmd.exe生成。 %RANDOM%                 系统       返回0到32767之间的任意十进制数字。由Cmd.exe生成。 %SYSTEMDRIVE%            系统       返回包含Windowsserveroperatingsystem根目录（即系统根目录）的驱动器。 %SYSTEMROOT%             系统       返回Windowsserveroperatingsystem根目录的位置。 %TEMP%和%TMP%            系统和用户 返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP，而其他应用程序则需要 TMP。 %TIME%                   系统       返回当前时间。使用与time/t命令相同的格式。由Cmd.exe生成。有关time命令的详细信息，请参阅Time。 %USERDOMAIN%             本地       返回包含用户帐户的域的名称。 %USERNAME%               本地       返回当前登录的用户的名称。 %USERPROFILE%            本地       返回当前用户的配置文件的位置。 %WINDIR%                 系统       返回操作系统目录的位置。  设置环境变量 使用 set 命令创建、更改、删除或显示环境变量。set 命令只更改当前解释器环境中的变量。  要查看变量，请在命令提示符下键入：  set VariableName  要添加变量，请在命令提示符下键入：  set variablename=Value  要删除变量，请在命令提示符下键入：  set VariableName=  可以将大多数字符用作变量值，其中包括空格。如果使用特殊字符 <、>、|、& 或 ^，则必须在它们前面加上转义字符 (^) 或引号。如果使用引号，则必须将引号作为值的组成部分，因为等号后面的任何内容都会被视为值。请考虑下列示例：  要创建变量值 new&name，请键入： set varname=new^&name  要创建变量值 "new&name"，请键入： set varname="new&name"  如果在命令提示符下键入 set varname=new&name，就会出现与下面内容类似的错误消息： “'name' 不是内部或外部文件，也不是可运行的程序或批处理文件。” 变量名不区分大小写。但是，set 显示的变量与您键入的完全相同。可以在变量名中结合使用大写字母和小写字母，这样可以使代码更具有可读性（例如，UserName）。  注意  单个环境变量的最大大小为 8192 字节。 所有环境变量的大小总和（包括变量名和等号）最大为 65,536 KB。 替换环境变量值 要在命令行或脚本中启用变量值替换，请将变量名包括在百分号之中（即，%VariableName%）。使用百分号可以确保 Cmd.exe 引用变量值，而不是进行文字比较。为变量名定义变量值之后，请将变量名包括在百分号之中。Cmd.exe 搜索该变量名的所有实例，并用定义的变量值进行替换。例如，如果创建包含不同值（例如，用户名）的脚本，并且想要用这些值为每个用户定义 USERNAME 环境变量，可以使用包括在百分号之中的 USERNAME 来编写代码。运行此脚本时，Cmd.exe 将用变量值替换 %USERNAME%，这样就消除了为每个用户手动执行此任务的必要。变量替换是不可递归的。Cmd.exe 检查变量一次。有关变量替换的详细信息，请参阅 For 和 Call。


Question: 大神啊，这几句到底啥意思？

看起来象是LCD操作,这类都是发个指令过去,然后从数据线上得到数据, 看手册上应该有的

MAIN_LCD_RW_DATA_ADDRESS 是一个地址，而这个地址可能是一个 IO 操作。 这个地址读取的数是由外部改变的。

这个值在地址 0x60100000这个位置，你的代码里看不出来，不过你调试的时候，是可以看到的


Question: 一道c语言题目所出现的一个问题

哦哦，你的结构体申请的内存好像少了，只能存一个学生的记录。

引用 1 楼 github_27756899 的回复:arr[m].name=strname;  改为： strcpy(arr[m].name,strname); ---------------------------------------------------------------------- 谢了啊。不过还得在前面加句 arr[m].name=(char*)malloc(sizeof(char)); 不然程序会崩


Question: a =1  b=32  输出 a<< b 为什么

引用 12 楼 lm_whales 的回复:按照数学上来说， 右移，有两种，逻辑右移和算术右移不同，一个补上符号位，一个补上0 左移只有一种，逻辑左移和算术左移相同 不论如何，右移超过数据位数，只有两种结果 ～0，和0 左移只有一种结果 0 但是某一年，Intel CPU 设计的某个工程师， 脑袋抽筋了，设计成32Bits只有5Bits有效位  这样 相当于 第二个操作数对 32 取余数，然后再移位  然后，依照惯例，整型+-*/移位等算术运算，根据CPU 内部算术运算来实现 一个移位表达式，被翻译成对应于 一条移位指令 这样后来就出现了，移位位数，不得超过寄存器位数的奇怪现象。  其实最奇葩的是某些版本的VC编译器 预编译指令中的移位，按照 结果为 0 算  代码中的移位，直接编译成对应的移位指令， 结果就是位数参数被阉割了

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

其实是CPU的问题，Intel CPU 32Bits  只能移位 0～32Bits因为只有移位的位数操作数，只有个5有效位

1 << 32 被编译器检测出参数异常了，直接替换成了 0，根本就没有生成移位的指令

左移，右边是补0的，移动32位之后，肯定就全部为0了 如果是有符号的数的话，右移会填充符号位的数 最后变成1111111111111111111111

循环移位是什么鬼

但是我做的是选择题 A 0 0  B  0 1  C 1 0   D  1 1 怎么选呢 而且我在编译器上跑了即便都是 1 0 怎么会是行为不确定呢

谢谢您  那1<< 32为什么是算术左移 而 a<< b却是循环左移呢。。

我的意思是 a=1  b=32 进行 a<<b操作 结果是1  我以为是像1 << 32这样为0 为什么是1 而不是0


Question: C语言或者C++求助，需要能自动读入txt，并查找指点的内容进行修改

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

1.打开的对话框中需要输入路径吗？ 2.指定位置是指什么位置？是txt的位置吗？添加编码做什么？是用来加密吗？


Question: 请问C语言的结构体到底方便在哪呢？好像它就是把不同的类型集合在一起而已？求高手指教

当做函数参数时，只需要一个指针即可，便于保持接口稳定。


Question: 关于字符串输出的问题

第一次 i=(*(a+x)-'0')+(*(b+y)-'0')+n;时, *(a+x)和*(b+y)都是0('\0'),  i是-负数

void myprint(char *a,int x,char *b,int y) { char name[1024];//定义个字符串接收结果   int n=0,i,m;  m=(x>y?x:y)+1;//m的大小是两个字符串长度中最长的那一个 +1 //目的是为了防止计算时有进位操作   name[m+1]='\0'; //m+1的位置加上字符串结束符   while(m>=0) { i=(*(a+x)-'0')+(*(b+y)-'0')+n;//两个字符转成数字相加+n（进位时的数值）   name[m]=i%10+'0';//把数值的尾数转成相应的字符存入字符串   if(i>10)//判断结果确定是否有进位  n=1; else n=0;  if(x==0)//循环到这里表明X=0 的下标以计算，将它的结果置0，以免影响计算结果  { *(a+x)='0'; }  if(y==0)//这时也是上面相同的考虑，主要是针对两个字符串，位数不同而设定  { *(b+y)='0'; }  m--; x--; y--;  if(x<0)x=0;//为防止出现name[ -1 ]越界情况强行置 0；  if(y<0)y=0;	 } puts(name); }  个认认为主要问题会出现在这个函数，求高手指点


Question: 执行程序的时候，如何看变量/数组等在内存里的地址和内容？

可以使用vc设置断点然后再调试，使用调试的内存窗口查看内存

"hello","kitty" 用二进制编辑器看,一般用UE看， 其实VS也可以看二进制文件  emp用调试器看，也可以自己输出查看

仅供参考：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);     } }

我电脑上安装的MSDN2008中文版。

引用 7 楼 zhangxiangDavaid 的回复:vs下F9，在该行下断点…… 谢谢，能否具体知道一下，如何下断点？下了断点程序就会在这个位置暂停？然后怎么看？

引用 14 楼 zhao4zhong1 的回复:[quote=引用 13 楼 learnc2015 的回复:] [quote=引用 12 楼 zhao4zhong1 的回复:] 请楼主通读MSDN中文版中有关如何使用VS IDE的相关章节。 百度了半天，也没找到MSDN中文版[/quote] [/quote] 这在哪看到的啊

引用 13 楼 learnc2015 的回复:[quote=引用 12 楼 zhao4zhong1 的回复:] 请楼主通读MSDN中文版中有关如何使用VS IDE的相关章节。 百度了半天，也没找到MSDN中文版[/quote]

引用 12 楼 zhao4zhong1 的回复:请楼主通读MSDN中文版中有关如何使用VS IDE的相关章节。 百度了半天，也没找到MSDN中文版

请楼主通读MSDN中文版中有关如何使用VS IDE的相关章节。

引用 10 楼 paschen 的回复:你要让程序停下来才可以看，比如设置一个断点，当程序运行到这个点的时候会停下来，IDE上会有相应窗口显示变量的各种信息、调用堆栈等 谢谢，如何设置断点?

vs下F9，在该行下断点……

引用 5 楼 learnc2015 的回复:[quote=引用 4 楼 bluewanderer 的回复:] ctrl + alt + m, 1 能否详细讲讲，我很菜的 程序首先要在那一步暂停吧？如何做到？[/quote]  在你想要看内容的位置设断点或者ctrl + f10执行到那一行，然后debug>window>memory随便开一个内存窗口，然后输入你想看的地址的表达式  ctrl+alt+m, 1/2/3/4是快捷方式。alt+6等效于ctrl+alt+m,1，不过我总感觉以前没见过，不知道是不是哪个版本的时候新加的。

引用 4 楼 bluewanderer 的回复:ctrl + alt + m, 1 能否详细讲讲，我很菜的 程序首先要在那一步暂停吧？如何做到？

ctrl + alt + m, 1

引用 2 楼 learnc2015 的回复:[quote=引用 1 楼 q3733353520 的回复:]  printf("%c\n",*emp[0]);//这个就是数组第一个元素（指针）所存地址的内容 printf("%p\n", emp[0]);//这个是数组第一个元素的内容（即存放上面那条语句内容的地址）  这个我知道，我要直接看内存，WINHEX? 我用的VS2010[/quote] VS没用过，按理说debug模式肯定可以

引用 1 楼 q3733353520 的回复: printf("%c\n",*emp[0]);//这个就是数组第一个元素（指针）所存地址的内容 printf("%p\n", emp[0]);//这个是数组第一个元素的内容（即存放上面那条语句内容的地址）  这个我知道，我要直接看内存，WINHEX? 我用的VS2010


Question: 请教一个指针的问题，谢谢char *emp[2]={"hello","kitty"}; 	printf("%c\n",*emp[0]);

引用 5 楼 q3733353520 的回复:[quote=引用 4 楼 learnc2015 的回复:] [quote=引用 3 楼 q3733353520 的回复:]  []优先级高于*,即先算emp[0]，代表指针数组的第一个元素（一个指针），然后*取指针内容，因为是char所以取一个字符  为什么printf("%s",emp[0]) 能打印出整个字符串？，不是说emp[0]只是保存了第一个字符的地址吗？ emp[0]能在任何地方表示整个字符串？[/quote]  它是第一个字符的地址，但是%s表示从这个地址是打印，一直到遇到'\0'[/quote] 它是第一个字符的地址，但是%s表示从这个地址开始打印，一直到遇到'\0'

引用 4 楼 learnc2015 的回复:[quote=引用 3 楼 q3733353520 的回复:]  []优先级高于*,即先算emp[0]，代表指针数组的第一个元素（一个指针），然后*取指针内容，因为是char所以取一个字符  为什么printf("%s",emp[0]) 能打印出整个字符串？，不是说emp[0]只是保存了第一个字符的地址吗？ emp[0]能在任何地方表示整个字符串？[/quote]  它是第一个字符的地址，但是%s表示从这个地址是打印，一直到遇到'\0'

引用 3 楼 q3733353520 的回复: []优先级高于*,即先算emp[0]，代表指针数组的第一个元素（一个指针），然后*取指针内容，因为是char所以取一个字符  为什么printf("%s",emp[0]) 能打印出整个字符串？，不是说emp[0]只是保存了第一个字符的地址吗？ emp[0]能在任何地方表示整个字符串？

引用 楼主 learnc2015 的回复:int main(void) { 	char *emp[2]={"hello","kitty"}; 	printf("%c\n",*emp[0]); 	return 0; }  这里该怎么理解*emp[0] 是先取得emp[0]的地址，然后用*取出这个地址的值？ 还是先*emp取得当前地址的值，然后再取得这个地址的值的第一个字符？  []运算符的优先级比*高，即*emp[0] 等价于*(emp[0] ) emp是一个数组，元素为一个char型指针 char *emp[2]={"hello","kitty"};  第一元素为"hello"的首地址，第二个元素为"kitty"的首地址 所以emp[0]为"hello"的首地址，*emp[0] 为"hello"字符串的第一个字符'h'

首先指针emp是指向的一个数组，*emp取得指针的内容，内容是数组，*emp[0]是进行数组的访问。


Question: c语言新手，一个关于抽签的问题，求帮助

仅供参考：#include <stdio.h> #include <stdlib.h> #include <time.h> int d[6]; int i,n,a,b,t; int c,j; void main() {     srand(time(NULL));     printf("shuffle 0..n-1 demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=0;i<n;i++) d[i]=i;/* 填写0～n-1 */             for (i=n;i>0;i--) {/* 打乱0～n-1 */                 a=i-1;b=rand()%i;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=0;i<n;i++) printf("%d",d[i]);             printf("\n");         }     }     printf("shuffle 1..n demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=1;i<=n;i++) d[i]=i;/* 填写1～n */             for (i=n;i>1;i--) {/* 打乱1～n */                 a=i;b=rand()%i+1;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=1;i<=n;i++) printf("%d",d[i]);             printf("\n");         }     } }

你的程序逻辑太乱了，没法改 另外对于m中取n个数，这种组合有多少种，才是b数组的大小  思路参考 http://blog.chinaunix.net/uid-20940095-id-3118454.html

引用 2 楼 q3733353520 的回复:  function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum);  谢谢大神！改正后没了语法错误。 可运行时还是出现了问题。是程序结构本身的错误吗？

引用 5 楼 csdn_mr_l 的回复:[quote=引用 2 楼 linux_liyi的回复:]  function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum);    function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum); [/quote]   function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum); [/quote] 为什么?这两个语句难道不是一个意思吗[/quote] 回去多看看书

引用 2 楼 linux_liyi的回复:  function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum);    function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum); [/quote]   function(random_numbers[],N,m,b[],sum); // 改为function(random_numbers,N,m,b,sum);  function(a[],n,m,b[],sum);//改为 function(a,n,m,b,sum); [/quote] 为什么?这两个语句难道不是一个意思吗

#include<stdio.h> #include<stdlib.h> #include<time.h> #define N 3000 //function功能为：从3000个随机数中随机抽出n个数，求出n个数之和的所有可能。 void function(int a[],int n,int m ,int b[],int sum); //a[]  随机数组 //n    随机数个数 //m    抽签问题中的数m //b[]  用于存放n个数之和的所有可能 //sum  对k个数进行累加 void function(int a[],int n,int m ,int b[],int sum) {         int i;         int j;         for(i=0,j=0;i<=n;i++,j++) 	{ 	    sum=sum+a[i]; 	    if(m>0)                function(a[],n,m,b[],sum);             else             b[j]=sum;         } }  main() {     int random_numbers[N];     int m,i;     int sum=0;     int b[1000];     int k;     int given_number;     srand((unsigned)time(NULL));     for(i = 0; i < N; i++) 	{ 		random_numbers[i] = rand()%RAND_MAX; 	}     scanf("%d",&m);     function(random_numbers[],N,m,b[],sum);     scanf("%d",&given_number);     for(k=0;k<1000;k++)         { 	    if(b[k]==given_number)                 printf("ok");                 break; 	} }


Question: 求教Winpcap编程的一些问题

引用 1 楼 user-1的回复:你确定你没提取错吗？ UDP 的长度不可能那么大的 果然提取错了，提取两个字节以上的要把网络字节序转换成主机字节序。这样两个问题都解决了

你确定你没提取错吗？ UDP 的长度不可能那么大的


Question: C语言求助！！！求大神们帮忙看看。

引用 3 楼 kingjkn 的回复:[quote=引用 1 楼 NexTor 的回复:] m1，m2没有初始化  爱死你了，能再问个问题么？ 为什么第一个函数需要 第二个函数不需要啊？ [/quote] 第一个函数中，两个if后的条件可能为假，这时他们就不会被赋值，然后的比较就没有意义了。第二个中就不存在这种情况

引用 1 楼 NexTor 的回复:m1，m2没有初始化  爱死你了，能再问个问题么？ 为什么第一个函数需要 第二个函数不需要啊？

亲，爱死你了，还是CSDN专业。 能再问你个问题么？ 为什么没初始化不行啊。

m1，m2没有初始化

引用 4 楼 wang0635 的回复:[quote=引用 3 楼 kingjkn 的回复:] [quote=引用 1 楼 NexTor 的回复:] m1，m2没有初始化  爱死你了，能再问个问题么？ 为什么第一个函数需要 第二个函数不需要啊？ [/quote] 第一个函数中，两个if后的条件可能为假，这时他们就不会被赋值，然后的比较就没有意义了。第二个中就不存在这种情况[/quote] 第二个中要走到if（m1 == m2）的判断，m1和m2都会被赋值了，不会存在没有被赋值的情况。

Not recognizing known sRGB profile that has been edited 和楼主贴出的代码好像没什么关系吧


Question: 求助C!!!

void createlist(linklist &L,int n)//改为void createlist(linklist L,int n)

你使用了引用，而这是.c文件，把文件改为.cpp

直接用g++编译好了


Question: 在顺序表中删除特定的值，请各位大神帮忙改改代码

但输出时还是会停止工作啊

void delete_x 里面的if语句里面加return，或着使用if-else语句

你的 list 是一个指针。sqlist是一个结构体 这两个之间我看了下，没有直接关系，然后你查找指定的数据是对list操作。然而简单的说 数据是储存在sqlist里面。你的操作出了些问题。 int main(int argc,char* argv[]) { int size=5,x,q;     Seqlist sqlist; Seqlist *list;     printf("初始化顺序表:\n");     sqlist=create(5); list = * sqlist/*此处增加，并没有实际测试，个人见解，见谅。*/     printf("顺序表如下:\n");     printList(sqlist);     printf("输入要删除的值:\n"); scanf("%d",&x);     q=locate(list,x); if(q!=-1) { delete_x(list,q); printList(sqlist); } else printf("删除失败!"); return 0; }

void delete_x(Seqlist *sqlist,int p) {     if(p<0||p>=sqlist->length)     {         printf("Not exist!\n");         return;     }     memmove(sqlist->data+p,             sqlist->data+p+1,             (sqlist->length-p-1)*sizeof(*sqlist->data));     --sqlist->length; }

指出一个问题  在创建空表的时候，是不是应该用指针函数，然后返回指针？

改了之后提示错误

q=locate(list,x);，list指针都没有指向链表，改成 q=locate(&sqlist,x);delete_x(list,q)改成delete_x(&sqlist,q);


Question: 关于const的一个问题

一个const 用常量表达式初始化，  会被直接当作常量表达式使用 假设有  const int i=0; 大部分代码中，会使用 的 0 这个值 某些代码，可能会存取取 i这个（常）变量，所在内存中的值。 这样的程序。 理所当然的，不能得到你所需要的确切结果。

不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！

常量折叠

修改常量内容是undefined behavior啊。你定义一个const int i = 0; 后面代码用到i很可能被编译器直接当0用，而根本不管I的值是不是被用非常手段改过。

测试了一下，外部的那个是在.rodata区，内部的那个在栈内。 内部的那个只能通过语法保证const，实际上仍然可以去修改它。 但是外部的那个，则通过mprotect改变了内存属性，修改它会触发seg-fault。

引用 2 楼 paschen 的回复:这是通过二级指针改变变常量的值，至于为什么全局常量会出错应该是全局常量是分配在常量区，而局部常量也是分配在栈上，只不过程序在编译时会检查你是否修改了这个常量 我觉得这位说的对，不过建议LZ反汇编看一下那个变量到底是在常量区（.rodata）还是在栈上。另外鄙视一下下面的赵老师。

引用 楼主 iaction 的回复: const int a = 5;//全局变量，可能放在常量区，属于不可写（只读）数据，用其它手段改写，就会出错。                      //这是CPU保护模式的一种能力。                      //如果没有通过地址读写的代码，这个常量可能不占用内存，---被优化掉了 void main() { 	int *ptr; 	ptr = (int*)&a;  	*ptr = 6; 	printf("%d\n",a); } 执行至*ptr=6时，写入内存冲突；   void main() { 	const int a = 5; //没有通过地址等间接手段引用，也可以被优化掉，                                //否则属于自动变量，                                 //在栈中,没有保护措施可用,改写也没问题，                                //虽然通过 a这个名字直接修改是不可能的 	int *ptr; 	ptr = (int*)&a; 	*ptr = 6; 	printf("a=%d\n",a); }  输出：a=6;   问题：为什么第一个不可以改变a的值，第二个可以呢？  const 宣布的是对应 标识符，及相关对象的不变特性 对于C++而言，通过常量表达式定义的 const ，结果可能是个常量表达式。 也可能同时是常量表达式和变量。 C没有真正的常量定义方式 ，要么宏定义，要么 enum C的 const 定义的标识符，结果不能成为常量表达式。


Question: 这个宏的作用是什么

引用 3 楼 sdghchj的回复:从A中抹去L-1的bit位。 比如A=5即00000101，L=4， L-1=3即 00000011,取反为 11111100 00000101 & 11111100 = 00000100 = 4 从A中抹去L-1的bit位。 比如A=5即00000101，L=4， L-1=3即 00000011,取反为 11111100 00000101 & 11111100 = 00000100 = 4[/quote] a=5,b=4 (a+b-1)&~(b-1) a->00000101+00000100-00000001=00001000 b-1->00000100-00000001=00000011取反 结果11111100 00001000 & 11111100 结果 00001000 呵呵，谢谢我也学会一招

原来与非门的作用是这样的啊。2、3楼正解

~((L) - 1))//L作为补码的原码  引用 2 楼 user-5 的回复:把地址 A 以 L 对齐。 L 必须是 4， 8， 16 之类的。++

把地址 A 以 L 对齐。 L 必须是 4， 8， 16 之类的。

#define MY_ALIGN(A,L)	(((A) + (L) - 1) & ~((L) - 1)) 应该就是在编译的时候将#define MY_ALIGN(A,L)替换成#(((A) + (L) - 1) & ~((L) - 1))呗 A+L-1与非L-1具体结果，还真得想一下


Question: 除了C PRIMER PLUS，请推荐基本C语言学习的好书，谢谢

引用 5 楼 learnc2015 的回复:[quote=引用 4 楼 Smile_Couson 的回复:] C语言程序设计-现代方法，新华书店在售。非常翔实易懂。 《C语言程序设计：现代方法》好像和《C语言程序设计》是两本不同的书  C程序设计语言（第2版·新版）Brian W．Kernighan, Dennis M．Ritchie徐宝文 李志 译 机械工业出版社30元 C语言程序设计：现代方法K.N.KING吕秀锋 译 人民邮电出版社55元[/quote] 对的。 作者K.N.KING，人民邮电出版社的那本。

c和指针，(美)(KennethA．Reek) ，经典书籍

我推荐 《C语言程序设计：现代方法》K.N.KING 吕秀锋 译 人民邮电出版社

引用 4 楼 Smile_Couson 的回复:C语言程序设计-现代方法，新华书店在售。非常翔实易懂。 《C语言程序设计：现代方法》好像和《C语言程序设计》是两本不同的书  C程序设计语言（第2版·新版）Brian W．Kernighan, Dennis M．Ritchie徐宝文 李志 译 机械工业出版社30元 C语言程序设计：现代方法K.N.KING吕秀锋 译 人民邮电出版社55元

C语言程序设计-现代方法，新华书店在售。非常翔实易懂。

[C和指针（第二版）].(美)Kenneth A.Reek.徐波译.扫描版.pdf [高质量程序设计指南：C.／C语言（第3版）（修订版）].林锐.扫描版.pdf

那就C PRIMER, 比C PRIMER PLUS稍微深入点

除了C PRIMER PLUS，请推荐几本C语言学习的好书，谢谢


Question: 问一个关于大端小端存储模式的问题

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

引用 11 楼 qq_31510849 的回复:[quote=引用 10 楼 bluewanderer 的回复:] 这是题？谁出的把谁拖出去用板砖拍死去... （题外话，话说那个i是啥？）  如果a的地址是0xbfae4d68那不管大小端打印都是bfae4d68，另外你到底想打印a还是a[0]？  a[1]，是我打错了，打出a[0]的大小端存储，用内存结构示意图[/quote]  我大概明白了... 本来题目是让你写一个我那样的东西，结果你凌乱了，以为你写的那个就是题目要求的，并且认为你输出的结果是和题目有关的...

大端模式又叫高位优先，是指数据的高位保存在低地址中 小端模式有叫做低位优先，是指数据的低位保存在低地址中。 大端模式的检测代码可以如下完成：  short tmp=0x1122; if(((char *)&tmp)[0]=0x11) { //高位优先，大端模式 }

引用 10 楼 bluewanderer 的回复:这是题？谁出的把谁拖出去用板砖拍死去... （题外话，话说那个i是啥？）  如果a的地址是0xbfae4d68那不管大小端打印都是bfae4d68，另外你到底想打印a还是a[0]？  a[1]，是我打错了，打出a[0]的大小端存储，用内存结构示意图

引用 8 楼 bluewanderer 的回复:那压根就是一个不确定的地址，而且根本不受大小端影响...  所以这道题就是这么回答的？ a[0]以大端存储模式输出的话就是bf ae 4d 68 小端就是 68 4d ae bf?

那压根就是一个不确定的地址，而且根本不受大小端影响...

引用 6 楼 bluewanderer 的回复:[quote=引用 5 楼 qq_31510849 的回复:] [quote=引用 4 楼 bluewanderer 的回复:] #include <stdio.h>  int main() { 	unsigned short a = 0x0100;  	printf("%d\n", ((unsigned char *)&a)[0]); }  大端输出1，小端输出0       我是想搞懂为什么0X12345678会变成那个结果[/quote]  根本和0x12345678没半毛钱关系啊，赋值前就已经输出了啊[/quote]    那么a[0]以大端存储模式输出的话就是bf ae 4d 68 小端就是 68 4d ae bf?

引用 5 楼 qq_31510849 的回复:[quote=引用 4 楼 bluewanderer 的回复:] #include <stdio.h>  int main() { 	unsigned short a = 0x0100;  	printf("%d\n", ((unsigned char *)&a)[0]); }  大端输出1，小端输出0       我是想搞懂为什么0X12345678会变成那个结果[/quote]  根本和0x12345678没半毛钱关系啊，赋值前就已经输出了啊

引用 4 楼 bluewanderer 的回复:#include <stdio.h>  int main() { 	unsigned short a = 0x0100;  	printf("%d\n", ((unsigned char *)&a)[0]); }  大端输出1，小端输出0       我是想搞懂为什么0X12345678会变成那个结果

引用 1 楼 bluewanderer 的回复:输出个栈里的地址能有什么用？  直接把一个多字节的变量当字节数组把第一个元素读出来看是高字节还是低字节不就成了。 什么意思，我刚学这个方面，如何读取？

什么意思，我刚学这个方面，有点不太清除


Question: c语言问题

VC6和其后的VS行为不一样。 其后的VS更符合C++标准。

测试代码: #include<stdio.h>   void main (void) { for (int i=0;i<5;i++) { 	printf("i+1:%d\t",i+1); } puts(" "); printf("for语句后i:%d\n",i); puts(" "); }

1、标准C(ANSI C / C89)不支持，C++ / C99才支持这样的定义方式； 2、i的作用范围仅限于该for代码块，属于块局部变量。  引用 楼主 ddbbv 的回复:for(int i=0;i<10;i++);  大家好，我刚开始学c语言，我问个问题， 对于for语句，在for 语句里面定义变量i可以吗？ 如果可以，那么i的作用范围是多少？

插补算法仿真程序设计， （1）能实现直线插补算法仿真      输入起点及终点坐标，按照每0.1秒钟的速度，以图形显示X/Y步进顺序和轨迹。 （2）圆弧插补      输入圆心及起点坐标，按照每0.1秒钟的速度，以图形显示X/Y步进顺序和轨迹。 （3）控制界面。       欢迎界面，有功能选择选项（直线插补和圆弧插补）。 （1）提供运行界面，界面美观。 （2）实现命令行绘图控制：       G00 空走 G01:直线插补  G02:顺圆插补，G03逆圆插补       X## X方向坐标  Y## Y方向坐标       输入一段代码，比如G01 X100 Y100  从当前点直线插补到(100,100)的地方；       注：上述G00 ，G01，G02，G03为软件自定义命令 （3） 具有插补坐标序列的文本文件（txt）存储功能和读取功能。即能向文           本文件中存储插补坐标序列，也可读取存储基本要求（1）中直线、                     圆或圆弧插补坐标序列的TXT文档，并能图形回显。 求助大神解答！

for 语句后面都可以用。包括此for 语句外。


Question: 请问C语言为什么不能把常量字符串赋给数组？

引用 8 楼 zhao4zhong1 的回复:“变量赋值”和“变量初始化”不是一回事！ “变量赋值”发生在运行期，其写法遵循赋值语法规定。 “变量初始化”发生在编译期或运行期，其写法遵循初始化列表语法规定。 查MSDN是Windows程序员必须掌握的技能之一。 https://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.71).aspx

需要复制的话建议使用strcpy或者更加安全的strcpy_s  如果觉得这样写麻烦，可以使用标准库中的std::string，其对象支持直接复制

char name[20] ={0}; strcpy(name, "hello idiot");//赋值不行，但是可以拷贝 //数组名是数组的首地址，是常量。

那么赋值应该怎么写呢？

引用 5 楼 u014626834 的回复:可是不是经常有 char name[20]="你好，朋友";这样的语句吗？ 这是初始化，不是赋值

可是不是经常有 char name[20]="你好，朋友";这样的语句吗？

地址赋值给地址，当然不行了

char str[] = "Hello World!";

我只听过字符串常量，没听过常量字符串. 字符串常量: - 类型是char[N]  - 连续存储，末尾自动添加\0 - 静态存储 - 相同值常量的地址可以不同 - 修改字符是未定义行为  常量字符串? const char* const?, C语言的const只是君子协议 又不是不能再修改.

常量字符串首元素的地址是常量，数组名也是常量，能常量赋给常量么？


Question: for循环中排序后引起数组数据是怎么回事？是局部变量的原因吗？

int handle(int * a)函数中的  for(int i = 0; i< 6;i++)  是不是应该为  for(int i = 0; i< 5;i++)

我要是把 int s 变成全局变量 就正常了 为什么呢？

引用 1 楼 yanpingzaizai 的回复:因为你传的是地址，所以 在函数中对数字操作会改变数组中的值 for循环中排序直接对原数组进行操作，改变数组中的值。

引用 1 楼 yanpingzaizai 的回复:因为你传的是地址，所以 在函数中对数字操作会改变数组中的值 我只是排序了一下 ，并没有改变内容啊 ？

因为你传的是地址，所以 在函数中对数字操作会改变数组中的值


Question: #include的问题

相对路径， 目的是让使用者看到相关函数和类的定义

相对路径 .   代表当前 ..  代表上一级 /   为相邻路径的分隔符

#include <>  表示在系统的头文件路径下找指定的头文件 #include "" 表示在当前路径下找指定的头文件

头文件也是有路径的

../../../代表的是 当前目录的"上一层再上一层再上一层目录"


Question: 关于局部变量和全局变量的一个问题

闭包是可以的，但需要支持C99 #include<stdio.h> int main() {     int a=1;     void f()     {         a=2;     }     f();     printf("%d\n",a);     return 0; } // Output: // 2

f2 已经分家出去了，单过了再用老头的钱说不过去的。

这个帖子也纠正了我认识上的误区！

不要把JS的思想代到C++中来了.  每个变量是有生命周期和作用域的.  auto int b; 这个是函数f1中的变量, 作用域限定在f1内,  f2中是不可见的. 同理, f1中也对f2中的c不可见

如果 b 是个传递到 f2() 中的参数，那就可见，如果没有传递到 f2() 中，那就不可见

如果传参的话可以

得使用全局变量才行……

b在f2中不可见。 函数是平等的，不是说调用谁谁就是下一级函数，就可以使用上一级的局部变量。

f1()，f2()，没有参数，不能传递 如果有参数，可以传递 另外 一个生命周期在语句组内部， auto int b; 一个在整程序生存期内


Question: VS2012怎么不能编译C呢？

谢谢各位的帮助，已经解决。vs2012 express for desktop 有漏洞，更新update 5 就可以编译使用了。 当然先要检查楼上各位提到的问题。

用CFree也可以的

盲从！几到几十 MB 的 C/C++ 集成环境遍地都是，很多初学者仅仅为了学 C/C++ 基础却去安装好几个GB的VS，也是服了！

或者说没有完整安装。

无法打开 stdio.h 是因为你没有卸载干净。。。

你得添加一个默认的头文件  #include "stdafx.h"  在最顶部。 要么就按照5楼的在属性中 选择 不使用 预编译头文件。

项目属性里改成不使用预编译头试下

改用简洁强大的Code::Blocks(http://www.codeblocks.org/)。

安装配好的话，肯定是可以的，楼主没安装好吧~~~

估计是你vs安装的问题，重装前，必须卸载干净（这方面微软做得确实有点失败）


Question: sizeof与strlen字符统计问题

引用 14 楼 yajuie 的回复:[quote=引用 13 楼 yajuie的回复:]本人小白，也来自己推算一下。看看结果对不对？大神们就不要拍了啊！  char str1[]="\\0318\"asb"; char str2[]={'1','\0','2'}; char str3[]="1\02"; char a[]="a0\0a0\0"; printf("%d\n",sizeof(str1)); //sizeof()是计算数组大小，这个代码内，数组存放应该是这样 \,0,3,1,8,",a,s,b,\0;结果应为10;  printf("%d\n",strlen(str1)); //strlen()是计算字符串，但不会算\0，因此会是结果会是9  printf("%d\n",sizeof(str2)); //这个存放时是以字符形式存放的，后并没有0，因此它的结果应该是3.   printf("%d\n",sizeof("123")); //这段代码，我理解的不是很透说得不对的话，大神们可以指正一下，但不要光拍砖，不来干货，首先123是字符串，他会以字符串的形式存放在常量区，而这样交给sizeof()，这个字符串在常量区的首地址,所以说"123"加上\0,一共会有4个字符，这里会是,4  printf("%d\n",strlen(str2)); //这里就好理解了，strlen,遇到\0会给束，而字符数组内\0也就是第二个字符，就会结束，而且不计算\0，因此这里应该是1;  printf("%d\n",sizeof(str3)); //"1\02"; //数组的存放模式应该是，1,\0,2, \0因此这里是3  printf("%d\n",strlen(str3));// "1\02"; //这里因为第二个字符是 \0，这里应该输出1  printf("%d\n",sizeof(a));// "a0\0a0\0"; //字符串在内存中的存放 a,0,\0,a,0,\0,\0,应此这里应输出 7  printf("%d\n",strlen(a));// "a0\0a0\0"; //第3个元素是\0，应此这里是2; 居然在这种情况下还错了两个地方，而且有一道，还数数数错了。晕死[/quote]  哈哈，感谢你这么耐心的解答，我明白了。谢谢

引用 1 楼 fly_dragon_fly 的回复:sizeof是求的类型, strlen是求字符串长度 1 有两个\\, 就算一个\0也要小心, 后面跟数字默认是八进制 2 str2是数组, "123"类型是const char * 3 第二个字节就是0 4 数组 5 \0后跟数字代表八进制 6 数组 引用 7 楼 user-7 的回复:如果希望表达 abd\0 和 2xyz 连接而成的字符串 写成 "abcd\0""2xyz" 这样两个 中间的引号会被忽略，因为两个字符串字面值，连续写（中间有空格）代表他们的连接    输出的时候是 abcd  继续输出可以输出2xyz 谢谢回答啊，明白是怎么回事了。

引用 1 楼 fly_dragon_fly 的回复:sizeof是求的类型, strlen是求字符串长度 1 有两个\\, 就算一个\0也要小心, 后面跟数字默认是八进制 2 str2是数组, "123"类型是const char * 3 第二个字节就是0 4 数组 5 \0后跟数字代表八进制 6 数组"123" 类型是char[4] 不是char*

引用 13 楼 yajuie的回复:本人小白，也来自己推算一下。看看结果对不对？大神们就不要拍了啊！  char str1[]="\\0318\"asb"; char str2[]={'1','\0','2'}; char str3[]="1\02"; char a[]="a0\0a0\0"; printf("%d\n",sizeof(str1)); //sizeof()是计算数组大小，这个代码内，数组存放应该是这样 \,0,3,1,8,",a,s,b,\0;结果应为10;  printf("%d\n",strlen(str1)); //strlen()是计算字符串，但不会算\0，因此会是结果会是9  printf("%d\n",sizeof(str2)); //这个存放时是以字符形式存放的，后并没有0，因此它的结果应该是3.   printf("%d\n",sizeof("123")); //这段代码，我理解的不是很透说得不对的话，大神们可以指正一下，但不要光拍砖，不来干货，首先123是字符串，他会以字符串的形式存放在常量区，而这样交给sizeof()，这个字符串在常量区的首地址,所以说"123"加上\0,一共会有4个字符，这里会是,4  printf("%d\n",strlen(str2)); //这里就好理解了，strlen,遇到\0会给束，而字符数组内\0也就是第二个字符，就会结束，而且不计算\0，因此这里应该是1;  printf("%d\n",sizeof(str3)); //"1\02"; //数组的存放模式应该是，1,\0,2, \0因此这里是3  printf("%d\n",strlen(str3));// "1\02"; //这里因为第二个字符是 \0，这里应该输出1  printf("%d\n",sizeof(a));// "a0\0a0\0"; //字符串在内存中的存放 a,0,\0,a,0,\0,\0,应此这里应输出 7  printf("%d\n",strlen(a));// "a0\0a0\0"; //第3个元素是\0，应此这里是2; 居然在这种情况下还错了两个地方，而且有一道，还数数数错了。晕死

引用 9 楼 zhao4zhong1 的回复:我说过所有sizeof都是在编译期计算了吗？  你以为朕是外国人不懂中国话吗？!

好吧, 这里是C语言子版块, 我还以为是C++, C99支持VLA, 虽说C11时半废了

引用 8 楼 sholber 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 了解一下 sizeof是编译期计算的，其源代码在编译器的源代码中； strlen是运行期计算的，其源代码在C运行时库的源代码中。  麻烦告诉我，下面的sizeof如何在编译期算出来：  int f (int n) {     return sizeof (int [n]); }[/quote]  sizeof表达式操作的是常量, 这样会编译失败

我说过所有sizeof都是在编译期计算了吗？

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

引用 2 楼 zhao4zhong1 的回复:了解一下 sizeof是编译期计算的，其源代码在编译器的源代码中； strlen是运行期计算的，其源代码在C运行时库的源代码中。  麻烦告诉我，下面的sizeof如何在编译期算出来：  int f (int n) {     return sizeof (int [n]); }

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

\\ 表示 \ 本身  所以 字符串是 【\ ,0 ,3,1,8,",a,s,b】 这9个字符 \0 是一个字符。 值为 0 因为已经 转义了一次了 这个 \ 不再能够转义别的字符了。 \02，是8进制转义字符 \02 =2 , 转义字符 遇到数字要特别注意，，，遇到字母，有时候也要仔细考察 \a，\b 也都是转义字符


Question: C Primer Plus第121页说，浮点型只能用> 和 < 来比较，那么我要判断 1.5>1.4999怎么办？

仅供参考：#include <stdio.h> #include <stdlib.h> #include <string.h> float f; double d; void showf() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nf=%.6f\n",f);     p=(unsigned char *)&f;     printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);     ltoa(*(long *)&f,b,2);     sprintf(bs,"%032s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);     strncpy(e,bs+1,8);e[8]=0;     ex=strtol(e,&t,2);     printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);     ex-=127;     printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9); } void showd() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nd=%.15lf\n",d);     p=(unsigned char *)&d;     printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);     _i64toa(*(__int64 *)&d,b,2);     sprintf(bs,"%064s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);     strncpy(e,bs+1,11);e[11]=0;     ex=strtol(e,&t,2);     printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);     ex-=1023;     printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12); } int main() {      for (f=0.0f;f<=2.2f;f+=0.2f) showf();     printf("------------\n");     f=2.0f;showf();     printf("-----------------------------------\n");     for (d=0.0 ;d<=2.2 ;d+=0.2 ) showd();     printf("------------\n");     d=2.0 ;showd();      return 0; } // //f=0.000000 //hex=00 00 00 00 //bin=00000000000000000000000000000000 //bin=0 00000000   00000000000000000000000 //  + 0   -127 1.00000000000000000000000 //  + -127     1.00000000000000000000000 // //f=0.200000 //hex=3E 4C CC CD //bin=00111110010011001100110011001101 //bin=0 01111100   10011001100110011001101 //  + 124 -127 1.10011001100110011001101 //  + -3       1.10011001100110011001101 // //f=0.400000 //hex=3E CC CC CD //bin=00111110110011001100110011001101 //bin=0 01111101   10011001100110011001101 //  + 125 -127 1.10011001100110011001101 //  + -2       1.10011001100110011001101 // //f=0.600000 //hex=3F 19 99 9A //bin=00111111000110011001100110011010 //bin=0 01111110   00110011001100110011010 //  + 126 -127 1.00110011001100110011010 //  + -1       1.00110011001100110011010 // //f=0.800000 //hex=3F 4C CC CD //bin=00111111010011001100110011001101 //bin=0 01111110   10011001100110011001101 //  + 126 -127 1.10011001100110011001101 //  + -1       1.10011001100110011001101 // //f=1.000000 //hex=3F 80 00 00 //bin=00111111100000000000000000000000 //bin=0 01111111   00000000000000000000000 //  + 127 -127 1.00000000000000000000000 //  + 0        1.00000000000000000000000 // //f=1.200000 //hex=3F 99 99 9A //bin=00111111100110011001100110011010 //bin=0 01111111   00110011001100110011010 //  + 127 -127 1.00110011001100110011010 //  + 0        1.00110011001100110011010 // //f=1.400000 //hex=3F B3 33 34 //bin=00111111101100110011001100110100 //bin=0 01111111   01100110011001100110100 //  + 127 -127 1.01100110011001100110100 //  + 0        1.01100110011001100110100 // //f=1.600000 //hex=3F CC CC CE //bin=00111111110011001100110011001110 //bin=0 01111111   10011001100110011001110 //  + 127 -127 1.10011001100110011001110 //  + 0        1.10011001100110011001110 // //f=1.800000 //hex=3F E6 66 68 //bin=00111111111001100110011001101000 //bin=0 01111111   11001100110011001101000 //  + 127 -127 1.11001100110011001101000 //  + 0        1.11001100110011001101000 // //f=2.000000 //hex=40 00 00 01 //bin=01000000000000000000000000000001 //bin=0 10000000   00000000000000000000001 //  + 128 -127 1.00000000000000000000001 //  + 1        1.00000000000000000000001 //------------ // //f=2.000000 //hex=40 00 00 00 //bin=01000000000000000000000000000000 //bin=0 10000000   00000000000000000000000 //  + 128 -127 1.00000000000000000000000 //  + 1        1.00000000000000000000000 //----------------------------------- // //d=0.000000000000000 //hex=00 00 00 00 00 00 00 00 //bin=0000000000000000000000000000000000000000000000000000000000000000 //bin=0 00000000000   0000000000000000000000000000000000000000000000000000 //  + 0     -1023 1.0000000000000000000000000000000000000000000000000000 //  + -1023       1.0000000000000000000000000000000000000000000000000000 // //d=0.200000000000000 //hex=3F C9 99 99 99 99 99 9A //bin=0011111111001001100110011001100110011001100110011001100110011010 //bin=0 01111111100   1001100110011001100110011001100110011001100110011010 //  + 1020  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -3          1.1001100110011001100110011001100110011001100110011010 // //d=0.400000000000000 //hex=3F D9 99 99 99 99 99 9A //bin=0011111111011001100110011001100110011001100110011001100110011010 //bin=0 01111111101   1001100110011001100110011001100110011001100110011010 //  + 1021  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -2          1.1001100110011001100110011001100110011001100110011010 // //d=0.600000000000000 //hex=3F E3 33 33 33 33 33 34 //bin=0011111111100011001100110011001100110011001100110011001100110100 //bin=0 01111111110   0011001100110011001100110011001100110011001100110100 //  + 1022  -1023 1.0011001100110011001100110011001100110011001100110100 //  + -1          1.0011001100110011001100110011001100110011001100110100 // //d=0.800000000000000 //hex=3F E9 99 99 99 99 99 9A //bin=0011111111101001100110011001100110011001100110011001100110011010 //bin=0 01111111110   1001100110011001100110011001100110011001100110011010 //  + 1022  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -1          1.1001100110011001100110011001100110011001100110011010 // //d=1.000000000000000 //hex=3F F0 00 00 00 00 00 00 //bin=0011111111110000000000000000000000000000000000000000000000000000 //bin=0 01111111111   0000000000000000000000000000000000000000000000000000 //  + 1023  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 0           1.0000000000000000000000000000000000000000000000000000 // //d=1.200000000000000 //hex=3F F3 33 33 33 33 33 33 //bin=0011111111110011001100110011001100110011001100110011001100110011 //bin=0 01111111111   0011001100110011001100110011001100110011001100110011 //  + 1023  -1023 1.0011001100110011001100110011001100110011001100110011 //  + 0           1.0011001100110011001100110011001100110011001100110011 // //d=1.400000000000000 //hex=3F F6 66 66 66 66 66 66 //bin=0011111111110110011001100110011001100110011001100110011001100110 //bin=0 01111111111   0110011001100110011001100110011001100110011001100110 //  + 1023  -1023 1.0110011001100110011001100110011001100110011001100110 //  + 0           1.0110011001100110011001100110011001100110011001100110 // //d=1.600000000000000 //hex=3F F9 99 99 99 99 99 99 //bin=0011111111111001100110011001100110011001100110011001100110011001 //bin=0 01111111111   1001100110011001100110011001100110011001100110011001 //  + 1023  -1023 1.1001100110011001100110011001100110011001100110011001 //  + 0           1.1001100110011001100110011001100110011001100110011001 // //d=1.800000000000000 //hex=3F FC CC CC CC CC CC CC //bin=0011111111111100110011001100110011001100110011001100110011001100 //bin=0 01111111111   1100110011001100110011001100110011001100110011001100 //  + 1023  -1023 1.1100110011001100110011001100110011001100110011001100 //  + 0           1.1100110011001100110011001100110011001100110011001100 // //d=2.000000000000000 //hex=3F FF FF FF FF FF FF FF //bin=0011111111111111111111111111111111111111111111111111111111111111 //bin=0 01111111111   1111111111111111111111111111111111111111111111111111 //  + 1023  -1023 1.1111111111111111111111111111111111111111111111111111 //  + 0           1.1111111111111111111111111111111111111111111111111111 // //d=2.200000000000000 //hex=40 01 99 99 99 99 99 99 //bin=0100000000000001100110011001100110011001100110011001100110011001 //bin=0 10000000000   0001100110011001100110011001100110011001100110011001 //  + 1024  -1023 1.0001100110011001100110011001100110011001100110011001 //  + 1           1.0001100110011001100110011001100110011001100110011001 //------------ // //d=2.000000000000000 //hex=40 00 00 00 00 00 00 00 //bin=0100000000000000000000000000000000000000000000000000000000000000 //bin=0 10000000000   0000000000000000000000000000000000000000000000000000 //  + 1024  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 1           1.0000000000000000000000000000000000000000000000000000 //

1.5>1.4999 这个为true，不需要程序去判断。  如果你使用变量来判断，那么你的程序肯定会有精度的要求。 此时需要依据你的精度来判断。 在实际使用的过程中，同样一个结果，在不同的时候是不一致的。

引用 6 楼 paschen的回复:书想表达的意思是最好不要用==、！=这种运算符判断浮点数是否相等，因为可能有精度误差导致问题，判断相等建议判断两浮点数相减绝对值是否小于一个很小的数 学习了，刚入门学习，还真没注意这方面问题

引用 3 楼 zhangxiangDavaid 的回复:照样使用 if(5.01 >= 5.001) C PRIMER PLUS第5版，第121页说，浮点型只能用> 和 < 来比较

浮点型应该能判断 >= <= 如果你有问题可以写代码直接运行检验一下。

照样使用 if(5.01 >= 5.001)

引用 1 楼 zhangxiangDavaid 的回复:直接 if(1.5 > 1.4999) 我说错了，我是说我要判断 5.01>=5.001怎么办？ 难道浮点型没法判断 >= <=了?

直接 if(1.5 > 1.4999)

5.01>=5.001 这当然可以啦  浮点数做比较运算的时候问题通常是这样产生的：1.23 == 1.23  这大多数时候是false   因为精度问题，你只给出小数后两位有效数字，而编译器处理double显然不止两位  在这个时候，正确的做法是： a - b <= 0.001    如果这个是true，则视为a==b     你可以通过修改0.001来确定一个可以满足你需要的精度

浮点数精度不同，如果等的话很危险...