user-0 提问: strlen计算长度	char b[]={'1'},a[]="123";

回复:
user: user-1
content: ret <===>  pop EFLAGS call esp 这里 call 搞错了 应该是： ret <===>  pop EFLAGS jmp esp

user: user-0
content: 引用 13 楼 lm_whales 的回复:X86，32Bits  call fun <===>  push Next_instruction, push EFLAGS jmp fun   ret <===>  pop EFLAGS call esp  函数 cdecl: int fun(int x,int y){return x+y;} <===>     push ebp          // 保存 ebp   mov  ebp,esp      // esp 的值复制到 ebp      mov eax ,x[ebp]  // x 相对esp的偏移量 为_x,复制到eax   add eax,y[ebp]   // x+y 结果存到 eax 。。。返回值在eax    pop ebp           //恢复ebp    ret               //返回，执行  call _fun的下一条指令 ，即执行 add esp 8 fun(a,b) <===>   push b          //参数压栈，左右边的开始压栈。   push a          //最左边的最后压栈                     call _fun       //调用指令     add esp 8       //调整堆栈     大约如此：  你这个我看得懂，谢谢你敲了这么多。我感觉自己就是钻牛角尖了，一直在纠结他那个内存里面的数据，他是四个字节对齐的（这个和系统有关系吗？），四个不够，它会自动补充，但是宽字符不是两个字节吗？

user: user-0
content: 引用 17 楼 lm_whales 的回复:对齐，和CPU，操作系统，编译器都有关系，并且还是可选的，也可以通过预编译指令控制。 CPU 决定不对齐，有没有问题，有什么问题。  操作系统，决定如何处理，CPU的运行和编程模式； 比如Windows 32 Bits， 只有flat 一种模式，除非CPU 对不对齐，产生异常， Windows 并不是很关心对齐的问题；  但是一般还是要求，32 Bits对齐。 而对有些特殊数据，则有一些特殊的对齐要求。  VC编译器 ，有一个对齐选项，可以决定一般数据，如何对齐，缺省是 32Bits，是可选的。 另外 有一条预编译指令，可以确定当前采取那种对齐方式。  VC还定义了一些非标准关键字，用于数据对齐。  其他编译器，应该也有类似的设置，以及对齐指令，或关键字。  恩恩，现在看来自己虽然对一些规则懂点，但是不能把这些东西与编译器环境这些东西联系不起来，还是知识面太窄了，要学的东西还很多，大四了找工作呢，边找边学习吧，谢谢你多次的帮助了

user: user-1
content: 对齐，和CPU，操作系统，编译器都有关系，并且还是可选的，也可以通过预编译指令控制。 CPU 决定不对齐，有没有问题，有什么问题。  操作系统，决定如何处理，CPU的运行和编程模式； 比如Windows 32 Bits， 只有flat 一种模式，除非CPU 对不对齐，产生异常， Windows 并不是很关心对齐的问题；  但是一般还是要求，32 Bits对齐。 而对有些特殊数据，则有一些特殊的对齐要求。  VC编译器 ，有一个对齐选项，可以决定一般数据，如何对齐，缺省是 32Bits，是可选的。 另外 有一条预编译指令，可以确定当前采取那种对齐方式。  VC还定义了一些非标准关键字，用于数据对齐。  其他编译器，应该也有类似的设置，以及对齐指令，或关键字。

user: user-2
content: 对b调用strlen有点bug喽！strlen测量长度至它遇到的第一个0为止， b是一个单个元素，无0结尾的字符数组

user: user-1
content: X86，32Bits  call fun <===>  push Next_instruction, push EFLAGS jmp fun   ret <===>  pop EFLAGS call esp  函数 cdecl: int fun(int x,int y){return x+y;} <===>     push ebp          // 保存 ebp   mov  ebp,esp      // esp 的值复制到 ebp      mov eax ,x[ebp]  // x 相对esp的偏移量 为_x,复制到eax   add eax,y[ebp]   // x+y 结果存到 eax 。。。返回值在eax    pop ebp           //恢复ebp    ret               //返回，执行  call _fun的下一条指令 ，即执行 add esp 8 fun(a,b) <===>   push b          //参数压栈，左右边的开始压栈。   push a          //最左边的最后压栈                     call _fun       //调用指令     add esp 8       //调整堆栈     大约如此：

user: user-1
content: 他后边哪些数据是根据什么规则加上去的，除非是象VC debug 一样，否则，根本没加数据，  只是输出时，根据数据内存分配的位置输出，直到找到结束符为止。 串长计算，同样是，一直找到结束符为止。  VC debug版程序会在，数据前后加入一些0xCC 这样的数据，如果这个数据被改变了，说明写操作越界了。    引用 楼主 wangyudong211 的回复:char b[]={'1'},a[]="123"; 	int c=strlen(a),d=strlen(b);  	printf("%d    %d\n",c,d); b={'1'} 反汇编窗口 b的地址里面存的是：0x0012ff44每次都一样的 //串在前   1  2  3 \0  1 0012FF40  31 32 33 00 31 CC CC CC 88  123.1烫虉 0012FF49  FF 12 00 19 13 40 00 01 00  .....@... 输出结果： 3  7 3个字节的对其数据用 0xCC0xCC0xCC 补足 后面的8个字节是函数返回地址，和标志寄存器的备份，用于保存现场，以利于函数返回   88FF1200    ===> 就是0x 0012FF88 ，是函数返回地址，就是函数返回后，执行的第一条指令的地址。 00 19 13 40 ===> 就是0x40131900是调用函数前，标志寄存器的值。函数调用返回后，自动恢复。  b={'1','2'};            1  2  3 \0  1  2 CC CC   0012FF40  31 32 33 00 31 32 CC CC 88  123.12烫. 0012FF49  FF 12 00 19 13 40 00 01 00  .....@... 输出结果： 3  7   b={'1','2','3'}; 0012FF40  31 32 33 00 31 32 33 CC 88  123.123虉 0012FF49  FF 12 00 19 13 40 00 01 00  .....@... 输出结果： 3  7  b={'1','2','3','4'}; 0012FF40  31 32 33 00 31 32 33 34 88  123.1234. 0012FF49  FF 12 00 19 13 40 00 01 00  .....@... 输出结果： 3  7  b={'1','2','3','4','5'}; 0012FF40  31 32 33 34 35 CC CC CC 88  12345烫虉 0012FF49  FF 12 00 19 13 40 00 01 00  .....@... 输出结果： 3  11  后序增加元素的话又是好几个11  以上都是VC6.0下， 这个到底是怎么一回事，不能理解这种现象，希望知道的可以解说下，谢谢了

