Question: css中的alloca替代？？

ccs是什么？

/STACK   (Stack Allocations) Home |  Overview |  How Do I |  Linker Options  The Stack Allocations (/STACK:reserve[,commit]) option sets the size of the stack in bytes.   To find this option in the development environment, click Settings on the Project menu. Then click the Link tab, and click Output in the Category box. The Reserve text box (or in the reserve argument on the command line) specifies the total stack allocation in virtual memory. The default stack size is 1 MB. The linker rounds up the specified value to the nearest 4 bytes.  The optional value specified in the Commit text box (or in the commit argument on the command line) is subject to interpretation by the operating system. In Windows NT, it specifies the amount of physical memory to allocate at a time. Committed virtual memory causes space to be reserved in the paging file. A higher commit value saves time when the application needs more stack space, but increases the memory requirements and possibly the startup time.  Specify the reserve and commit values in decimal or C-language notation.  Another way to set the size of the stack is with the STACKSIZE statement in a module-definition (.DEF) file. STACKSIZE overrides the Stack Allocations (/STACK) option if both are specified. You can change the stack after the .EXE file is built by using the EDITBIN tool.

_alloca Allocates memory on the stack.  void *_alloca( size_t size );  Routine Required Header Compatibility  _alloca <malloc.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  The _alloca routine returns a void pointer to the allocated space, which is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than char, use a type cast on the return value. A stack overflow exception is generated if the space cannot be allocated.  Parameter  size  Bytes to be allocated from stack  Remarks  _alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function exits. Therefore, do not pass the pointer value returned by _alloca as an argument to free.  There are restrictions to explicitly calling _alloca in an exception handler (EH). EH routines that run on x86-class processors operate in their own memory “frame”: They perform their tasks in memory space that is not based on the current location of the stack pointer of the enclosing function. The most common implementations include Windows NT structured exception handling (SEH) and C++ catch clause expressions. Therefore, explicitly calling _alloca in any of the following scenarios results in program failure during the return to the calling EH routine:   Windows NT SEH exception filter expression:  __except ( alloca() )   Windows NT SEH final exception handler:  __finally { alloca() }   C++ EH catch clause expression  However, _alloca can be called directly from within an EH routine or from an application-supplied callback that gets invoked by one of the EH scenarios listed above.   Memory Allocation Routines  See Also   calloc, malloc, realloc


Question: C语言或者C++中关于字符串两两转换成无符号字符类型即MAC格式

使用的头文件： #include <tchar.h> #include <vector> using namespace std;

