user-0 提问: 炫耀帖，记录本人在CSDN上的活动，以免以后找不到了。

回复:
user: user-1
content: 过来水一下

user: user-0
content: 引用 52 楼 cysccnu 的回复:[quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  这种问题不应该纠结于哪个标准，背后的汇编才是标准。运行这段代码第一次打印b的值确实是55，why？ 看汇编： 19:       for (a = 1; b <= 75; b = (++ a * 5) + 50) 0040103F   mov         dword ptr [ebp-4],1  //第一步给a赋值为1 00401046   jmp         main+3Dh (0040105d)  //第二部跳转去判断b<=75 00401048   mov         eax,dword ptr [ebp-4] 0040104B   add         eax,1 0040104E   mov         dword ptr [ebp-4],eax 00401051   mov         ecx,dword ptr [ebp-4] 00401054   imul        ecx,ecx,5 00401057   add         ecx,32h 0040105A   mov         dword ptr [ebp-8],ecx 0040105D   cmp         dword ptr [ebp-8],4Bh  //第3步判断出b=60比75小，所以直接打印b=55，for中expression-3只有在expression-2不为真时才执行。 00401061   jg          main+56h (00401076) 20:           printf ("%d\n", b); [/quote]  你的观点很荒谬。汇编说明不了任何问题。  引用 52 楼 cysccnu 的回复:[quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  这种问题不应该纠结于哪个标准，背后的汇编才是标准。运行这段代码第一次打印b的值确实是55，why？ 看汇编： 19:       for (a = 1; b <= 75; b = (++ a * 5) + 50) 0040103F   mov         dword ptr [ebp-4],1  //第一步给a赋值为1 00401046   jmp         main+3Dh (0040105d)  //第二部跳转去判断b<=75 00401048   mov         eax,dword ptr [ebp-4] 0040104B   add         eax,1 0040104E   mov         dword ptr [ebp-4],eax 00401051   mov         ecx,dword ptr [ebp-4] 00401054   imul        ecx,ecx,5 00401057   add         ecx,32h 0040105A   mov         dword ptr [ebp-8],ecx 0040105D   cmp         dword ptr [ebp-8],4Bh  //第3步判断出b=60比75小，所以直接打印b=55，for中expression-3只有在expression-2不为真时才执行。 00401061   jg          main+56h (00401076) 20:           printf ("%d\n", b); [/quote]  汇编输出能够代替C标准？就凭这一点，我就知道说再多，也白费口舌。 不解释 ，我知道没用的……

user: user-2
content: for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }

user: user-3
content: 引用 42 楼 sholber 的回复:今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  这种问题不应该纠结于哪个标准，背后的汇编才是标准。运行这段代码第一次打印b的值确实是55，why？ 看汇编： 19:       for (a = 1; b <= 75; b = (++ a * 5) + 50) 0040103F   mov         dword ptr [ebp-4],1  //第一步给a赋值为1 00401046   jmp         main+3Dh (0040105d)  //第二部跳转去判断b<=75 00401048   mov         eax,dword ptr [ebp-4] 0040104B   add         eax,1 0040104E   mov         dword ptr [ebp-4],eax 00401051   mov         ecx,dword ptr [ebp-4] 00401054   imul        ecx,ecx,5 00401057   add         ecx,32h 0040105A   mov         dword ptr [ebp-8],ecx 0040105D   cmp         dword ptr [ebp-8],4Bh  //第3步判断出b=60比75小，所以直接打印b=55，for中expression-3只有在expression-2不为真时才执行。 00401061   jg          main+56h (00401076) 20:           printf ("%d\n", b);

user: user-4
content: 楼主先改代码

user: user-5
content: 我是引用错了，csdn的bug，第二次引用居然没有覆盖第一次。 我引用的其实是你这个贴   天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： C/C++ code ? 1 2 int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b);  帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-

