考虑char *a[] = {"abc", "xyz", "def"};
深拷贝 char *a[]
到char **b
.
有人能说什么是深拷贝吗?我们需要分配多少内存b
?
char *a[n];
是一个包含 n 个指向字符的指针的数组。数组的每个元素在内存中都是连续的。所需的内存大小是
sizeof(char *) * n
我在这里使用了 sizeof() 运算符……你可以假设一个指针有 4 个字节,但这可能不安全……这取决于你的硬件。
char **b
略有不同。这是一个指向字符的指针。**b 尚未分配指针数组。首先分配数组...
char **b = malloc( sizeof(char *) * n);
编辑:感谢 interjay 指出我的错误...下面的示例现在使用 strdup() 为每个 b[i] 分配内存
**b 指向由 n 个指针组成的数组的开头。对于该数组中的每个指针,您可以对浅拷贝执行 b[0] = a[0]
这是一个浅拷贝,因为 b[0] 将指向与 a[0] 指向的内存相同的内存。因此更改内容 b[0] 将更改 a[0] 的内容。
深拷贝意味着您有两个完全独立的实体……因此更改内容 b[0] 不会导致更改 a[0] 的内容。这意味着您需要为每个 b[i] 分配新内存并将字符串从 a[i] 复制到该新块中。
深拷贝:
char *a[n];
// ...intialise array a....
char **b = malloc( sizeof(char *) * n); // allocate array of pointers
if( b )
{
int i = 0;
for(; i < n; ++i)
b[i] = (char *)strdup(a[i]); // allocate memory for new string and copy string
}
else
printf("You ran out of memory!\n");
顺便说一句...您使用了常量字符串,因此您不应该在技术上修改它们...
char *xxx = "String";
char yyy[] = "String";
您可以安全地修改 yyy 的内容。通常你可以修改 xxx 的内容没有任何问题,但是注意,因为字符串内存是在编译时分配的,你会发现编译器已经把它,例如,放在只读内存中。
编辑: 似乎一直在争论是否从 malloc 中强制返回(我一直有这样做的习惯,但似乎这是一个坏习惯!)......请参阅为什么我们需要强制转换 malloc 返回的内容?
走在a
阵列上,为每个a[i]
请求空间使用*alloc()
系列函数之一分配它,并将结果放入相应的b[i]
. b
指针本身应该是一个具有足够空间的指针,可以将字符串的数量作为a
指针保存。用这样的东西计算:
int bsize = (sizeof(a)/sizeof(a[0])) * sizeof(char*);
char **b = malloc(bsize);
int i,len;
/* if(b == NULL) /* error: no memory */
for(i = 0,len = sizeof(a)/sizeof(a[0]); i < len; i++) {
char *tmp = malloc(strlen(a[i])+1);
if(tmp == NULL) /* error: no memory */
strcpy(tmp, a[i]);
b[i] = tmp;
}
请注意,您需要或将b
数组的大小保存在内存中,或者将 aNULL
放在数组的末尾。
你可以做
b=a
这会将指针数组 *a[3] 的基地址分配给 b。
现在您可以使用 b 访问字符串
for example string 1 can be accessed by *(b+0) gives address of string 1
string 2 " " *(b+1) " " string 2
string 3 " " *(b+2) " " string 3
由于您将指针数组分配给指向指针的指针,因此您已经将内存分配给 b 因此您不需要使用 malloc。
仅当您在运行时将一些数据分配给指针并且您没有为程序中的指针分配内存时,才只能使用 malloc。