浅谈内存和指针§
内存§
计算机内存的地址通常按字节间隔排列。
在计算机中,内存被划分为许多小的存储单元,每个单元通常是一个字节。
每个存储单元都有一个唯一的地址,这些地址通常按顺序连续分配,形成了一个连续的地址空间。
在
C语言中,最小的基本数据类型是char,大小为1个字节,即8位。
1字节是C语言中内存的最小单元。这是因为计算机内存的寻址通常是以字节为单位,而不是位。void *data = malloc(4 * sizeof(char));
malloc函数接受一个整数参数,表示要分配的字节数,返回一个通用指针,指向一个大小为4字节的内存块。由于内存是在堆上分配的,不像局部变量那样在栈上分配,因此在不再需要时应该释放它,以避免内存泄漏。
free(data);接下来看一些常用的内存操作函数。
memset(data, 0b11111111, 4 * sizeof(char));
memset函数的作用是将data指针指向的内存块的前4个字节的每个字节的所有位都设置为1(即0b11111111) 。 void *new_data = malloc(4 * sizeof(char)); memcpy(new_data, data, 4 * sizeof(char)); memmove(new_data, data, 4 * sizeof(char));
memcpy和memmove函数的作用是将指针data所指向的内存块的前4个字节按顺序复制到指针new_data所指向的内存块的前4个字节。它们的区别在于第一个函数直接进行复制操作,而第二个函数则会先将内容存储到一个临时的内存位置,然后再进行复制操作。
因此,如果第一个函数中
data和new_data指向同一块内存,复制的结果是未定义的;而第二个函数则能够正常运行,因为它使用了临时内存来确保复制的安全性。显然,第一个函数的性能更好,但使用时需要注意指针是否指向相同的内存块。
int res = memcmp(new_data, data, 4 * sizeof(char));
memcmp函数用于按顺序比较data指针指向的内存块和new_data指针指向的内存块的前4个字节。返回值
res的大小代表着比较的结果:
如果
res小于0,则表示new_data的内容在字典顺序上小于data的内容。如果
res等于0,则表示new_data的内容与data的内容相等。如果
res大于0,则表示new_data的内容在字典顺序上大于data的内容。
指针§
在
C语言中,指针是用来存储内存块地址的。它的值实际上就是一个整数。
printf("The address of data : %u\n", data);
The address of data : 2481815280这个地址
2481815280表示指针data指向的内存块的起始地址。简单来说,可以把它想象成内存中的第
2481815280个字节位置。假设指针
data指向的内存块大小是4字节,那么从地址2481815280到2481815283的这4个字节都属于这个内存块。 printf("The address of data : %u\n", data); printf("The address of (char *)data + 1 : %u\n", (char *)data + 1); printf("The address of (short *)data + 1 : %u\n", (short *)data + 1); printf("The address of (int *)data + 1 : %u\n", (int *)data + 1);The address of data : 3576725232 The address of (char *)data + 1 : 3576725233 The address of (short *)data + 1 : 3576725234 The address of (int *)data + 1 : 3576725236通过以上代码我们可以看出,不同类型的指针相邻之间地址的差值并不相同。
char*增加1时地址增加1,short*增加1时地址增加2,int*增加1时地址增加4。这反映了不同数据类型所占内存空间大小的差异。
同样,将某个指针加
1实际上是得到了当前指针指向内存块紧挨着的下一个内存块的起始地址。它们的地址差正好是该内存块所占的字节数。
在
C语言中,这些指针运算被隐藏在幕后,编译器会自动处理,因此看起来似乎是简单地将指针加1,实际上是移动了一个特定大小的内存块。