user: user-0
content: 引用 48 楼 ypzhong 的回复:[quote=引用 46 楼 sholber 的回复:] 问题： 函数 void play（void） {      int datalen；          unsigned char  *data1 = "*abvxdfkg";      datalen = strlen(data1);  } 编译一直出现 argument of type "unsigned char *" is incompatible with parameter of type "const char *"；  请问将其强制转换是否有问题datalen = strlen((const char *)data1);   问题的分析如下：  翻一下ISO/IEC 9899:201x Committee Draft 文件N1570，strlen函数的原型如下：  # include <string.h>  size_t strlen (const char * s);  很清楚，strlen函数的参数类型是const char *。  N1570，6.5.2.2 Function calls  In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the  corresponding argument. 这即是说，参数传递类似于赋值。那么，我们再看赋值时，如果=运算符左右两个操作数都是指针类型时，有什么样的要求--> N1570，6.5.16.1 Simple assignment  the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed  to by the left has all the qualifiers of the type pointed to by the right; 简言之，左右两个指针所指向的类型，在去掉限定符后，应当是兼容类型。而且，左边那个指针所指向的类型，应当具有右边那个指针所指向的类型的所有限定符。  因为strlen函数的参数类型是const char *，传递给该函数的参数类型是unsigned char *，那么， 1，左边指针所指向的类型具有const限定符，右边指针指向的类型没有限定符。可以视为，左边指针指向的类型具有自己的限定符const，加上右边指针所指向的类型的限定符（无）。这一条件通过； 2，两个指针所指向的类型在去掉限定符后，一个是char，另一个是unsigned char。不管char等价于unsigned char，还是等价于signed char，它们都是三种彼此不兼容的类型。问题就出在这里。  关于char、unsigned char和signed char的标准说明： N1570，6.2.7  Compatible type and composite type  Two  types  have compatible type if their types are the same.   N1570，第45页，注脚45： CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options.  Irrespective of the choice made,char is a separate type from the other two and is not compatible with either. 引用 44 楼 sholber 的回复:[quote=引用 43 楼 lm_whales 的回复:] [quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。  [/quote]  作为一个void表达式求值，这就是标准上的原话，没有问题。 N1570，6.3.2.2 void 1 The (non existent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.  If an expression of any other type is valuated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)   将expression-3作为void表达式求值，意味着将显式地丢弃该表达式的值。但是，求值（evaluation）包括值的计算和副作用，所以，该表达式的副作用是存在的。[/quote]    呵呵，语言的目的是用来解决现实问题的。钻牛角尖，舍本求末是没有意义。[/quote]  连细节都没搞清楚，你还怎么解决现实问题。所以你也只能呵呵了。

user: user-5
content: 引用 46 楼 sholber 的回复:问题： 函数 void play（void） {      int datalen；          unsigned char  *data1 = "*abvxdfkg";      datalen = strlen(data1);  } 编译一直出现 argument of type "unsigned char *" is incompatible with parameter of type "const char *"；  请问将其强制转换是否有问题datalen = strlen((const char *)data1);   问题的分析如下：  翻一下ISO/IEC 9899:201x Committee Draft 文件N1570，strlen函数的原型如下：  # include <string.h>  size_t strlen (const char * s);  很清楚，strlen函数的参数类型是const char *。  N1570，6.5.2.2 Function calls  In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the  corresponding argument. 这即是说，参数传递类似于赋值。那么，我们再看赋值时，如果=运算符左右两个操作数都是指针类型时，有什么样的要求--> N1570，6.5.16.1 Simple assignment  the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed  to by the left has all the qualifiers of the type pointed to by the right; 简言之，左右两个指针所指向的类型，在去掉限定符后，应当是兼容类型。而且，左边那个指针所指向的类型，应当具有右边那个指针所指向的类型的所有限定符。  因为strlen函数的参数类型是const char *，传递给该函数的参数类型是unsigned char *，那么， 1，左边指针所指向的类型具有const限定符，右边指针指向的类型没有限定符。可以视为，左边指针指向的类型具有自己的限定符const，加上右边指针所指向的类型的限定符（无）。这一条件通过； 2，两个指针所指向的类型在去掉限定符后，一个是char，另一个是unsigned char。不管char等价于unsigned char，还是等价于signed char，它们都是三种彼此不兼容的类型。问题就出在这里。  关于char、unsigned char和signed char的标准说明： N1570，6.2.7  Compatible type and composite type  Two  types  have compatible type if their types are the same.   N1570，第45页，注脚45： CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options.  Irrespective of the choice made,char is a separate type from the other two and is not compatible with either. 引用 44 楼 sholber 的回复:[quote=引用 43 楼 lm_whales 的回复:] [quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。  [/quote]  作为一个void表达式求值，这就是标准上的原话，没有问题。 N1570，6.3.2.2 void 1 The (non existent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.  If an expression of any other type is valuated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)   将expression-3作为void表达式求值，意味着将显式地丢弃该表达式的值。但是，求值（evaluation）包括值的计算和副作用，所以，该表达式的副作用是存在的。[/quote]    呵呵，语言的目的是用来解决现实问题的。钻牛角尖，舍本求末是没有意义。