仅供参考，unsigned char pChar[32];我设置的固定值，视情况自己改。否则出现Bug概不负责。   void get16(string strBuffer) { 	vector<string> vctStr; 	for (int i=0;i<strBuffer.size();i=i+2) 	{ 		string strTemp = strBuffer.substr(i,2); 		vctStr.push_back(strTemp); 	} 	vector<string>::size_type first; 	int isize = vctStr.size(); 	unsigned char pChar[32]; 	for (first = 0;first < isize;first++) 	{ 		pChar[first] = _tcstol(vctStr[first].c_str(),NULL,16); //转换成十六进制 	} }


Question: 用C实现SMS4国密算法，我实在是找不出来哪里溢出了，大神们求帮助TAT

弱爆，S盒固定的啊？不能根据密钥生成？

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

//你的K_function和F_function函数中都存在内存违规访问的问题，见注释 //这样的问题，调试运行的话很容易找到的 unsigned int K_function(unsigned int a0,unsigned int a1,unsigned int a2,unsigned int a3,unsigned int rk) { 	unsigned char t,temp; 	unsigned char *tc; 	t = a1 ^ a2 ^ a3 ^ rk; 	tc = &t;         //tc保存的仅仅是t的地址   	//S盒替代运算 	tc[0]=S[tc[0]]; //tc[0]相当于访问t，所以这里没有内存越界访问 	tc[1]=S[tc[1]]; //越界访问 	tc[2]=S[tc[2]]; //越界访问 	tc[3]=S[tc[3]]; //越界访问  	//线性变换L 	temp = t << 13; //t <<< 13 	t = t ^ temp;  	temp = temp << 10;     //t <<< 23  	t = t ^ temp;   	t = a0 ^ t;   	return t;  }


Question: 可以这样吗？

可以的！！！

可以是可以，但这样一来代码会很容易出错的，多写一行代码算什么呢？对于大程序而言，错一行也是大事啊……

存在不安全因素 比如kind为 ++a 就变成if(0 < ++a && ++a < 20),这可能不是自己想要的  如果你想写成联等的，可以使用C++语言的运算符重载机制

要命，不喜欢C的风格就换个别的语种吧。

不要这样写！！！！！！ 这种代码看了会吐的，OK。

合法，但不好。

只要预编译后和原表达式一样即可，但是这种宏无法解决“所有”的可能性。 建议写个函数。

最好给X套上括号#define R(X) (X) && (X)

可以啊。但是表达式可能会出问题。

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

语法糖越甜，编译调试查错越苦！ 把有限的生命浪费在品尝/品鉴无穷多种的语法糖中，我认为不值当。


Question: 求助C语言一个基础数组问题

数组元素有类型，数组的首地址进行数值运算时，偏移量要乘以数组元素类型大小 换言之 a + 1 = 0x0030f85c + 1 * sizeof(int)

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

A[B] *(A+B) *(B+A) B[A] 以上四行等价

建议多看看指针的加减法！  如 int a[10];  a[i] 等价于 *(int*)( reinterpret_cast<BYTE*>(a）+ i * sizeof(int) );


Question: 请问在C语言中如何判断类型？

在API上加一个参数，传入类型  typedef enum {  type1 = 0,  type2 = 1,  ... } TYPE; void fun(const void *value, TYPE type) {  switch(type) {  case type1:      xxx *v = (xxx *)value;  break;  ...  } }

引用 12 楼 zhao4zhong1 的回复:仅供参考：//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5] typeinfo.h不是C语言的头文件吧。#ifndef __cplusplus   #error This header requires a C++ compiler ...   #endif  /* __cplusplus */

参考VARIANT的定义。

试了一下,gcc4.9 可以用C11的_Generic了。 #include<stdio.h>  #define V(X) \ 	printf(#X " is %s\n", \ 		_Generic((X), \ 			int:"int", \ 			char:"char", \ 			float:"float", \ 			double:"double", \ 			char*:"char*", \ 			int*:"int*", \ 			float*:"float*", \ 			default:"default" \ 		) \ 	)  int main() { 	int a;float b; 	V(1); 	V((char)'s'); 	V(1.2f); 	V(3.4); 	V("s"); 	V(&a); 	V(&b); 	V(main); 	return 0; } /* output: 1 is int (char)'s' is char 1.2f is float 3.4 is double "s" is char* &a is int* &b is float* main is default */

强制类型转换啊

使用gcc的typeof

这就是说你形参什么类型的都可以，自己调用时给什么类型都可以

int main (void) {     int f (void);     return f (); }  static int f (void) {/* …… */}

自定义type，入口判断。

编译器是指不上的了，靠自己想办法。

参照微软的做法, 在 void * 类型使用时, 再定义一个类型符 我用得最多的就是 SystemParametersInfo, 其中 uiAction 就表示了 pvParam 是何种类型 在函数内部 switch 这个类型符, 每个 case 处理一种

const void*   value,  这表明接收任何类型。但要使用的话，你得知道具体类型。

引用 1 楼 mewiteor 的回复:C语言没有反射 我知道没反射才来这里问答呢！

C语言没有反射


Question: 关于p++先取值，再加１的问题。

很详细自己看吧！http://bbs.csdn.net/topics/370153775

不知道为什么，这类问题好多人问呀  p++ 表达式展开就是豆号表达式:  (tmp = p, p += 1, tmp) 最终返回值是 tmp ... 就算放到 函数里也是 func(  (tmp = p, p += 1, tmp), n) ...

对。 void foo(int p) { 	cout << p << endl; }  int main() { 	int a = 10; 	foo(a++); 	cout << a << endl; 	return 0; }


Question: 约瑟夫环大数据要怎么做？

引用 7 楼 JiangWenjie2014 的回复: #include <stdio.h> #include <stdlib.h>  #define N 200000 #define M 5   struct list {   int prev;   int next; };  int Round (struct list *p, int cur) {   int i, pr, ne;    for (i = 0; i < M - 1; ++i) {     cur = p[cur].next;   }    pr = p[cur].prev;   ne = p[cur].next;    p[pr].next = ne;   p[ne].prev = pr;    //printf ("del %d\n", cur);    return ne; }  int main (int argc, char *argv[]) {   int idx, cur;    struct list *p = malloc (N * sizeof (*p));    for (idx = 0; idx < N; ++idx) {     p[idx].prev = (idx + N - 1) % N;     p[idx].next = (idx + 1) % N;   }  //  for (idx = 0; idx < N; ++idx) { //    printf ("%d) prev %d, next %d\n", idx, p[idx].prev, p[idx].next); //  }      printf ("Start\n");   for (idx = 0, cur = 0; idx < N; ++idx) {     cur = Round (p, cur);   }   printf ("Finish\n");    free (p);    return 0; } 时间还是超了，如果N=200000，时间大于1s，要怎样优化，这正是我所疑惑的

网上的约瑟夫公式都只是求最后一个数字，并不能将每次淘汰的数字输出

引用 3 楼 JiangWenjie2014 的回复: // [0,1,2,3,...,n-2,n-1]:m // Round 0: POS = (m-1)%n // Let k be the next position(m%n) of the deleted element, so remaining elements are //  k,k+1,...,n-2,n-1,0,1,2,...,k-2 //  0,1,2,...,n-3,n-2 << "each minus k, that is, m%n" // Round 1: POS = (m-1)%(n-1) // Let k be the next position(m%(n-1)) of the deleted element, so remaining elements are //  k,k+1,...,n-2,n-1,0,1,2,...,k-3 //  0,1,2,...,n-4,n-3 << "each minus k, that is, m%(n-1)" // // At round i, if element at position j is deleted, this element will be at // position (j+m)%(n-i) at round i-1. // // As is known to all, at round n-1, of course element at position 0 will be // deleted. So we got the formula // Position(n-1) = 0; // Position(i) = (Position(i+1)+m)%(n-i);  int Joseph(int n, int m) {   int pos;   for (int i = n-1; i >= 0; --i) {     if (i == n-1)       pos = 0;     else       pos = (pos+m)%(n-i);   }   return pos; } 谢谢，可是题目要的不仅仅只是最后幸存那个数字，而是要输出每一次淘汰的数字，要过大数据，请问怎么解决呢？

3楼好解法

搜“约瑟夫 公式”

每次踢出的数都要依次输出，不仅仅是输出最后一个数。这该怎么做


Question: scanf和gets函数的区别

引用 5 楼 zhangxiangDavaid 的回复:[quote=引用 3 楼 cdddfq 的回复:] 我想请问，我连用俩个scanf #include<stdio.h> void main() { 	int i = 1; 	scanf("%d", &i); 	scanf("%d",&i);	 	printf("%d\n",i); } 为什么我没有清空缓存区也不跳过 你输入第一个整数后，回车 回车字符会被读入但不会保存。于是你的接着输入第二个整数，才可以让第二个scanf读入 [/quote] 纠正： 你输入第一个整数后，回车 回车字符不会被读入。于是你的接着输入第二个整数，第二个scanf会自动跳过回车读入第二个整数。第二个回车不会被读入。

引用 3 楼 cdddfq 的回复:我想请问，我连用俩个scanf #include<stdio.h> void main() { 	int i = 1; 	scanf("%d", &i); 	scanf("%d",&i);	 	printf("%d\n",i); } 为什么我没有清空缓存区也不跳过 你输入第一个整数后，回车 回车字符会被读入但不会保存。于是你的接着输入第二个整数，才可以让第二个scanf读入

引用 3 楼 cdddfq 的回复:我想请问，我连用俩个scanf #include<stdio.h> void main() { 	int i = 1; 	scanf("%d", &i); 	scanf("%d",&i);	 	printf("%d\n",i); } 为什么我没有清空缓存区也不跳过 答案在#1楼。 英语也是一门计算机语言的说。

gets, _getws Get a line from the stdin stream.  char *gets( char *buffer );  wchar_t *_getws( wchar_t *buffer );  Routine Required Header Compatibility  gets <stdio.h> ANSI, Win 95, Win NT  _getws <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns its argument if successful. A NULL pointer indicates an error or end-of-file condition. Use ferror or feof to determine which one has occurred.  Parameter  buffer  Storage location for input string  Remarks  The gets function reads a line from the standard input stream stdin and stores it in buffer. The line consists of all characters up to and including the first newline character ('\n'). gets then replaces the newline character with a null character ('\0') before returning the line. In contrast, the fgets function retains the newline character. _getws is a wide-character version of gets; its argument and return value are wide-character strings.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _getts gets gets _getws    Example  /* GETS.C */  #include <stdio.h>  void main( void ) {    char line[81];     printf( "Input a string: " );    gets( line );    printf( "The line entered was: %s\n", line ); }   Output  Input a string: Hello! The line entered was: Hello!   Stream I/O Routines  See Also   fgets, fputs, puts

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.


Question: 一道笔试题，相同地址的int变量，不同内容是为何

因为代码是错的  这是未定义行为  结果毫无意义

引用 6 楼 u013163178 的回复:搜“常量折叠” 正解

2，4，6，8楼都对的，不过我记得的是C++才这样的，C是不是这样我没有考查过。

这应该和c++的编译器有关吧，c++对const的编译应该会类似define， 如果这个用c来执行对a进行强制转换，两次输出都应该是0

搜“常量折叠”

编译器会帮你做很多它认为理所应当的事，2楼4楼说的已经很全面了。

因为a是个const限定，导致编译器直接把a常量化了，也就说你输出a时，已被编译器转化为cout << 0;虽然你已经修改了值，但是输出已经不再从内存中读取了，而实际的*j还是从内存中读取 你可以在a上加上volatile试试，肯定就一样了  + volatile const int a = 0;

乍看起来c++的cin、cout在输入、输出上比c的scanf、printf简单，不用格式控制符！ 但是不用格式控制符，输入输出恰好是你期望的格式的时候好说；等到输入输出不是你期望的格式的时候，你就会觉得还是用格式控制符更方便、更靠谱。 摒弃cin、cout！ 使用scanf、printf。

1.你用指针改掉了a在内存中的值，虽然打印出的还是原来的0,但实际上它已经被改了 2.地址当然是一样的，j不是指向的是a吗，所以打印的地址是一样的  你在a前面加个volatile修饰，就知道了。

引用 楼主 llghwll 的回复:加上了(int *)，指针j指向的内容被赋值为了1  我还想问问楼主为何加了强制转换，就赋值为1了？？？


Question: （抓狂）几乎一样的两段代码，一段总报错。

自已看看哪不一样就知道了。typedef出来的别用用的太早了。

“几乎一样”，就在于哪里不一样

唉！羞愧！谢谢大家

楼上的+1.

楼上的+1.

1楼+1， 这个结构定义完成才起别名， 在结构内，别名还没有生效

第一个结构体里边“struct TREENODE *...”有问题，不要用TREENODE，要使用TreeNode。也就是说，在结构体里边使用结构体本身时，最好使用原类型，不要使用typedef之后的类型

几乎这词用到了好处

既然使用C++，就不要使用 typedef struct Tt { } TT; 的语法了，这样的语法 TT 只是个别名，实际不存在名叫 TT 的类型。  直接使用 struct TT { } ;

C语言分大小写所以struct TreeNode和struct TREENODE是不同的名字（struct是名字的一部分）


Question: 有关TCP/IP中持续上传新数据问题

引用 2 楼 zhao4zhong1 的回复:建立数据库连接 while(1) {   usleep(1000000);  从数据库获取数据到buf  connect  send  close } 断开数据库连接  您好，我想问一下在while中close后，下次循环时还能再connect么，使用close不就是关闭客户端了么

这样发一次数据就要打开关闭客户端一次，感觉好傻，想不出来怎样改变buf的值

引用 6 楼 zhao4zhong1 的回复:你没close当然不能再connect了。  恩，好像是的，但是加了还是报错

你没close当然不能再connect了。

引用 4 楼 zhao4zhong1 的回复:connect send close 都是对socket操作，和数据库连接没关系。 要更稳妥，请改为  connect send recv收到对端对应刚才send内容已收到的应答 close  不好意思啊，我试了下，把connect放在循环中执行一次后，第二次就会报错	  while(1) {      int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr));//连接 	if(r == -1) 	{ 		DEBUG_MSG("connect err : %d\n", errno); 		return 1; 	} 	DEBUG_MSG("connect success\n");                  memset(buf, 0, 127);           fread(buf, 1, 1, fp);    //测试只用了文件操作，读取一个txt文本中的数据           send(fd, buf, 127, 0);          DEBUG_MSG("data send\n") }  运行结果 create socket success connect success data send connect err : 106  如果把close放入循环也会报错 create socket success connect success data send connect err : 9  把connect拿出循环就成功了  基于文件操作的灵感，我想在sqlite3里有没有读取数据后，偏移到下一条数据的函数，这样执行实现我的想法


Question: 我这样的写法有什么不对吗？

# include <stdio.h>  int main() {     int mb = 0;     int a = 0, b = 0;      mb = 0;     a = 0;     b = 0;     printf("a = %d, b = %d\n", a, b);     mb == 0 ? (a = 1) : (b = 1);     printf("a = %d, b = %d\n", a, b);      mb = 1;     a = 0;     b = 0;     printf("a = %d, b = %d\n", a, b);     mb == 0 ? (a = 1) : (b = 1);     printf("a = %d, b = %d\n", a, b);      mb = 0;     a = 0;     b = 0;     printf("a = %d, b = %d\n", a, b);     *(mb == 0 ? &a : &b) = 1;     printf("a = %d, b = %d\n", a, b);      return 0;

不管只知不知道优先级，多加个括号总是不会错的，这也是一种好的编程习惯

y = (x != y ? s1 : s2).i;

引用 12 楼 mbctb 的回复:[quote=引用 11 楼 woshiyuanlei 的回复:] 楼上不是都已经有人回答了是右值么。。右值不能赋值。。像2楼那样就可以赋值了。。自己百度一下左值右值吧 是的，我看到楼上的了，但是我有个疑问，既然它是个右值，不能赋值，那编译器应该报错啊？可是编译器没有报错。这个问题我是经过很艰苦的调试才找到的。  我想知道编译器把它误会成什么了？为什么会有这样的误会？[/quote]  怪我刚才妄下评论，这是汇编，结果很明显  	int csdn_c=0,csdn_a=0,csdn_b=0; 00412D90  mov         dword ptr [ebp-18h],0    //csdn_c=0 00412D97  mov         dword ptr [ebp-24h],0    //csdn_a=0 00412D9E  mov         dword ptr [ebp-30h],0   //csdn_b=0 	csdn_c==0?csdn_a:csdn_b=1; 00412DA5  cmp         dword ptr [ebp-18h],0    //csdn_c==0 00412DA9  jne         wmain+66h (412DB6h)  //假如csdn_c不等于0，就跳到00412DB6处 00412DAB  mov         eax,dword ptr [ebp-24h]   //这句和后面两句没太多用,总之csdn_a的值未变 00412DAE  mov         dword ptr [ebp-5C0h],eax   00412DB4  jmp         wmain+76h (412DC6h)   00412DB6  mov         dword ptr [ebp-30h],1      //假如csdn_c不等于0，就跳到这里,这时给csdn_b赋值1 00412DBD  mov         ecx,dword ptr [ebp-30h]   00412DC0  mov         dword ptr [ebp-5C0h],ecx   	cout<<"csdn_a="<<csdn_a<<" csdn_b="<<csdn_b<<endl; 00412DC6  mov         esi,esp   00412DC8  mov         eax,dword ptr [__imp_std::endl (43055Ch)]      依据我的分析，你的代码中如果mb==0为假，那么b是可以赋值成功的，a则不行。。

二楼正解！！

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

一楼正解。 你可以在编译器中查看错误原因。

?和= 结合性是从右到左

mb == 0 ? (a=1) : (b = 1); //你的代码相当于 if(mb == 0)     a ; else     b = 1;

引用 11 楼 woshiyuanlei 的回复:楼上不是都已经有人回答了是右值么。。右值不能赋值。。像2楼那样就可以赋值了。。自己百度一下左值右值吧 是的，我看到楼上的了，但是我有个疑问，既然它是个右值，不能赋值，那编译器应该报错啊？可是编译器没有报错。这个问题我是经过很艰苦的调试才找到的。  我想知道编译器把它误会成什么了？为什么会有这样的误会？

引用 8 楼 LouisScola 的回复:搞不清楚优先级的时候就加（） 可是，？　：　的　优先级不是比　＝　高吗？ 所以我觉得：mb == 0 ? a : b = 1; 就等于：(mb == 0 ? a : b) = 1; 这有什么不对吗？

自己写代码搞不清楚算符优先级请多加括号。 看别人代码搞不清楚算符优先级能调试的话请单步调试对应汇编。 看别人代码搞不清楚算符优先级不能调试的话想办法照写一小段孤立的可调试的代码然后单步调试对应汇编。 看别人代码搞不清楚算符优先级不能调试的话且没有办法照写一小段孤立的可调试的代码然后单步调试对应汇编的话只能参考算符优先级表猜了（提醒：并不能100%猜对）。 //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 | //+------------------+-----------------------------------------+---------------+

搞不清楚优先级的时候就加（）

mb == 0 ? a : b的结果是右值，也就a或b的值，而不是其变量本身，所以不可被赋值。把代码改成*(mb == 0 ?& a:&b) = 1;即可。


我改成了scanf就不存在这样的问题了，但是输出结果有问题，测试数据为100 50 90的时候，我的输出为YES 18，但是，正解为NO 250? 为什么？  #include<stdio.h> #include<stdlib.h> #include<string.h> #define PI 3.14159 int main() {     int x,y,z;     char reciv[11];     while(1)     {         double dist,gallo_need;         scanf("%s",reciv);         if(strcmp(reciv,"ENDOFINPUT")==0)             break;         scanf("%d %d %d",&x,&y,&z);         scanf("%s",reciv)         if(z>180)         {             z=360-z;         }         dist=2*PI*x*z/360;         gallo_need=dist/5;         if(gallo_need>y)         {             printf("NO %d\n",y*5);         }         else             printf("YES %d\n",(int)(y-gallo_need));     }     return 0; }

能解释下吗？

gets(reciv); if (0==reciv[0]) continue;

gets, _getws Get a line from the stdin stream.  char *gets( char *buffer );  wchar_t *_getws( wchar_t *buffer );  Routine Required Header Compatibility  gets <stdio.h> ANSI, Win 95, Win NT  _getws <stdio.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns its argument if successful. A NULL pointer indicates an error or end-of-file condition. Use ferror or feof to determine which one has occurred.  Parameter  buffer  Storage location for input string  Remarks  The gets function reads a line from the standard input stream stdin and stores it in buffer. The line consists of all characters up to and including the first newline character ('\n'). gets then replaces the newline character with a null character ('\0') before returning the line. In contrast, the fgets function retains the newline character. _getws is a wide-character version of gets; its argument and return value are wide-character strings.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _getts gets gets _getws    Example  /* GETS.C */  #include <stdio.h>  void main( void ) {    char line[81];     printf( "Input a string: " );    gets( line );    printf( "The line entered was: %s\n", line ); }   Output  Input a string: Hello! The line entered was: Hello!   Stream I/O Routines  See Also   fgets, fputs, puts

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

代码AC了，不过是用的scanf，为什么scanf就不存在缓冲区的问题，scanf为什么不会把缓冲区的\n赋给reciv呢？

我把代码改成这样，虽然能正确输出，可是提交上去，提示ouput limint exceed，我这个程序是有break的，怎么会是死循环呢？ 还有那个fflush是什么意思呢？我知道他是清除缓冲区的，但是其中的原理不是太懂？ #include<stdio.h> #include<stdlib.h> #include<string.h> #define PI 3.14159 int main() {     int x,y,z;     char reciv[11];     while(1)     {         fflush(stdin);         int dist,gallo_need;         gets(reciv);         if(strcmp(reciv,"END")==0)             continue;         if(strcmp(reciv,"ENDOFINPUT")==0)             break;         scanf("%d %d %d",&x,&y,&z);         dist=2*PI*x*z/360;         gallo_need=dist/5;         if(gallo_need>y)         {             printf("NO %d\n",y*5);         }         else             printf("YES %d\n",y-gallo_need);     }     return 0; }

大哥，为什么呢？能解释下细节吗？

在gets()后加上fflush(stdin);  gets(reciv); fflush(stdin);


Question: 解析字符串

sscanf也可以啊，sprintf也可以啊

竟然不知道strtok

#include<stdio.h> #include<stdlib.h> #define MAX_P 4 char tmp[]="113421234123|435345345|675454545|78956456456"; int main(){ 	char *p[MAX_P]; 	char *t; 	int i=0,j; 	for(t=strtok(tmp,"|");t;t=strtok(NULL,"|")) p[i++]=t; 	for(j=0;j<i;++j) printf("p[%d]:%s\n",j,p[j]); 	return 0; }

LZ需要strtok

开头定义两个指针p1，p2，p2依次比较'|',相同则将p1-p2保存起来，然后将p2赋给p1，继续比较。

引用 3 楼 zhao4zhong1 的回复:strtok, wcstok, _mbstok Find the next token in a string.  char *strtok( char *strToken, const char *strDelimit );  wchar_t *wcstok( wchar_t *strToken, const wchar_t *strDelimit );  unsigned char *_mbstok( unsigned char*strToken, const unsigned char *strDelimit );  Routine Required Header Compatibility  strtok <string.h> ANSI, Win 95, Win NT  wcstok <string.h> or <wchar.h> ANSI, Win 95, Win NT  _mbstok <mbstring.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  All of these functions return a pointer to the next token found in strToken. They return NULL when no more tokens are found. Each call modifies strToken by substituting a NULL character for each delimiter that is encountered.  Parameters  strToken  String containing token(s)  strDelimit  Set of delimiter characters  Remarks  The strtok function finds the next token in strToken. The set of characters in strDelimit specifies possible delimiters of the token to be found in strToken on the current call. wcstok and _mbstok are wide-character and multibyte-character versions of strtok. The arguments and return value of wcstok are wide-character strings; those of _mbstok are multibyte-character strings. These three functions behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tcstok strtok  _mbstok  wcstok     On the first call to strtok, the function skips leading delimiters and returns a pointer to the first token in strToken, terminating the token with a null character. More tokens can be broken out of the remainder of strToken by a series of calls to strtok. Each call to strtok modifies strToken by inserting a null character after the token returned by that call. To read the next token from strToken, call strtok with a NULL value for the strToken argument. The NULL strToken argument causes strtok to search for the next token in the modified strToken. The strDelimit argument can take any value from one call to the next so that the set of delimiters may vary.  Warning   Each of these functions uses a static variable for parsing the string into tokens. If multiple or simultaneous calls are made to the same function, a high potential for data corruption and inaccurate results exists. Therefore, do not attempt to call the same function simultaneously for different strings and be aware of calling one of these function from within a loop where another routine may be called that uses the same function.  However, calling this function simultaneously from multiple threads does not have undesirable effects.  Example  /* STRTOK.C: In this program, a loop uses strtok  * to print all the tokens (separated by commas  * or blanks) in the string named "string".  */  #include <string.h> #include <stdio.h>  char string[] = "A string\tof ,,tokens\nand some  more tokens"; char seps[]   = " ,\t\n"; char *token;  void main( void ) {    printf( "%s\n\nTokens:\n", string );    /* Establish string and get the first token: */    token = strtok( string, seps );    while( token != NULL )    {       /* While there are tokens in "string" */       printf( " %s\n", token );       /* Get next token: */       token = strtok( NULL, seps );    } }   Output  A string   of ,,tokens and some  more tokens  Tokens:  A  string  of  tokens  and  some  more  tokens   String Manipulation Routines  See Also   strcspn, strspn, setlocalehttp://en.cppreference.com/w/c/string/byte/strtok

引用 6 楼 a461874693 的回复:[quote=引用 4 楼 my_live_123 的回复:]  str = tmp; p[0] = str; i = 1; while(*str) {          if(*str == '|') { +                 *str = 0; //把 | 换掉                    p[i++] = ++str;                    continue;           }           ++str; }  [/quote] 修正一下

引用 5 楼 xiadun 的回复:[quote=引用 4 楼 my_live_123 的回复:]  str = tmp; p[0] = str; i = 1; while(*str) {          if(*str == '|') {                    p[i++] = ++str;                    continue;           }           ++str; }   你这样输出不对 [/quote] 指向对应的地址，你的需求是什么？

char tmp[]="113421234123|435345345|675454545|78956456456"; 	char *p[4]; 	char* p1 = tmp, *p2 = NULL; 	int len = 0; 	for (int i = 0; i < 4;++i) 	{ 		p2 = p1 + len; 		p[i] = strtok(p2,"|"); 		len += strlen(p2) + 1 ; 	} 	for (int i = 0; i < 4; ++i) 	{ 		cout << p[i] << endl; 	} 	return 0;

引用 4 楼 my_live_123 的回复: str = tmp; p[0] = str; i = 1; while(*str) {          if(*str == '|') {                    p[i++] = ++str;                    continue;           }           ++str; }  你这个不是他想要的结果吧

引用 4 楼 my_live_123 的回复: str = tmp; p[0] = str; i = 1; while(*str) {          if(*str == '|') {                    p[i++] = ++str;                    continue;           }           ++str; }   你这样输出不对


Question: 关于Dijkstra算法求源节点到其余各个顶点的最短路径

你再往后翻翻，应该有floyd算法，数据结构书上一般都要讲这两个的！如果没有，自行搜素，关键字“floyd最短路径”

Dijkstra算法 http://blog.csdn.net/zhangxiangdavaid/article/details/38360337


Question: 这个怎么破？关于花括号的问题

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

我只想说，楼主用的编辑器太弱智

这是垃圾代码

引用 14 楼 mbctb 的回复:[quote=引用 10 楼 my_live_123 的回复:] [quote=引用 8 楼 mbctb 的回复:] [quote=引用 7 楼 my_live_123 的回复:] 如果使用的CB IDE，你可以设定常见的模板格式，而且也可以设定自己的风格 你说的是CB，是C++ Builder吗？[/quote] codeblack[/quote] codeblack能用于ＶＳ２００８吗？[/quote] 不是谁用谁的关系，二者都是IDE

引用 13 楼 mbctb 的回复:[quote=引用 12 楼 super_miker 的回复:] 16：9的显示器分两栏编辑应该挺舒服的，顺便我用的是notepad++ 分两栏编辑？怎么用？求指教。 [/quote] 在标签上点击“复制到另一视图”（notepad++，其他编辑器不知道）

引用 10 楼 my_live_123 的回复:[quote=引用 8 楼 mbctb 的回复:] [quote=引用 7 楼 my_live_123 的回复:] 如果使用的CB IDE，你可以设定常见的模板格式，而且也可以设定自己的风格 你说的是CB，是C++ Builder吗？[/quote] codeblack[/quote] codeblack能用于ＶＳ２００８吗？

引用 12 楼 super_miker 的回复:16：9的显示器分两栏编辑应该挺舒服的，顺便我用的是notepad++ 分两栏编辑？怎么用？求指教。

16：9的显示器分两栏编辑应该挺舒服的，顺便我用的是notepad++

如果使用的CB IDE，你可以设定常见的模板格式，而且也可以设定自己的风格

没有必要减少行数，某些公司员工还得故意增加行数应付kpi呢  可读性很重要

好像是微软的风格 for(int i = 0; i < 128; i ++) {     for(int j = 0; j < 25; j ++)     {         x = 0;     } } a ++;  ASCII风格 for(int i = 0; i < 128; i ++) {     for(int j = 0; j < 25; j ++)  {         x = 0;     } } a ++;  当循环内只有一条语句时简化风格 for(int i = 0; i < 128; i ++)     for(int j = 0; j < 25; j ++)         x = 0;  a ++;

for(int i = 0; i < 128; i ++){     for(int j = 0; j < 25; j ++){         x = 0;     } }  for(int i = 0; i < 128; i ++){ for(int j = 0; j <  25; j ++){     x = 0; }}

为了多看几行， 而导致代码可读性变低。 现实工作中最好不要这么做。  不过你可以使用这样的代码风格 for(int i = 0; i < 128; i ++){     for(int j = 0; j < 25; j ++){         x = 0;     } } 但令是减少了两行

反正屏宽，写一行算了 for(int i = 0; i < 128; i ++) for(int j = 0; j < 25; j ++) x = 0; // 或者 for(int i = 0; i < 128; i ++) for(int j = 0; j < 25; j ++) {       x = 0; }

for(int i = 0; i < 128; i ++) {     for(int j = 0; j < 25; j ++)     {         x = 0;     } } a ++ 这么写，错不了

引用 8 楼 mbctb 的回复:[quote=引用 7 楼 my_live_123 的回复:] 如果使用的CB IDE，你可以设定常见的模板格式，而且也可以设定自己的风格 你说的是CB，是C++ Builder吗？[/quote] codeblack

我只想说微软的VS系列编辑器基本都有Alt+F8自动排版的，当然仅限于格式异常不大的位置，要是全部都是乱的，估计也没辙。

引用 7 楼 my_live_123 的回复:如果使用的CB IDE，你可以设定常见的模板格式，而且也可以设定自己的风格 你说的是CB，是C++ Builder吗？


Question: c语言紧急作业，求大神帮助，给思路就可以！感谢不尽

cout<<hex<<*(long long *)&d<<' '<<*(int *)&f

首先， 实数也就是浮点数，可能是保存到double中也可能是float中。 那么你需要定义两种类型的变量接收这个浮点数。 然后，你需要理解数据在内存中都是以二进制保存。 （假设double是64bit，float是32bit, 并且是小端） 然后就有如下代码。 float val; cin>>val; double dVal=val;  int64  llValue = *(int64*)&dVal;        //保存到64bit的类型中 DWORD dwVal = *(DWORD*)&val; //保存到32bit类型中。  然后就可以取得  位与 得到每个bit的值是0还是1. 比如我要判断最低位是否为1，就是  if( (dwVal&0x00000001)==1) { }


Question: 求大神帮忙

谢谢大神回帖，主要是我做的程序就是用Matlab，导师不让调用c语言，那段程序我也没看太懂，所以在这儿求帮助，你要是有空就帮我编一下呗

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


Question: 请教如何安全的写入内存特定地址

写入某地址，是基于逻辑关系。  所以，根本不存在任意地址的安全写入。

IsBadWritePtr IsBadReadPtr

引用 3 楼 bios8086 的回复:楼上的好像是windows 的函数 要是我的不是windows 那？ 提醒：Linux是开源的。

你意思想修改可执行文件？

啥叫特定地址，内核没有提供给你的地址？ 在high level os中，直接访问地址是很危险的，你想读写特定地址就要很小心

啥叫安全？

引用 楼主 bios8086 的回复:	int* pMemory =(int *) 0x00400000; 	*pMemory = 2345;  这种不行。因为这个地址可能不能用。  假设我知道那段地址可用，比如0xffffffff-0x00401000 我知道这段可以 。 怎么写比较好 如果我不知道 那怎么用比较好呢？ 调用操作系统 先知道那段能读写？  我觉得是个原则问题吧，你自己申请的地址才能够写入，不说你自己申请的地址就不要写。虽然可以通过某些手段修改别的进程申请的地址

楼上的好像是windows 的函数 要是我的不是windows 那？

WriteProcessMemory The WriteProcessMemory function writes memory in a specified process. The entire area to be written to must be accessible, or the operation fails.   BOOL WriteProcessMemory(   HANDLE hProcess,  // handle to process whose memory is written to   LPVOID lpBaseAddress,                     // address to start writing to   LPVOID lpBuffer,  // pointer to buffer to write data to   DWORD nSize,      // number of bytes to write   LPDWORD lpNumberOfBytesWritten                      // actual number of bytes written );   Parameters hProcess  Handle to the process whose memory is to be modified. The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process.  lpBaseAddress  Pointer to the base address in the specified process to be written to. Before any data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for write access. If this is the case, the function proceeds; otherwise, the function fails.  lpBuffer  Pointer to the buffer that supplies data to be written into the address space of the specified process.  nSize  Specifies the requested number of bytes to write into the specified process.  lpNumberOfBytesWritten  Pointer to the actual number of bytes transferred into the specified process. This parameter is optional. If lpNumberOfBytesWritten is NULL, the parameter is ignored.  Return Values If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError. The function will fail if the requested write operation crosses into an area of the process that is inaccessible.   Remarks WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function. The process whose address space is being written to is typically, but not necessarily, being debugged.   The entire area to be written to must be accessible. If it is not, the function fails as noted previously.   Windows CE: The hProcess parameter is the handle returned from the OpenProcess function that provided full access to the process.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in winbase.h.   Import Library: Use kernel32.lib.  See Also Debugging Overview, Debugging Functions, ReadProcessMemory, WriteProcessMemoryVlm

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533  推荐使用WinHex软件查看或者改写（后果自负）硬盘或文件或内存中的原始字节内容。


Question: 如何学习C语言

我推荐郝斌的《C语言自学教程》和小甲鱼的《零基础学C语言》，这两套视屏都很好很详细，前者是郝斌老师的培训视屏，有180课，看似很多很吓人，其实每一课只有一个知识点，有些视屏只有两三分钟，所以真正的内容并不多。后者是小甲鱼出的，他的视屏都不错。大家选择其中的一套学习就行了。练习至关重要，我们要每天保证练习100行以上的程序，前期不会写，可以模仿、改写等。不多说了，全身心投入的话，3个月可以把C语言基础学的不错。


Question: 如何切换 Mac里面的clang为gcc ?

可以采用这个办法：  alias gcc=/usr/local/bin/gcc-4.9  g++同理。


Question: 初学c语言 想编一个rpc····求大神帮看看这啥错误····

谢谢iyomumx大师，是这个链接库

链接Rpcrt4.lib _T("字符串")

8	IntelliSense: "unsigned char *" 类型的实参与 "RPC_WSTR" 类型的形参不兼容 d:\documents\visual studio 2010\projects\helloworld\helloworld\server.c	18	28	hellowrd 9	IntelliSense: "unsigned char *" 类型的实参与 "RPC_WSTR" 类型的形参不兼容 d:\documents\visual studio 2010\projects\helloworld\helloworld\server.c	18	61	hellowrd   那这两个错误是怎么回事呢大师们

将错误信息中出现的标识符放在google里面搜一下，看其在哪个.lib中，然后在本地硬盘上搜索该.lib,如果没有，在网上搜索相关库或模块下载安装，然后将其所在目录填写到“附加依赖库所在目录”中，将其名字添加到“附加依赖库”中，重新连接。 VC6： 工程、设置、C/C++、分类：Preprocessor、附加包含路径：填写附加头文件所在目录 逗号间隔多项 工程、设置、Link、分类：Input、附加库路径：填写附加依赖库所在目录 分号间隔多项 工程、设置、Link、分类：Input、对象/库模块：填写附加依赖库的名字.lib 空格间隔多项 VS20xx： 项目、属性、C/C++、附加包含目录：填写附加头文件所在目录 分号间隔多项 项目、属性、链接器、常规、附加库目录：填写附加依赖库所在目录 分号间隔多项 项目、属性、链接器、输入、附加依赖项：填写附加依赖库的名字.lib 空格或分号间隔多项

楼主说的RPC俺不懂，但是这种RpcServerUseProtseqEp没有定义的问题，我猜测应该是楼主没有把相应的链接库放进工程里面 不管是VC还是GCC，都可以网上搜索一下如何添加动态链接库或静态链接库，当然还要查一下RPC的链接库是哪个


Question: 关于c语言程序进程管理的一个问题

TCHAR cmdline[] = TEXT(path); 楼主你的工程编译的是宽字符的还是单字符的，单字符的没问题，TCHAR跟char是一样的，但是宽字符的程序编译可不能这么转 如果真要用单字符转宽字符字符串，楼主查一下调用什么函数


Question: C 中单精度和双精度转换问题

引用 11 楼 feitianhu213 的回复:算了，我还是自己百度+谷歌好了。 百度＋谷歌 也不如 引用 3 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390676437  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？

算了，我还是自己百度+谷歌好了。

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 7 楼 super_miker 的回复:[quote=引用 6 楼 feitianhu213 的回复:] [quote=引用 5 楼 super_miker 的回复:] [quote=引用 2 楼 feitianhu213 的回复:] [quote=引用 1 楼 super_miker 的回复:] 这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。 可是为什么截断后会变大？不应该变小？如果上述改为：float fa = 1000000000.000000(比 a 多一位) 则可以正常显示，为什么呢？[/quote]  没有人规定截断一定要往下截的，可以往上截、往下截、往零截和往偶数截。。。[/quote] 截断不是去掉一些位吗？既然去掉了，无论是去掉那个位，不应该变小？既然可以表示 1,000,000,000 为什么不可以表示更小的 345,122,907 ? [/quote]  就算是十进制也有四舍五入这种说法你该不会是不知道吧[/quote] 可不可以说的详细点？

引用 6 楼 feitianhu213 的回复:[quote=引用 5 楼 super_miker 的回复:] [quote=引用 2 楼 feitianhu213 的回复:] [quote=引用 1 楼 super_miker 的回复:] 这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。 可是为什么截断后会变大？不应该变小？如果上述改为：float fa = 1000000000.000000(比 a 多一位) 则可以正常显示，为什么呢？[/quote]  没有人规定截断一定要往下截的，可以往上截、往下截、往零截和往偶数截。。。[/quote] 截断不是去掉一些位吗？既然去掉了，无论是去掉那个位，不应该变小？既然可以表示 1,000,000,000 为什么不可以表示更小的 345,122,907 ? [/quote]  就算是十进制也有四舍五入这种说法你该不会是不知道吧

引用 5 楼 super_miker 的回复:[quote=引用 2 楼 feitianhu213 的回复:] [quote=引用 1 楼 super_miker 的回复:] 这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。 可是为什么截断后会变大？不应该变小？如果上述改为：float fa = 1000000000.000000(比 a 多一位) 则可以正常显示，为什么呢？[/quote]  没有人规定截断一定要往下截的，可以往上截、往下截、往零截和往偶数截。。。[/quote] 截断不是去掉一些位吗？既然去掉了，无论是去掉那个位，不应该变小？既然可以表示 1,000,000,000 为什么不可以表示更小的 345,122,907 ?

引用 8 楼 feitianhu213 的回复:[quote=引用 7 楼 super_miker 的回复:] [quote=引用 6 楼 feitianhu213 的回复:] [quote=引用 5 楼 super_miker 的回复:] [quote=引用 2 楼 feitianhu213 的回复:] [quote=引用 1 楼 super_miker 的回复:] 这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。 可是为什么截断后会变大？不应该变小？如果上述改为：float fa = 1000000000.000000(比 a 多一位) 则可以正常显示，为什么呢？[/quote]  没有人规定截断一定要往下截的，可以往上截、往下截、往零截和往偶数截。。。[/quote] 截断不是去掉一些位吗？既然去掉了，无论是去掉那个位，不应该变小？既然可以表示 1,000,000,000 为什么不可以表示更小的 345,122,907 ? [/quote]  就算是十进制也有四舍五入这种说法你该不会是不知道吧[/quote] 可不可以说的详细点？[/quote] 比如0.4四舍五入之后变成0，0.5四舍五入之后变成1

引用 2 楼 feitianhu213 的回复:[quote=引用 1 楼 super_miker 的回复:] 这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。 可是为什么截断后会变大？不应该变小？如果上述改为：float fa = 1000000000.000000(比 a 多一位) 则可以正常显示，为什么呢？[/quote]  没有人规定截断一定要往下截的，可以往上截、往下截、往零截和往偶数截。。。

直接看二进制好了，红色部分就是尾数，float只有23位，你自己数一下 0100000110110100100100100010100001011011000000000000000000000000

引用 1 楼 super_miker 的回复:这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。 可是为什么截断后会变大？不应该变小？如果上述改为：float fa = 1000000000.000000(比 a 多一位) 则可以正常显示，为什么呢？

这不是很正常的精度损失吗，float型无法表达这么多位所以进行截断。。。


Question: 求帮助，用C写程序为何这么费力？

慢慢提升，读一下linux编程的基础书。

非常感谢 赵老师的回复和帮助！ 我还要花些时间消化您说的gdb的调试方法。 再次感谢！

使用越不费力的开发语言或各种语法糖写程序，编译调试查错越苦！ 出来混，迟早是要还的。

用C写程序越费力，C程序员的竞争对手越少，薪资越高。  楼主的关键问题还是不精通各种调试手段＋懒。  进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令  watch 表达式：设置一个监视点，一旦被监视的“表达式”的值改变，gdb将强行终止正在被调试的程序。如： watch a 在gdb中，有以下几种暂停方式：断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)及线程停止(Thread Stops)。 为断点设置一个条件，可使用if关键词，后面跟其断点条件。并且，条件设置好后，可以用condition命令来修改断点的条件(只有break和watch命令支持if，catch目前暂不支持if)。  有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中  理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

谢谢你的评论，不过能否请你详细的说一说我哪些能力有待提高？

因为你水平低。


Question: 如果一个常量大于int所能表示的范围，需要用它作为循环的终止条件怎么办？

引用 7 楼 xiaohuh421 的回复:编写程序的时候， 你就需要考虑到溢出的问题。 不管你使用多大的数据类型，都是需要考虑的。 不然， 你以为“千年虫”是怎么发生的。 您说的对。

引用 6 楼 mewiteor 的回复:[quote=引用 5 楼 rockpk008 的回复:] [quote=引用 2 楼 mewiteor 的回复:] 至于3和0FB397A74，你打开计算器，选择程序员模式，输入17099750004，切换到16进制，一看就明白了。  是的用了long long Int就没有问题了。我想问一下，方框中的汇编，为什么要这样比较呢？[/quote] 比较大小要从高位比起，这里相当于2的32次方进制的数比较大小，对于17099750004转化成2的32次方进制的数就是 (3,0FB397A74)2^32 所以就是先比高位3,再比低位0FB397A74。[/quote]  多谢指点

引用 5 楼 rockpk008 的回复:[quote=引用 2 楼 mewiteor 的回复:] 至于3和0FB397A74，你打开计算器，选择程序员模式，输入17099750004，切换到16进制，一看就明白了。  是的用了long long Int就没有问题了。我想问一下，方框中的汇编，为什么要这样比较呢？[/quote] 比较大小要从高位比起，这里相当于2的32次方进制的数比较大小，对于17099750004转化成2的32次方进制的数就是 (3,0FB397A74)2^32 所以就是先比高位3,再比低位0FB397A74。

引用 2 楼 mewiteor 的回复:至于3和0FB397A74，你打开计算器，选择程序员模式，输入17099750004，切换到16进制，一看就明白了。  是的用了long long Int就没有问题了。我想问一下，方框中的汇编，为什么要这样比较呢？

使用一楼的方法试一试

在现实世界中，除时间和空间可能是无限的以外，其它任何事物都是有限的。

c语言中，有一种数据类型是long long,它是64位的，占8个字节。 c语言中，还有一个头文件是stdint.h，里面有1、2、4、8个字节的有/无符号整数类型。


Question: buf[tnum++] = 0x0d; 是先取tnum的值，再加1吗？

int i = 10; 00C595FE  mov         dword ptr [i],0Ah   	int num = i++; 00C59605  mov         eax,dword ptr [i]   00C59608  mov         dword ptr [num],eax   00C5960B  mov         ecx,dword ptr [i]   00C5960E  add         ecx,1   00C59611  mov         dword ptr [i],ecx     	int i = 10; 000795FE  mov         dword ptr [i],0Ah   	int num = ++i; 00079605  mov         eax,dword ptr [i]   00079608  add         eax,1   0007960B  mov         dword ptr [i],eax   0007960E  mov         ecx,dword ptr [i]   00079611  mov         dword ptr [num],ecx

是的，先引用后增值

++有两种， 一种在前面： ++k，一种在后面： k++，它们应该看作是两种完全不同的操作符。 +=，与它们没有可比性。

引用 4 楼 mbctb 的回复:[quote=引用 3 楼 user-5 的回复:] [quote=引用 2 楼 mbctb 的回复:] 更进一步的，我想问：  buf[tnum +＝ 2] = 0x0d;  是不是相当于： buf[tnum] = 0x0d; tnum += 2; 这个倒不是了，这个是这样的 tnum += 2; buf[tnum] = 0x0d; 所以++和--是比较奇葩的，其实具体你可以写个小程序看反汇编就知道了。[/quote] 好的，非常感谢！[/quote] 客气了，同学，共同探讨，共同研究，共同进步！

引用 3 楼 user-5 的回复:[quote=引用 2 楼 mbctb 的回复:] 更进一步的，我想问：  buf[tnum +＝ 2] = 0x0d;  是不是相当于： buf[tnum] = 0x0d; tnum += 2; 这个倒不是了，这个是这样的 tnum += 2; buf[tnum] = 0x0d; 所以++和--是比较奇葩的，其实具体你可以写个小程序看反汇编就知道了。[/quote] 好的，非常感谢！

引用 2 楼 mbctb 的回复:更进一步的，我想问：  buf[tnum +＝ 2] = 0x0d;  是不是相当于： buf[tnum] = 0x0d; tnum += 2; 这个倒不是了，这个是这样的 tnum += 2; buf[tnum] = 0x0d; 所以++和--是比较奇葩的，其实具体你可以写个小程序看反汇编就知道了。

是这样的，如果++在前面，那么就把你写的那个顺序反一下。


Question: 关于fwrite函数

跟大小端无关，3楼是对的。

大小端----字节序.. 网络字节序：大端   big-endian, 这是网络传输协议中规定采用的字节序 主机字节序：跟据主机而定,  可能是 大端与可能是小端  little-endian  htons(), ntohs().  等系列函数将主机字节序与网络字节序(大端)相互转换 如果楼主想  fwrite 到文件 时保持跟  输入 时看到的一样   packet = htons(packet); // 转换成    (大端---大尾序---网络序---be序----------  N多种叫法 fwrite (&packet, 2, 1, pFile1);  当fread 时 也要做相应的转换   ntohs() ,  转换回主机字节序  // -------------------------------------------- htons(), ntohs().  等系列函数 在 windows 中头文件好像是  winscok.h,  需要添加   ws2_32.lib linux 在 arpa/inet.h ..... 具体可查资料.

刚按照二楼所说的百度了一下，只是大小端这种问题可以改变吗？比如我现在是小端如何改为大端呢

第一张图片上面的下标是0 和1 第二张图片，按照人类可读方式，按字节从右向左，因此还是和第一张保持一致的

引用 1 楼 dooX8086 的回复:整数packet ? 这个是 short packet  ？ 大小端问题: short packet  = 0x0ffc;  小端 :  fc  0f 大端:  0f  fc  详细可搜索:  内存 大小端  求教，这要怎么改代码呢？


Question: 新人求助。

malloc realloc free

也觉得你应该调试一下看看问题在哪。 另外，那个冒泡排序难道不是  for(int i=0; i<N; i++) for(int j = 0; j<N-i; j++) ... 么？ 我也是新手

调试一下看看哪里出问题

引用 1 楼 FightForProgrammer 的回复:调试一下看看哪里出问题  原来调试以后是这样的……感觉就没读入数字……输出的是未初始化的随机值?

引用 4 楼 user-5 的回复:你是在读取之后才为它分配内存的，这不行。。。 i初始值应为0. 主要是想让这个排序算法能够自动分配内存空间……所以……如果人为分配的话，还要靠人去数出个数，感觉并不是很好……所以……

引用 4 楼 user-5 的回复:你是在读取之后才为它分配内存的，这不行。。。 i初始值应为0. 一开始我是想把i初始化0的，但是后面发现如果我要用在数组里，如果i=0，第一次读取一个数据以后，想要扩大数组……就无法实现了，因为我是用i*sizeof(int)，这个时候还是原来的大小（i++后i=1）,所以我就想是不是从1开始……把0那个空出来……

修改如下  int main(void) { 	int *n; 	int i = 1, t; 	if ((n = (int*)malloc(sizeof(int))) == NULL) 	{ 		printf("Not able to allocate memory.\n"); 		exit(1); 	} 	while (scanf_s("%d", &n[i - 1], 1))  //这里是i-1 	{ 		i++; 		if ((n = (int*)realloc(n, i*sizeof(int))) == NULL) 		{ 			printf("Not able to allocate memory.\n"); 			exit(1); 		} 		//n = (int*)realloc(n, i*sizeof(int));   //这句不要 	} 	//其它…… 	return 0; }

你是在读取之后才为它分配内存的，这不行。。。 i初始值应为0.


Question: 关于函数中传参的名称

引用 17 楼 xiaohuh421 的回复:[quote=引用 16 楼 zhao4zhong1 的回复:] 别急着++,在64位系统上编译链接调试看看结果吧。  赵老师教训得是。  代码的正确性可能有待考证， 但思路还是可行的。[/quote] 64位上，前几个参数默认是通过寄存器传递的。

当然你定义函数的时候，不写名字，函数内你不能直接用不上了，但是可以间接方式，使用内联汇编取出函数参数的值 像这样  #include <stdio.h> #include <stdlib.h>  void fun(int a, int b) { 	unsigned int i, j; 	long ret;  #if 1 	asm volatile ( 			"movl 12(%%ebp), %%eax\n\t"//参数b 			"movl 8(%%ebp), %%ebx\n\t" //参数a 			"movl 4(%%ebp), %%ecx\n\t" //ret 			:"=a"(i), "=b"(j), "=c"(ret) 			:); 	printf("p2 = %x; p1 = %x; ret = %p\n", i, j, ret); #endif }  int main(int argc, char *argv[]) { 	fun(1, 2); 	exit(0); }

函数声明的时候可以只给出参数类型，不给出变量名。 但在定义的时候，如果也不给出变量名，一般情况下则无法使用该变量

引用 16 楼 zhao4zhong1 的回复:别急着++,在64位系统上编译链接调试看看结果吧。  赵老师教训得是。  代码的正确性可能有待考证， 但思路还是可行的。

引用 11 楼 xiaohuh421 的回复:[quote=引用 10 楼 kkk2017 的回复:] void foo(int,int) { 	int myparam[1]; 	int *pmyp=myparam; 	printf("myparam0=%d,myparam1=%d\n",*((int*)pmyp+4),*((int*)pmyp+5)); }  int _tmain(int argc, _TCHAR* argv[]) { 	foo(56,45); 	return 0; } ++[/quote] 别急着++,在64位系统上编译链接调试看看结果吧。

引用 5 楼 a461874693 的回复:既然要用到形参，为什么要省略它的名字呢，加一个能表示它作用的形参名不更好吗 我觉得c居然可以这样写，应该有他的道理，可能在什么情况下会用得到

嗯，我的意思是这样写什么含义，我认为你没有名称根本就用不了这个参数，但是我听别人说可以用指针对其进行操作，就是不知道这里怎么做

引用 10 楼 kkk2017 的回复:void foo(int,int) { 	int myparam[1]; 	int *pmyp=myparam; 	printf("myparam0=%d,myparam1=%d\n",*((int*)pmyp+4),*((int*)pmyp+5)); }  int _tmain(int argc, _TCHAR* argv[]) { 	foo(56,45); 	return 0; }  什么意思呀

引用 20 楼 zhao4zhong1 的回复:64位上，前几个参数默认是通过寄存器传递的。  原来如此， 谢谢赵老师指点。

void foo(int ,int ); //这里可以没有形参名 int main void){ foo(56,45); return 0; } void foo(int a, int b){ 这里使用a，b }

如果你传进去的参数没有使用foo（）参数里面想写几个，写几个，当然不写最省事，既然要用，没形参，怎么使用实参的值。支持1，2楼

引用 10 楼 kkk2017 的回复:void foo(int,int) { 	int myparam[1]; 	int *pmyp=myparam; 	printf("myparam0=%d,myparam1=%d\n",*((int*)pmyp+4),*((int*)pmyp+5)); }  int _tmain(int argc, _TCHAR* argv[]) { 	foo(56,45); 	return 0; } ++

引用 6 楼 xiaohuh421 的回复:void foo(int ,int ){   ...... } 这里没有变量名, 一般方式就没办法用了. 当然, 这种情况你可以通过内嵌汇编来访问这两个变量,  但是SB才会在这种情况下用内嵌汇编. 不是SB，是ZB！

楼主不是逗吗？想使用传进去的变量竟然需要加变量名  声明的时候可以不加，或者使用与定义时不一样的变量名字

《汇编语言》 -- 王爽 “综合研究部分 -- 不定参函数实现机制”

既然要用到形参，为什么要省略它的名字呢，加一个能表示它作用的形参名不更好吗

引用 1 楼 wwwboyxa 的回复:hehe 函数声明时可以这样，函数定义时不能这样  #include <iostream> using namespace std; int foo(int, int) { 	return 5; }  int main() { 	cout << foo(10,20) << endl; 	return 0; } 定义写成这样并不会报错

支持上面两位


Question: 按键扫描程序

这要根据实际电路来理解，搜索4*4矩阵键盘。

这个应该是4*4的键盘 所以先扫X行，对应端口P1.0-P1.3 接着再扫Y列，对应端口P1.4-P1.7 最终得出键值。

AD转换的精度是什么意思？

这个得计算AD转换的精度，

在百度图片中搜“键盘扫描电路”


Question: gcc 参数

-l是一个单独的参数，表示要链接后面紧跟着的库，在这里就是要链接nsl.a 类似的例子： gcc -lpthread test.c

1.man gcc 2.gcc在线手册 http://tps://gcc.gnu.org/onlinedocs/5.1.0/

man gcc

gcc -v --help

gcc --help


Question: 这个表达式怎么理解？for(int j = 0, have = 1; j < num; j++)

#7   正解!

引用 5 楼 mbctb 的回复:[quote=引用 4 楼 hhhhhhhhhhkkkkkkkkkk 的回复:] 那个int j=0,have=1;就是一个变量声明语句而已。这是c++的风格。标准C没有。  这表示什么？是定义int j，再改变已有变量have的值，而不是定义新变量have？[/quote] 不是，定义了j和have这两个变量，都是int型的，同时为他们赋了初始值。

C99从C++引入的新特性 1.定义循环变量 2.作用域据域仅在for循环体 3.不算赋值表达式，算初始化

int j=0,have=1;等于int j=0;int have=1;int j=0,have=1;这样写方便，是C++的基础语法

引用 4 楼 hhhhhhhhhhkkkkkkkkkk 的回复:那个int j=0,have=1;就是一个变量声明语句而已。这是c++的风格。标准C没有。  这表示什么？是定义int j，再改变已有变量have的值，而不是定义新变量have？

这个事典型的c++生命语句。

随用随声明是C++语法。

for的第一部分可以是变量声明也可以是表达式，在这个例子中是声明。 int直到分号前都有效。


Question: 【数据结构】求两个表的并集

根据你的代码，简单修改，仅供参考  #include<stdio.h> #include<stdlib.h> typedef struct Node{ 	int element; 	struct Node * Next; }* List;   //初始化 List initList(){ 	List L; 	L = (List)malloc(sizeof(Node));//List只是一个指针，这里申请的内存大小应为Node的大小 	if(L == NULL){ 		printf("fail"); 	}else{ 		L->Next =NULL; 	} 	return L; }  void destoryList(List L) { 	List temp; 	while(L) 	{ 		temp=L; 		L=L->Next; 		free(temp); 	} }  void Push(List L,int ele){ 	for(List t=L->Next;t!=NULL;t=t->Next) 	{ 		if(t->element==ele) 		{ 			return; 		} 	} 	List P,temp; 	P = (List)malloc(sizeof(Node)); 	P->element = ele; 	P->Next =NULL; 	temp=L; 	while (temp->Next!=NULL) 	{ 		temp=temp->Next; 	} 	temp->Next=P; }  int Pop(List L){ 	List temp; 	int e; 	temp = L->Next; 	e = temp->element; 	L->Next = temp->Next; 	free(temp); 	return e; }  int isEqual(int m,int n){ 	return m == n ; }  int isEmpty(List L){ 	return L->Next == NULL; }  //求两个表的并集 List Union(List L1,List L2){ 	List newList=initList(); 	for(List temp1=L1->Next;temp1!=NULL;temp1=temp1->Next) 	{ 		Push(newList,temp1->element); 	} 	for(List temp2=L2->Next;temp2!=NULL;temp2=temp2->Next) 	{ 		Push(newList,temp2->element); 	} 	return newList; }  //打印输出 void printList(List L){ 	List temp; 	temp = L->Next;  	if(!isEmpty(L)){ 		while(temp!=NULL){ 			printf("%3d",temp->element ); 			temp = temp->Next; 		} 	}else{ 		printf("Empty List"); 	} 	return ; }  int main(){ 	List L1,L2,L3; 	int i,j; 	L1 = initList(); 	L2 = initList(); 	for(i=0;i<5;i++){ 		Push(L1,i+1);//L1是{1,2,3,4,5} 		Push(L2,i+3);//L2是{3,4,5,6,7} 	} 	L3 = Union(L1,L2);//L1和L3的并集应该是{1,2,3,4,5,6,7} 	printList(L3); 	destoryList(L1); 	destoryList(L2); 	destoryList(L3); }

List tempCell; 这个指针没有分配地址，这代码逻辑上有点问题，如果两个list第一个元素不等，就无法退出了

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //


Question: C:打印字符数组的问题

初始化下AdapterList应该就可以了！memset(AdapterList,0,sizeof(AdapterList)); 同理，你声明的其它数组或变量最好也初始化一下！


Question: 已处理好的数据存在矩阵中，用该矩阵成像问题

float是16位 double是32位


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


Question: 音频fft取点问题

我和你在这方面知道的一样多。 在百度或百度图片搜“音频FFT”

引用 3 楼 zhao4zhong1 的回复:0..1023 1024..2047 2048..3071 3072..4095 ...如果这样取n个1024段，那么是不是就得到了n个频谱图了？老师能不能留个qq交流下，拜托了

引用 1 楼 zhao4zhong1 的回复:连续取。 频谱是随时间变化的。 推荐学习使用Audition软件。您好，那么请问下频谱随时间变化应该是怎么变的呢？就是所取的1024个点在时间轴上依次滑动吗？应该以怎样的速率华东呢？

连续取。 频谱是随时间变化的。 推荐学习使用Audition软件。


Question: Linux 时间 日期

sleep(24 * 60 * 60); A();

还是不算很明白，希望大家帮忙啊。~~~~

执行A程序，只需要捕捉SIGALRM信号即可

1.定时  #include <unistd.h> unsigned int alarm(unsigned int seconds); Returns: 0 or number of seconds until previously set alarm   2.设置时间  #include <sys/time.h> int clock_settime(clockid_t clock_id, const struct timespec *tsp);

参考crontab命令

先使用sigaction或者signal设置到达时间时执行的函数, 然后 #include <unistd.h> unsigned int alarm(unsigned int seconds);

启动时记录下时间，起一个定时器，定时检测是否到24小时。 到了就执行你要的工作。 时间可以直接用time_t的格式，以秒为单位相减。

不想写代码就用crontab  或者用libevent也行，轮询的方式要不得精度低，耗资源

引用 4 楼 a30037338 的回复: #inclue"time.h" 	time_t t; 	time( &t); 	struct tm* starttime = localtime(&t); 	 ... 	time(&t); 	struct tm *endtime = localtime(&t); 	if(endtime->tm_hour - 24 == starttime->tm_hour) 	{ 		time( &t); 		struct tm* starttime = localtime(&t); 		func(); 	}    这样做感觉要专门用一个线程来处理时间吧，一直在获取本地时间才可以  有其他的方式没有啊。


Question: 强制类型转换必须加括号吗？

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

这是C++中的写法  UCHAR(........)  目前的标准，C语言中要加括号


Question: 关于scanf()的一些小疑问

7楼解释出了本质，其实char和int可以互相转换，在编译时只是警告，并不会出错，而char在内存中占1个字节，int占2个或者4个（与编译器有关），按4位看，第二个输入的int型覆盖了第一个的底24位，只留下高8位8个0，而后面的24为全部存储了。

引用 9 楼 JackXJack 的回复:我对这道题目的理解是：a,b,c,d定义为字符型变量，但字符型变量也对应着ASCLL码。a读取6，b读取5，c读取65，d读取66，打印输出65和66对应的字符A和B。但是6和5这个关系我搞不清楚，开头定义的int，到scanf()里面又出现了%c，应该是ASCLL码6和5对应的字符。。。我凌乱了 你scanf用%c读的a,b;printf时也用的%c，所以打出来就是字符'6','5';如果printf("%d,%d",a,b);打出来就是‘6’，‘5’的ASCLL值54，53

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 8 楼 JackXJack 的回复:[quote=引用 7 楼 dooX8086 的回复:]  // --------------------------- //这跟你发的帖子不一样。这里是正常输入  //------------------------------------------------------- scanf 不是会检查被写入的地址, 它只会根据格式控制符，往里写数据。 scanf %c --->&a : 根据格式控制符 %c 读取到的是一个  '6' 字符，ascii 码是 54, 而不是数值 6 写入数据: a  | 54 | -- | -- | -- |  ,还有3个 byte 空闲  变量b 也是一样...  如果把 printf 改成 printf("%d, %d, %c, %c\n", a, b, c, d); //结果是想像中的  ??? 54, 53, A, B  如果是 debug 版会是这个结果，但如果 release版... .那就是不一定能输出 变量 a:54   b:53 的值了 因为 int a, b ...   没有初始化...

引用 7 楼 dooX8086 的回复:溢出写入... scanf 不是会检查被入的址的. scanf %d ---->&a  :  从地址 &a 这里开始根据格式控制符%d的要求, 写入 4 个字节..  如:char a, b 在栈中的排列一般为, (不同编译器会有所不同) |0x 低位-------------------------------------->| 高位 |----------&b[1 byte]|&a[ 1 byte]-----------|  如果是 scan %d ----> &b , 即从&b开始写入4个byte---->将覆盖 a 各其后面的 3 个 byte  如写一段这样的测试  #include <stdio.h>  int main(int argc, char *argv[]) {  	char at[4] = {0}, a=0, b=0;  	scanf("%x", &b); 	 	printf(" a:%x,  b:%x\n", a, b); 	printf("at:%x\n", *((int *)at));  	return 0; }  // 输入  abcd1234  // 在小端环境中 // 结果有可能是   a:12,  b:34 at:abcd  // 也有可能是 a:0, b:34 at:0 /// 然后报错... 等行为. ///  // 在大端环境中 // 可能是 a:cd, b:ab at: 1234 // 有点头晕.... // .... //....   // 溢出其结果是(行为)不确定的，有依赖其环境(只要是编译器) // 所以不要纠结其结果， // 所以溢出的 bug 也是狠难查的...d写的太深刻了，不明觉厉啊！！！非常感谢您的回答！我之所以附上两张图是由一道题目启发的，大神若有空可帮我看看这道题目，后面输出A和B我理解，但是我不知输出6和5的原因。。。希望您能赐教！

你单步跟一下看看内容

好像说的看错了，忽略我上面说的。

引用 3 楼 haitunxiaomo 的回复:第二种你把地址符去掉试试看。输入字符的时候一般使用地址符的。试了，程序停止工作

第二种你把地址符去掉试试看。输入字符的时候一般使用地址符的。

我的问题：scanf()函数要按照变量的数据类型指定与该数据类型相匹配的格式字符，但上图中scanf()内的数据类型和最开始指定的数据类型不匹配，不应该是相当于遇到非法字符吗？请各位具体地解释一下上面两种情况，尤其是第二种情况，拜谢各位！


Question: 程序线程数的奇怪问题

9个线程怎么了？   0个线程怎么样？

Hook CreateThread ?


Question: 想用define来定义一个函数，该如何定义？

引用 2 楼 zhao4zhong1 的回复:#define rt_WM_GetDialogItem return(WM_GetDialogItem(WM_HWIN hItem, int id))  感谢赵老师

引用 4 楼 todo9351 的回复:[quote=引用 1 楼 biao1990 的回复:] #define  FUN(a,b)  return WM_GetDialogItem(a,b)   这样吗？  不能这样 define  #define FUNC(a, b)   WM_GetDialogItem(a,b)  这样就可以了[/quote]  感谢。有点不熟练

不是你那样直接return的，需要在define的函数名后面加上函数内的操作啊……不然要这个函数宏做什么用呢？你说对不

这不是把大炮当成鸟枪用了吗？

引用 1 楼 biao1990 的回复:#define  FUN(a,b)  return WM_GetDialogItem(a,b)   这样吗？  不能这样 define  #define FUNC(a, b)   WM_GetDialogItem(a,b)  这样就可以了


Question: 新手问个很小白的问题~

请判断每个函数的返回值。 请关闭防火墙、UAC、杀毒软件 请用Administrator用户登录 ……

权限不够吧，根据编译环境 + UAC设置 到百度上去搜

因为会被自动映射到另一个路径. 看完这个,你应该知道 http://blog.csdn.net/aastoneaa/article/details/7885634

自己顶一下.....有知道的吗？拜托给新人讲讲........

引用 1 楼 fly_dragon_fly 的回复:微软错了 Mircosoft  好吧，，，改过来以后为什么开机成功启动了而注册表里仍然没有？

微软错了 Mircosoft


Question: linux  下用 C  修改IP配置文件 写的时候文件内容丢失

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


Question: 请教sprintf的用法，为什么这段程序会运行崩溃

引用 10 楼 newerC 的回复:char c[] 极端情况需要能表示"255.255.255.255"这种IP地址，字符长度共 3+1+3+1+3+1+3 = 15 所以c至少需要申明为char c[15+1]正解！！！

看懂返回值 Return value “Upon successful return, these functions return the number of characters printed (not including the trailing '\0' used to end output to strings).”

数组越界

sprintf第一个参数是字符串类型的好不好，你那里整型肯定不行，自己百度一下sprintf的用法

引用 7 楼 a1232345 的回复:[quote=引用 4 楼 u014749886 的回复:] char c[8]  不够用啊，最起码也得  至少也得16吧 请问这个16是怎么看出来的，大小是看最后形成的字符串大小吗？，4个%u = 16，但不是还有几个点吗，应该是20 吧？[/quote] 有那个时间掰指头计算长度，还不一定计算正确，为什么不略微多定义几个字符保证其够用呢？

引用 4 楼 u014749886 的回复:char c[8]  不够用啊，最起码也得  至少也得16吧 请问这个16是怎么看出来的，大小是看最后形成的字符串大小吗？，4个%u = 16，但不是还有几个点吗，应该是20 吧？

搜“编译器 堆栈检查”

引用 4 楼 u014749886 的回复:char c[8]  不够用啊，最起码也得  至少也得16吧 为什么我改成char c[20](4个int+4个'.')，编译运行可以了。但是gcc的时候加上-g就报错了了？

char c[8]  不够用啊，最起码也得  至少也得16吧

栈溢出了，试给程序多分配一些栈空间。

PRINTF Section: Linux Programmer's Manual (3 ) Updated: 2000-10-16  --------------------------------------------------------------------------------    NAME printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - formatted output conversion    SYNOPSIS #include <stdio.h>  int printf(const char *format, ...);  int fprintf(FILE *stream, const char *format, ...);  int sprintf(char *str, const char *format, ...);  int snprintf(char *str, size_t size, const char *format, ...);   #include <stdarg.h>   int vprintf(const char *format, va_list ap);  int vfprintf(FILE *stream, const char *format, va_list ap);  int vsprintf(char *str, const char *format, va_list ap);  int vsnprintf(char *str, size_t size, const char *format, va_list ap);     DESCRIPTION The functions in the printf family produce output according to a format as described below. The functions printf and vprintf write output to stdout, the standard output stream; fprintf and vfprintf write output to the given output stream; sprintf, snprintf, vsprintf and vsnprintf write to the character string str.  The functions vprintf, vfprintf, vsprintf, vsnprintf are equivalent to the functions printf, fprintf, sprintf, snprintf, respectively, except that they are called with a va_list instead of a variable number of arguments. These functions do not call the va_end macro. Consequently, the value of ap is undefined after the call. The application should call va_end(ap) itself afterwards.   These eight functions write the output under the control of a format string that specifies how subsequent arguments (or arguments accessed via the variable-length argument facilities of stdarg(3)) are converted for output.     Return value Upon successful return, these functions return the number of characters printed (not including the trailing '\0' used to end output to strings). The functions snprintf and vsnprintf do not write more than size bytes (including the trailing '\0'). If the output was truncated due to this limit then the return value is the number of characters (not including the trailing '\0') which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated. (See also below under NOTES.) If an output error is encountered, a negative value is returned.

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令


Question: 关于双线程并发的问题

引用 楼主 u014524569 的回复:简单的程序代码（Linux下）： #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<pthread.h>  #define THREAD_NUMBER 2	 int retval_hello1=2,retval_hello2=3;  void* hello1(void *arg) { 	int i,sum=0; 	char * hello_str=(char *)arg; 	//sleep(1); 	printf("%s\n",hello_str); 	printf("%s\n",hello_str); 	printf("%s\n",hello_str); 	printf("%s\n",hello_str); 	/*for(i=0;i<1000;i++){ 		sum+=i; 	} 	printf("sum1=%d\n",sum);*/ //sleep(1); printf("%s\n",hello_str); printf("%s\n",hello_str); printf("%s\n",hello_str); printf("%s\n",hello_str); 	pthread_exit(&retval_hello1); }  void* hello2(void *arg) { 	int i,j,x=0,sum=0; 	char * hello_str=(char *)arg; 	//sleep(2); 	printf("%s\n",hello_str); 	printf("%s\n",hello_str); 	printf("%s\n",hello_str); 	printf("%s\n",hello_str); 	//sum+=1; 	//printf("sum2=%d\n",sum); for(i=0;i<100;i++){ 	for(j=0;j<100;j++){ 		x++; 		sum+=x; 		} 	} 	printf("sum2=%d\n",sum); printf("%s\n",hello_str); printf("%s\n",hello_str); printf("%s\n",hello_str); printf("%s\n",hello_str); 	pthread_exit(&retval_hello2); }  int main(int argc,char * argv[]) { 	int i; 	int ret_val; 	int * retval_hello[2]; 	pthread_t pt[THREAD_NUMBER]; 	const char * arg[THREAD_NUMBER]; 	arg[0]="hello world from thread1"; 	arg[1]="hello world from thread2"; 	printf("Begin to create threads..\n");  	ret_val=pthread_create(&pt[0],NULL,hello1,(void*)arg[0]); 	if(ret_val!=0) 	{ 		printf("pthread_create erro!\n"); 		exit(1); 	} 	ret_val=pthread_create(&pt[1],NULL,hello2,(void*)arg[1]); 	if(ret_val!=0) 	{ 		printf("pthread_create erro!\n"); 		exit(1); 	} 	 	printf("Now,the main thread returns.\n"); 	printf("Begin to wait for threads..\n"); 	for(i=0;i<THREAD_NUMBER;i++){ 		ret_val=pthread_join(pt[i],(void * *)&retval_hello[i]); 		if(ret_val!=0){ 			printf("pthread_join error!\n"); 			exit(1); 		} 		else{ 			printf("return vlaue is %d\n",* retval_hello[i]); 		} 	} 	 	/*ret_val=pthread_join(pt[1],(void * *)&retval_hello[1]); 	printf("return vlaue is %d\n",* retval_hello[1]);  	ret_val=pthread_join(pt[0],(void * *)&retval_hello[0]); 	printf("return vlaue is %d\n",* retval_hello[0]);*/  	printf("This is a test.\n"); 	return 0; } 	         问题1：在不同的机器中，程序的运行结果不同，有先运行完线程1再运行线程2的，有先运行线程2再运行线程1的，有互相穿插 的。这应该是时间片问题吧，但线程2的运行时间比线程1大很多，为什么会出现先运行2再运行1的？另外优先级是怎么确 定的呢？          问题2：在主线程main中，pthread_join的先后并没有决定线程的先后，甚至只用一个pthread_join都可以运行两个线程，但一个都没有却不能运行线程，为什么呢？          问题3：如果现在有两个线程，一个是读文件线程，一个是对读到的数据进行处理的线程，这两个线程是串行进行的，即先读再 处理，虽然可以不用线程编写，但用线程是不是更好一点呢？再，处理的线程的程序比较复杂，运行时间比读线程久， 那么，程序在运行时，会不会出错，比如，先运行处理，再读，或者互相穿插？那应该怎么解决呢？             望各位不吝赐教！感谢非常！   代码太长了，没有看看，简单说说  1、你的代码里面没有对线程1、2进行调度，其运行先后完全由系统调度。此外，你的线程运行时间太短了，所以偶尔出现一个完了才运行另一个的现象。至于优先级，posix有标准函数，自行百度  2、pthread_join的具体作用似乎没有弄清楚，建议百度之，简而言之就是等待某个线程。在你的程序里面，主线程处用个getchar之类的，似乎更合理  3、必须要分两个线程，因为一个是io一个是逻辑。理论上io处理速度远远低于逻辑处理速度。其实这个问题就是最简单的生产者消费者。boost有无锁解决方案

仅供参考：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             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]:'.');             }             Log("%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]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX );     InitializeCriticalSection(&cs_BBB ); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef WIN32     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_BBB );     DeleteCriticalSection(&cs_HEX );     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }


Question: 急急急 MQRMH 索引消息传输文件 websphere8 java

顶一下


Question: VS 2013 无法启动.dll

程序员的常识之一：不要将程序源代码或项目或exe放在桌面这种复杂（多半带空格和汉字且在防火墙或杀毒软件严密控制的C盘上）的目录下。

连接库的路径设置错

我也遇到这状况


Question: 求指导数组越界的问题

c/c++语言本身没有提供这种功能，但是你完全可以自己封装一个库

判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

用一个变量保存已经输入个数. 达到超过10个就报错.  注意.  系统是不会主动给你报错的, 这不同与Java等更高级的语言

C语言不行，　java倒是可以抛出异常。

C语言没有这种规范，除非编译器实现

输入时只允许输入10个数字即可。

要对输入得到的数组做一个长度统计,然后与你预期想输入的数组大小进行比较。

没太理解楼主的意思. 如果知道数组的大小，用循环输入的话应该不会有越界的问题（除非代码写错了）。  如果要判断越界，可以数组的地址进行判断。

个人感觉： 应该要对输入得到的数组做一个长度统计。 然后与你预期想输入的数组大小进行比较。  不知道其他大神有没有更好的想法。


引用 3 楼 zhangxiangDavaid 的回复:word是整型 一般情况下， word是两个字节大小 dword是double word的缩写，那就是4个字节的大小 DWORD_PTR指的是dword类型的指针 错,DWORD_PTR是unsigned long类型,不是什么指针

used for pointer precision怎么翻译?

有啥不懂的啊。。认真看。用词典辅助


Question: 关于用套接字从内网到外网的通信

引用 2 楼 user-3 的回复:两个不在同一个局域网下的PC互相通信： 1）需要端口映射   需要把socket接收端（server）的计算机的端口和这台机器所在的路由器的相应的端口映射起来 因为一般计算机都是通过路由器和internet连接的，任何internet过来的消息都会先经过路由器才能到达pc，普通的一个信息过来，路由器就是直接拦住并丢弃了，不会往内网里的任何机器上发的 而如果你做了端口映射：即把内网的某个机器上的某个端口和路由器的某个端口映射起来的话，当路由器的这个端口接收到信息的时候，就等于那个机器接收到了这个信息---------所谓端口映射，简单点说就是把两个端口捏成一个 2）socket的接收端需要固定的外网IP（static ip）～～～由于当今计算机太多，ip4早就用光光了，现在电信服务商的办法都是动态ip，你可以在百度里输入：我的ip地址，然后百度会告诉你你的外网ip是什么，但这个ip是个动态ip，你把路由器关了再开一下，很可能就变了～～～～～～这个动态ip是电信商管理的路由器给你分配的，你想通过这个ip接收信息，就和上面的1）的道理一样，除非你能进入电信服务商的那个给你分配ip的路由器去做端口映射-------这显然是不可能的，所以，你需要给你的server申请一个static ip（静态ip），在ip4如此紧张的今天，这个申请很可能需要你花钱................  如果你没有静态ip（你应该肯定没有），那么请看3） 3）找免费的动态域名解析服务--------国内比较用得多的应该是“花生壳”，自己百度下个客户端用用，很简单  不过，有一种情况3）也会失效，就是电信服务商变态到给你用10开头的ip做外网..............本来10开头的ip是私有的保留ip，不会做外网的，但是由于ip资源紧张，所以现在连10开头的都有那来做外网地址的了........10开头的可以做一个不太大的城市范围的外网ip----------城域网～～～如果你“不幸”被分配到了10开头的网址.......那么你要想用上面的办法实现socket信息发送，就必须确保你的客户端和服务器端必须在同一个城域网内........  4）百度下vpn，可以找个免费的vpn服务器，用这个免费的vpn服务器做中转站，实现客户端和服务器端的socket信息发送-----这个方法最简单也最靠谱  谢谢你，真的还有很多东西要学~~ 还有几个问题： 1、在百度上查到的我的IP就是路由器IP吗？ 2、如果我把我的计算机端口和路由器端口映射起来了，用SOCKET绑定百度上查到的这个IP，那是不是在我重启电脑之前可以和不同局域网的电脑通信？ 3、一般映射哪个端口进行通信？或者说怎样判断该映射哪些端口？

学习点基本的TCP/IP知识吧。

引用 3 楼 qq_27432295 的回复:[quote=引用 2 楼 user-3 的回复:] 两个不在同一个局域网下的PC互相通信： 1）需要端口映射   需要把socket接收端（server）的计算机的端口和这台机器所在的路由器的相应的端口映射起来 因为一般计算机都是通过路由器和internet连接的，任何internet过来的消息都会先经过路由器才能到达pc，普通的一个信息过来，路由器就是直接拦住并丢弃了，不会往内网里的任何机器上发的 而如果你做了端口映射：即把内网的某个机器上的某个端口和路由器的某个端口映射起来的话，当路由器的这个端口接收到信息的时候，就等于那个机器接收到了这个信息---------所谓端口映射，简单点说就是把两个端口捏成一个 2）socket的接收端需要固定的外网IP（static ip）～～～由于当今计算机太多，ip4早就用光光了，现在电信服务商的办法都是动态ip，你可以在百度里输入：我的ip地址，然后百度会告诉你你的外网ip是什么，但这个ip是个动态ip，你把路由器关了再开一下，很可能就变了～～～～～～这个动态ip是电信商管理的路由器给你分配的，你想通过这个ip接收信息，就和上面的1）的道理一样，除非你能进入电信服务商的那个给你分配ip的路由器去做端口映射-------这显然是不可能的，所以，你需要给你的server申请一个static ip（静态ip），在ip4如此紧张的今天，这个申请很可能需要你花钱................  如果你没有静态ip（你应该肯定没有），那么请看3） 3）找免费的动态域名解析服务--------国内比较用得多的应该是“花生壳”，自己百度下个客户端用用，很简单  不过，有一种情况3）也会失效，就是电信服务商变态到给你用10开头的ip做外网..............本来10开头的ip是私有的保留ip，不会做外网的，但是由于ip资源紧张，所以现在连10开头的都有那来做外网地址的了........10开头的可以做一个不太大的城市范围的外网ip----------城域网～～～如果你“不幸”被分配到了10开头的网址.......那么你要想用上面的办法实现socket信息发送，就必须确保你的客户端和服务器端必须在同一个城域网内........  4）百度下vpn，可以找个免费的vpn服务器，用这个免费的vpn服务器做中转站，实现客户端和服务器端的socket信息发送-----这个方法最简单也最靠谱  谢谢你，真的还有很多东西要学~~ 还有几个问题： 1、在百度上查到的我的IP就是路由器IP吗？ 2、如果我把我的计算机端口和路由器端口映射起来了，用SOCKET绑定百度上查到的这个IP，那是不是在我重启电脑之前可以和不同局域网的电脑通信？ 3、一般映射哪个端口进行通信？或者说怎样判断该映射哪些端口？[/quote]  1）是的---是个动态ip 2）不是你重启电脑，而是重启路由器---路由器重启动态ip就很可能会变化～～～～不一定可以，我已经解释过了。如果你所说的不同的局域网在同一个城市，应该可以～～～ 3）百度：常用端口  这个问题你要自己上网查～～不过如果只是做个socket发送普通的消息的话，10000以后的端口一般可以随便用，你可以把你打算开放的端口百度一下，看看有没有特殊用途，如果有，就别用----其实用了也没事.......只是一般我们不会随便用那些有专门用途的端口～～

网上看到一个NAT转换，是这个原因吗？我是新手，不太懂.....NAT转换后的IP是外网IP吗？我改成了外网IP也不行啊.....要怎么样才可以


Question: 关于 基于身份的加密算法 stanford ibe-0.7.2调试问题

引用 2 楼 user-2 的回复: 注意体会上面的命令写法，这是在Windows下运行的命令拼写，<和>都是命令的组成部分，各字串之间有空格。 按照您这方法确实可以加密了，但怎么解密呢？而且它的私钥是否一定要通过邮件发送？


Question: 关于windows基指针类型的疑问

LPBYTE pX; TCHAR __based (pInFile) *pIn; //pIn是(TCHAR __based (pInFile)*)类型 pIn = (TCHAR __based (pInFile)*) *(DWORD *)pX;//将pX强转为(DWORD *)类型后在取其值，并将取得的值再强转为(TCHAR __based (pInFile)*)类型，最后赋值给pIn


Question: 信源编码怎么运用到实际

有没有了解的大神指点一下。。。

引用 2 楼 zhao4zhong1 的回复:电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。 我的意思是霍夫曼编码实现过程中，比如A对应的编码是0010，一般编码实现时是分别将‘0’、‘0’、‘1’、‘0’作为占有八位二进制位的字符放进字符数组中；但是我们实际编码时应该是把它们分别当做一位二进制位来看。前一种编码后就占了4*8=32位二进制位了，而我们实际想要得到的应该是4位二进制位不是么？

引用 1 楼 user-2 的回复:字符数组不就是二进制吗？还要转什么？ 计算机内部什么东西不是二进制呢？？？  估计楼主没有说清问题 我的意思是霍夫曼编码实现过程中，比如A对应的编码是0010，一般编码实现时是分别将‘0’、‘0’、‘1’、‘0’作为占有八位二进制位的字符放进字符数组中；但是我们实际编码时应该是把它们分别当做一位二进制位来看。前一种编码后就占了4*8=32位二进制位了，而我们实际想要得到的应该是4位二进制位不是么？