字符指针和字符数组有一个小的区别:
字符指针是一个指针变量,他是要占用空间的,这个空间的大小取决于机器是多少位的(64位的就要占用8个字节,因为他是地址,64位系统的地址是用64位来表示的)
字符数组虽然在使用上类似上像是在使用字符指针,然而实际上,本质上他只不过是编译器在内存中做的标记,字符数组本身不占用任何空间。
所以,下面的struct在64位机器上的大小是16个字节。
struct test{
int32_t a;
char* buff;
char buf[];
};
int32_t a;
char* buff;
char buf[];
};
int32_t a; 应当使用4个字节,但是64位机器要做64位对其,所以占用了8个字节
char* buff; buff是一个指针,又占用一个64为的地址空间,再加8个字节
char buf[]; 这个东西一个空间也不占用,他就像是一个隐形的字符指针
这一点在redis的
Simple Dynamic Strings中得到了出色的应用,参考:http://redis.io/topics/internals-sds修改了的代码可以看到效果:
#include <stdio.h>
#include <iostream>
using namespace std;
typedef char *sds;
struct sdshdr {
long len;
long free;
char buf[];
};
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
sh = (sdshdr*)malloc(sizeof(struct sdshdr)+initlen+1);
if (sh == NULL) return NULL;
sh->len = initlen;
sh->free = 0;
if (initlen) {
if (init) memcpy(sh->buf, init, initlen);
else memset(sh->buf,0,initlen);
}
sh->buf[initlen] = '\0';
printf("addr of len : 0x%X\n",&sh->len);
printf("addr of free: 0x%X\n",&sh->free);
printf("addr of buf : 0x%X\n",&sh->buf);
printf("addr of sh : 0x%X\n",sh);
return (char*)sh->buf;
}
size_t sdslen(const sds s) {
printf("addr of s : 0x%X\n",s);
struct sdshdr *sh = (sdshdr*) (s-(sizeof(struct sdshdr)));
printf("addr of sh : 0x%X\n",sh);
return sh->len;
}
main()
{
sds str = sdsnewlen("redis", 5);
cout<<"-----------------------"<<endl;
cout<<(sdslen(str))<<endl;;
}
#include <iostream>
using namespace std;
typedef char *sds;
struct sdshdr {
long len;
long free;
char buf[];
};
sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh;
sh = (sdshdr*)malloc(sizeof(struct sdshdr)+initlen+1);
if (sh == NULL) return NULL;
sh->len = initlen;
sh->free = 0;
if (initlen) {
if (init) memcpy(sh->buf, init, initlen);
else memset(sh->buf,0,initlen);
}
sh->buf[initlen] = '\0';
printf("addr of len : 0x%X\n",&sh->len);
printf("addr of free: 0x%X\n",&sh->free);
printf("addr of buf : 0x%X\n",&sh->buf);
printf("addr of sh : 0x%X\n",sh);
return (char*)sh->buf;
}
size_t sdslen(const sds s) {
printf("addr of s : 0x%X\n",s);
struct sdshdr *sh = (sdshdr*) (s-(sizeof(struct sdshdr)));
printf("addr of sh : 0x%X\n",sh);
return sh->len;
}
main()
{
sds str = sdsnewlen("redis", 5);
cout<<"-----------------------"<<endl;
cout<<(sdslen(str))<<endl;;
}
以上代码的输出是:
addr of len : 0xE8D3010
addr of free: 0xE8D3018
addr of buf : 0xE8D3020
addr of sh : 0xE8D3010
-----------------------
addr of s : 0xE8D3020
addr of sh : 0xE8D3010
5
addr of free: 0xE8D3018
addr of buf : 0xE8D3020
addr of sh : 0xE8D3010
-----------------------
addr of s : 0xE8D3020
addr of sh : 0xE8D3010
5
在这个sdshdr中,buf就好像是一个隐藏的指针,他不参与大小的运算(其实根本没有给他分配内存空间),但是却保存着sds最重要的数据内容。
相关的描述也可以在下面的文章中看到:
http://www.cnblogs.com/welkinwalker/archive/2011/01/05/1926203.html