user: user-6
content: 已经很久没看到有人愿意这么去翻标准了。

user: user-0
content: 问题： 函数 void play（void） {      int datalen；          unsigned char  *data1 = "*abvxdfkg";      datalen = strlen(data1);  } 编译一直出现 argument of type "unsigned char *" is incompatible with parameter of type "const char *"；  请问将其强制转换是否有问题datalen = strlen((const char *)data1);   问题的分析如下：  翻一下ISO/IEC 9899:201x Committee Draft 文件N1570，strlen函数的原型如下：  # include <string.h>  size_t strlen (const char * s);  很清楚，strlen函数的参数类型是const char *。  N1570，6.5.2.2 Function calls  In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the  corresponding argument. 这即是说，参数传递类似于赋值。那么，我们再看赋值时，如果=运算符左右两个操作数都是指针类型时，有什么样的要求--> N1570，6.5.16.1 Simple assignment  the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed  to by the left has all the qualifiers of the type pointed to by the right; 简言之，左右两个指针所指向的类型，在去掉限定符后，应当是兼容类型。而且，左边那个指针所指向的类型，应当具有右边那个指针所指向的类型的所有限定符。  因为strlen函数的参数类型是const char *，传递给该函数的参数类型是unsigned char *，那么， 1，左边指针所指向的类型具有const限定符，右边指针指向的类型没有限定符。可以视为，左边指针指向的类型具有自己的限定符const，加上右边指针所指向的类型的限定符（无）。这一条件通过； 2，两个指针所指向的类型在去掉限定符后，一个是char，另一个是unsigned char。不管char等价于unsigned char，还是等价于signed char，它们都是三种彼此不兼容的类型。问题就出在这里。  关于char、unsigned char和signed char的标准说明： N1570，6.2.7  Compatible type and composite type  Two  types  have compatible type if their types are the same.   N1570，第45页，注脚45： CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options.  Irrespective of the choice made,char is a separate type from the other two and is not compatible with either.

user: user-7
content: 原来作为 void 是这个意思， 我还以为直接不用求值了呢 直接不用求值虽然好， 但是会造成表达式求值过程的不统一。 想必编译器，不会这样做，  但是针对 这种情况， 直接丢弃表达式的值， 道是很简单方便。  当然这个表达式 也可以本身就是 void 类型的。  例如调用一个无返回值的函数（void 类型的函数）的函数调用表达式。

user: user-0
content: 引用 43 楼 lm_whales 的回复:[quote=引用 42 楼 sholber 的回复:] 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。  [/quote]  作为一个void表达式求值，这就是标准上的原话，没有问题。 N1570，6.3.2.2 void 1 The (non existent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.  If an expression of any other type is valuated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)   将expression-3作为void表达式求值，意味着将显式地丢弃该表达式的值。但是，求值（evaluation）包括值的计算和副作用，所以，该表达式的副作用是存在的。

