对内存字节的理解

Posted strive-sun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对内存字节的理解相关的知识,希望对你有一定的参考价值。

为了加强自己的记忆,我决定用文字记录下来。

这是源代码,主要是输出环境变量,具体可以参考CreateEnvironmentBlock函数

 1 #include <Windows.h>
 2 #include <UserEnv.h>
 3 #include <assert.h>
 4 #include <stdio.h>
 5 #pragma comment(lib, "userenv.lib")
 6 #pragma warning(disable : 4996)
 7 
 8 int main()
 9 
10     HANDLE hToken = NULL;    
11     BOOL ok = OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken);
12     /*assert(ok);
13 
14     wchar_t* penv = NULL;
15     ok = CreateEnvironmentBlock((void**)&penv, hToken, TRUE);
16     assert(ok);
17 
18     while (*penv) 
19         printf("%ls\\n", penv);
20         penv += wcslen(penv) + 1;
21     */
22     wchar_t* wnext = NULL;
23     LPVOID pEnvironment = NULL;
24     ok = CreateEnvironmentBlock(&pEnvironment,
25         hToken,
26         FALSE);
27     if (!ok)
28     
29         // handle error
30     
31 
32     wchar_t* wtemp = (wchar_t*)pEnvironment;
33 
34     do
35     
36         wnext = wtemp + wcslen(wtemp) + 1;
37         int m = wcslen(wtemp);
38         if (*(wnext+1) == L\\0) // Crashes here
39         
40             break;
41         
42         else
43         
44             wtemp = wnext;
45             printf("%ls\\n", wtemp);
46         
47      while (1);
48 
49     return 0;
50 

注释部分可以不用看,主要注意 if (*(wnext+1) == L‘\\0‘) 这行

下面两张图分别是控制台输出结果和内存字节

技术图片

 

 

 技术图片

 

 

 从第二张图可以看到控制台打印到windir=C:\\WINDOWS之后,下面就会打印空行,再然后就会进入break,这是为什么呢?

我们已知宽字节占两个字节,所以一次会跳过2个点,包括r. s. 等等,我们在执行wnext = wtemp + wcslen(wtemp)+1这行代码时,实际上是相当于wtemp地址往后移动 wcslen(wtemp)+1个地址位,而我们在往后移动 wcslen(wtemp)时,我们其实到达了C.:.\\.W.I.N.D.O.W.S.的S.的位置,再+1就相当于到C.:.\\.W.I.N.D.O.W.S...的位置,+1的原因是为了跳过\\0的字符串结束位,到这边是将(..)这个空的赋给wnext,而在执行到下一行代码if (*(wnext+1) == L‘\\0‘),地址相当于又往后面移动一个宽字节,也就是C.:.\\.W.I.N.D.O.W.S.....,然后我们判断这之后的(\\.),把它与L‘\\0‘进行比较,发现它不为0,然后代码跳到else上面。

重点来了,wtemp = wnext;这行代码其实是把C.:.\\.W.I.N.D.O.W.S...后面的(..)这个空的内存字节赋给wtemp,打印为空,并不是C.:.\\.W.I.N.D.O.W.S.....,因为C.:.\\.W.I.N.D.O.W.S.....这个只是后面用于比较的,然后到wnext = wtemp + wcslen(wtemp) + 1这行代码,之前wtemp为空,所以wcslen(wtemp) = 0, 再+1,往后面移一个地址,就到了C.:.\\.W.I.N.D.O.W.S.....上的最后一个点的位置,接着执行到下一行代码if (*(wnext+1) == L‘\\0‘),地址上再+1,相当于跳过了(\\.),我们需要比较(\\.)后面的值,也就是(..),可以看到是空,然后与L‘\\0‘相同,到了break,跳出while循环,程序结束。

 

这段代码的正确输出要把if (*(wnext+1) == L‘\\0‘)中的+1去除,这样避免指针指向未知的内存区域。

可能写的有点乱,仅供参考吧,我也是第一次接触,很多术语都没怎么明白。

 

以上是关于对内存字节的理解的主要内容,如果未能解决你的问题,请参考以下文章

字节换算

网络字节序

网络字节序

高地址,低地址:

如何将字符串转换为字节数组? [关闭]

char多少字节influxdb