user-0 提问: C 下数字相减导致数据异常的问题。

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

user: user-1
content: 判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #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; }

user: user-0
content: 计算过程是这样的， 上面是我没写清楚， 本来是想把变量的 类型直接带在前面的：  ttt = x -((unsigned long) y - (unsigned long) z) -sizeof(aaa);

user: user-0
content: 引用 3 楼 user-3 的回复:把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出 因为只有一个core文件，暂时复现不了， 然后用core文件里面的数据，打桩 对这个地方单元测试，也没出现上面的问题。  这个地方的内存被踩的问题，我也初步排除了。 我把这个数据附近的内存，都打印出来了， 除了正常赋值的部分，没有发现其他 异常地址那里有这个异常数据（也就是初步排除了memcpy这些内存之类的操作，导致的踩内存覆盖）。 还有一个就是 指针++ 导致的 踩内存，这个 还不确定，是不是有这个问题，不过在上面那个表达式附近，没有指针++的操作，所以应该也不是这个问题导致的。

user: user-1
content: Type-Cast Conversions You can use type casts to explicitly convert types.   Syntax  cast-expression :  unary expression ( type-name ) cast-expression  type-name :  specifier-qualifier-list abstract-declarator opt  The type-name is a type and cast-expression is a value to be converted to that type. An expression with a type cast is not an l-value. The cast-expression is converted as though it had been assigned to a variable of type type-name. The conversion rules for assignments (outlined in Assignment Conversions) apply to type casts as well. Table 4.5 shows the types that can be cast to any given type.  Table 4.5   Legal Type Casts  Destination Types Potential Sources  Integral types Any integer type or floating-point type, or pointer to an object  Floating-point Any arithmetic type  A pointer to an object, or (void *) Any integer type, (void *), a pointer to an object, or a function pointer  Function pointer Any integral type, a pointer to an object, or a function pointer  A structure, union, or array  None  Void type Any type    Any identifier can be cast to void type. However, if the type specified in a type-cast expression is not void, then the identifier being cast to that type cannot be a void expression. Any expression can be cast to void, but an expression of type void cannot be cast to any other type. For example, a function with void return type cannot have its return cast to another type.   Note that a void * expression has a type pointer to void, not type void. If an object is cast to void type, the resulting expression cannot be assigned to any item. Similarly, a type-cast object is not an acceptable l-value, so no assignment can be made to a type-cast object.   Microsoft Specific —>  A type cast can be an l-value expression as long as the size of the identifier does not change. For information on l-value expressions, see L-Value and R-Value Expressions.   END Microsoft Specific  You can convert an expression to type void with a cast, but the resulting expression can be used only where a value is not required. An object pointer converted to void * and back to the original type will return to its original value.

user: user-0
content: 引用 10 楼 ghx287524027 的回复:[quote=引用 9 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 ghx287524027 的回复:] 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。[/quote]  我在想，楼主用的什么编译器呢，那么写竟然还能编过去[/quote] gcc的编译器呢， 我不是太清除，我写了那个地方 编译器不让 编译。 愿意请教，呵呵。

user: user-0
content: 引用 3 楼 user-3 的回复:把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出 引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 ghx287524027 的回复:] 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。[/quote] 确实有点晕，知道的不是非常清除。 愿听赵老师详解。

user: user-2
content: 引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 ghx287524027 的回复:] 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。[/quote]  我在想，楼主用的什么编译器呢，那么写竟然还能编过去

user: user-1
content: 引用 8 楼 ghx287524027 的回复:对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了） 楼主强制类型转换相关语法不熟。我猜。

user: user-2
content: 对于指针 char *p，无论p指向什么位置，你只要将p强转成int或者long类型就可以啊，就是对应的内存的地址了，不知道你这里(unsigned long)char* y - (unsigned long)char* z 为什么还有 “char *”呢？我觉得直接 long ttt =  x -((long) y - (long) z) -sizeof(aaa); 这么计算就可以了呀（具体的选择什么样的数据类型，要根据你计算的数值确定，确保不会溢出就可以了）

user: user-0
content: 引用 5 楼 ghx287524027 的回复:你可以把你的代码贴出来，为什么计算长度会用了这么多项呢？ 这就是一个算包长度的过程，包整个长度  减包头的长度，得到包的长度，很简单的一个问题

user: user-0
content: 引用 3 楼 user-3 的回复:把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出 只有一个core文件，无法复现  引用 5 楼 ghx287524027 的回复:你可以把你的代码贴出来，为什么计算长度会用了这么多项呢？ 代码就是上面的那个啊，只是用  X, Y , Z代替了。 我看了一下整个代码，因为这个ttt的数据， 传递给下一个函数的时候，不是指针，直接是变量传值，然后我用gdb把栈上，所有这个变量的赋值看过(因为不是指针传进去的，所以肯定不会出现某个修改导致其他地方看到的这个数据都被修改了)，都是这个值，所以这个值肯定是一开始就算错了，不会是因为越界把数据踩了导致的， 上面那个地方就是最开始算数据的地方，只是我没看明白，为啥算了个巨大无比的数据出来了。

user: user-2
content: 你可以把你的代码贴出来，为什么计算长度会用了这么多项呢？

user: user-2
content: int  ttt = (unsigned short) x -((unsigned long) y - (unsigned long) z) -sizeof(aaa);

user: user-3
content: 把表达式分成一步步的，然后单步运行程序观察结果 另检查是否有溢出

user: user-0
content: 引用 1 楼 ghx287524027 的回复:char *y = 0x7fd33d232036，char*z = 0x7fd322e86800  这不是指针类型吗，怎么直接拿来做运算了？？？ 算长度用的，应该很常见吧

user: user-2
content: char *y = 0x7fd33d232036，char*z = 0x7fd322e86800  这不是指针类型吗，怎么直接拿来做运算了？？？