user: user-7
content: 引用 42 楼 sholber 的回复:今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。  作者的输出结构是对的，  不过 “作为一个void表达式求值”。 这个应该是优化的行为， 这个说法是有问题的，应该不是C语言的标准。

user: user-0
content: 今天看到一个很好的素材，可以用在书里，来解释for语句的执行过程： int a, b = 55; for (a = 1; b <= 75; b = (++ a * 5) + 50) printf ("%d\n", b); 帖子的作者认为，第一次输出为55，但是我认为是60；求原因。   N1570，6.8.5.3 Theforstatement [1] The statement  for (clause-1 ;expression-2 ;expression-3 ) statement  behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression.  If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. 这就是说，expression-2作为控制表达式，将在语句statement之前执行；expression-3是在循环体statement每次执行之后，作为一个void表达式求值。

user: user-0
content: 声明：以下内容，同写代码又臭又长的赵老湿切磋一下。   给定声明： int * * p; 则p是指向“指向int类型的指针”的指针。  可以动态创建一个数组，令p指向它的首元素。但是，这个数组的元素类型必须是int * ： p = (int * *) malloc (sizeof (int *) * ROWS); 那么，如何利用p访问这个数组的每一个元素呢（比如，将它的每个元素都赋NULL指针）？  第一种方法是利用指针运算的规则： for (int i = 0; i < ROWS; i ++)      * (p + i) = NULL; 第二种方法是利用“在某些情况下，数组和指向它首元素的指针等价”： for (int i = 0; i < ROWS; i ++)      p [i] = NULL; 第三种方法也是利用数组下标运算，但是要先将p从“指向数组首元素的指针”转化为“指向一个数组的指针”： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      (* q) [i] = NULL; 以上，声明q为指向数组的指针，然后将p转化为指向数组的指针，赋给q。当q解引用（*q）后，就得到一个数组，这时就可以利用下标来访问数组的每一个元素了。考虑到在某些情况下，数组和指向它首元素的指针等价，故上述代码也可以写成： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      * ((* q) + i) = NULL;  前面那个动态创建的数组，其元素都是指向int类型的指针，我们已经全部赋值为NULL。如果希望令它们各自指向一个int类型的数组的首元素，怎么办呢？很简单，只需要使用上述四种方法中的一种，将NULL改成 (int *) malloc (sizeof (int) * COLS); 即可。如： for (int i = 0; i < ROWS; i ++)      * (p + i) = (int *) malloc (sizeof (int) * COLS);  最后，我们来看看，如何用前面的四种方法来读写这个奇怪数组的每一个元素。为简单起见，用前两种方法写，用后两种方法读。  写入数据的方法一： for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          * (* (p + i) + j) = j; 写入数据的方法二： for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          p [i] [j] = j; 读出数据的方法一： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          {              int (* r) [] = (int (*) [])(* q) [i];  //先将(* q) [i]转化为指向数组的指针             printf("%d\n", (* r) [j]);  //r解引用后是数组，下标j引用它的第j个元素         } 读出数据的方法二： int * (*q) [] = (int * (*) []) p;  for (int i = 0; i < ROWS; i ++)      for (int j = 0; j < COLS; j ++)          printf("%d\n", *(* (* q + i) + j));

user: user-0
content: 这是昨天晚上闲来无事，为某网友写的一个函数，目前自认为已经达到最简，看有没有谁能使之更简。 /* 功能：在字符串中找出连续最长的数字串，并把这个串的长度返回，例如：输入akjs123ccd458965，则输出458965，返回6 函数原型：    unsigned int Continumax(char** pOutputstr,  char* intputstr) 输入参数：    char* intputstr  输入字符串  输出参数：    char** pOutputstr: 连续最长的数字串，如果连续最长的数字串的长度为0，应该返回空字符串    pOutputstr 指向的内存应该在函数内用malloc函数申请，由调用处负责释放  返回值：   连续最长的数字串的长度  */ unsigned int Continumax(char * * pOutputstr,  char * intputstr) {     int cnt = 0, c = 0;     char * pos;       while (* intputstr ++ != '\0')         if (* (intputstr - 1) >= '0' && * (intputstr - 1) <= '9')             c ++;         else         {             if (c > cnt) cnt = c, pos = intputstr - c - 1;             c = 0;         }       if ((c = cnt)  != 0)     {         * pOutputstr = malloc (c + 1);         (* pOutputstr) [c] = '\0';         while (c --) (* pOutputstr) [c] = pos [c];     }     else * pOutputstr = 0;       return cnt; }   以上，之所以有     while (* intputstr ++ != '\0')         if (* (intputstr - 1) >= '0' && * (intputstr - 1) <= '9') 是因为，数字串可能位于源串的尾部，即'\0'之前。当然，你可能说使用do ... while语句，但那样还得多一条判断intputstr不为空的语句。

user: user-2
content: 引用 18 楼 zhao4zhong1 的回复:TDD 小心驶得万年船！ #include <stdio.h> #include <string.h> int del_substr (char * str, char const * substr) {     int cnt = 0;     char * p, * q, * r;     while (q = (char *)substr, * (p = r = str ++) != '\0')         while (* q != '\0' && * p ++ == * q)             if (* ++ q == '\0' && ++ cnt && -- str)                 while ((* r ++ = * p ++) != '\0') ;     return cnt; } int main() {     char *s1,*s2;     char b1[100],b2[100];      printf("del_substr(NULL,NULL)==%d\n",del_substr(NULL,NULL));     printf("del_substr(NULL,\"\")==%d\n",del_substr(NULL,""));     printf("del_substr(NULL,\"s\")==%d\n",del_substr(NULL,"s"));      strcpy(b1,"");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"s1");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"s1");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"s1");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"1s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"1s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"1s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"s1s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"s1s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"s1s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"ss1s");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"ss1s");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"ss1s");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"sss");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"sss");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"sss");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"1s2");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"1s2");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"1s2");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));      strcpy(b1,"1ss2");s1=b1;     printf("del_substr(\"%s\",NULL)==%d\n",s1,del_substr(s1,NULL));     strcpy(b1,"1ss2");s1=b1;     printf("del_substr(\"%s\",\"\")==%d\n",s1,del_substr(s1,""));     strcpy(b1,"1ss2");s1=b1;     printf("del_substr(\"%s\",\"s\")==%d\n",s1,del_substr(s1,"s"));       strcpy(b1,"1sss2s3");s1=b1;strcpy(b2,"sss");s2=b2;     printf("del_substr(\"%s\",\"%s\")==%d\n",s1,s2,del_substr(s1,s2));     strcpy(b1,"1sss2ss3");s1=b1;strcpy(b2,"ss");s2=b2;     printf("del_substr(\"%s\",\"%s\")==%d\n",s1,s2,del_substr(s1,s2));     strcpy(b1,"sss");s1=b1;strcpy(b2,"sss");s2=b2;     printf("del_substr(\"%s\",\"%s\")==%d\n",s1,s2,del_substr(s1,s2));      return 0; }  楼主受累完善一下以上代码。 郑重声明：楼主累死我不赔命。

user: user-8

user: user-9
content: 引用 16 楼 sholber 的回复:就像 if (5 == x) {/* …… */} 这就做作了，令人作呕。要知道，能够这样写的人，已经表明他意识到不能把==写成=。既然自己意识到了，还这么写，不是叫人倒胃吗？至于扯编码风格，什么别人来帮你维护什么的，只能滚犊子了。 这样写是为了避开手误，直接写=编译是不会出错的，特别是你写某些不常见分支没能测出来，就麻烦了。

user: user-10
content: 当然是看看究竟为主