user: user-3
content: strlen, wcslen, _mbslen, _mbstrlen Get the length of a string.  size_t strlen( const char *string );  size_t wcslen( const wchar_t *string );  size_t _mbslen( const unsigned char *string );  size_t _mbstrlen( const char *string );  Routine Required Header Compatibility  strlen <string.h> ANSI, Win 95, Win NT  wcslen <string.h> or <wchar.h> ANSI, Win 95, Win NT  _mbslen <mbstring.h> Win 95, Win NT  _mbstrlen <stdlib.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  Each of these functions returns the number of characters in string, excluding the terminal NULL. No return value is reserved to indicate an error.  Parameter  string  Null-terminated string  Remarks  Each of these functions returns the number of characters in string, not including the terminating null character. wcslen is a wide-character version of strlen; the argument of wcslen is a wide-character string. wcslen and strlen behave identically otherwise.   Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tcslen strlen strlen wcslen  _tcsclen strlen _mbslen wcslen    _mbslen and _mbstrlen return the number of multibyte characters in a multibyte-character string. _mbslen recognizes multibyte-character sequences according to the multibyte code page currently in use; it does not test for multibyte-character validity. _mbstrlen tests for multibyte-character validity and recognizes multibyte-character sequences according to the LC_CTYPE category setting of the current locale. For more information about the LC_CTYPE category, see setlocale.  Example  /*  STRLEN.C */  #include <string.h> #include <stdio.h> #include <conio.h> #include <dos.h>  void main( void ) {    char buffer[61] = "How long am I?";    int  len;    len = strlen( buffer );    printf( "'%s' is %d characters long\n", buffer, len ); }   Output  'How long am I?' is 14 characters long   String Manipulation Routines |  Locale Routines  See Also   setlocale, strcat, strcmp, strcoll Functions, strcpy, strrchr, _strset, strspn

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

user: user-0
content: 引用 8 楼 lm_whales 的回复:比较好理解的是，函数内部，数组在后，串在前，数据顺序存放的话（有很大可能是顺序的）， 数组地址，可能会比较低。 这样串长可能就是，从数组第一个元素，到串的结束符之间的，字符个数。  数组在前，除非数据反序存放，否则可能没有规律--VC有时会打乱顺序，有些编译器，则无任何顺序可言。   如果数据在函数外部，数组在前，串在后，如果数据顺序存放--可能性非常高，数组地址，可能会比较低。  如果输出字符串，或者求串长。 会从第一个元素开始查找字符。  如果串地址，在数组地址的后面，则输出时，可能会连串一起输出。 求串长，则可能会从数组找到串的结束符为止。 主要是数组b的长度是怎么一回事，他后边哪些数据是根据什么规则加上去的

user: user-1
content: 比较好理解的是，函数内部，数组在后，串在前，数据顺序存放的话（有很大可能是顺序的）， 数组地址，可能会比较低。 这样串长可能就是，从数组第一个元素，到串的结束符之间的，字符个数。  数组在前，除非数据反序存放，否则可能没有规律--VC有时会打乱顺序，有些编译器，则无任何顺序可言。   如果数据在函数外部，数组在前，串在后，如果数据顺序存放--可能性非常高，数组地址，可能会比较低。  如果输出字符串，或者求串长。 会从第一个元素开始查找字符。  如果串地址，在数组地址的后面，则输出时，可能会连串一起输出。 求串长，则可能会从数组找到串的结束符为止。

user: user-0
content: 引用 6 楼 zhaokai115 的回复:b没有\0结束符，strlen会一直往后搜索直到有\0，所以结果依赖于当时内存中的内容。 是这么一回事，但是他是有规律的啊并不是随便找\0的

user: user-4
content: b没有\0结束符，strlen会一直往后搜索直到有\0，所以结果依赖于当时内存中的内容。

user: user-0
content: char b[]={'1','2','3','4','5'},a[]="123"; 	int c=strlen(a),d=strlen(b);  	printf("%d    %d\n",c,d); 	getchar();   VS2012输出结果是：3 19

user: user-0
content: 引用 1 楼 focuslight 的回复:设置的是宽字符这个之前没接触过，看了半天资料还是很迷糊。。。  能针对这个题给我具体解释下不？

user: user-5
content: 多字节字符集和Unicode的区别是什么？

user: user-6
content: 在VC6中，默认使用MBCS编码，即多字节字符集；而VC7、VC8以及VS默认的都是Unicode编码

user: user-6
content: 设置的是宽字符