当使用sprintf将指针复制到字符串时,我有一些代码堆栈转储.我试图将动物的内容复制到一个名为output的新指针数组中.但是,我得到一个堆栈转储.
输出应该是以下内容:新动物兔新动物马新动物驴
我正确地走这条路吗?
非常感谢
#include#include #include void p_init(const char **animals, char **output); int main(int argc, char **argv) { char *animals[] = {"rabbit", "horse", "donkey", '\0'}; char **prt_animals = animals; char *output[sizeof(*animals)]; /* print the contents here */ while(*prt_animals) { printf("Animal: %s\n", *prt_animals++); } /* copy and update in the output buffer */ p_init(*&animals, *&output); getchar(); return 0; void p_init(const char **animals, char **output) { while(*animals) { sprintf(*output, "new animal %s", *animals); *output++; } }
Johannes Sch.. 6
该数组animals
是一个指针数组.它不是某种大小的缓冲区数组.因此,如果你这样做
sizeof(*animals)
您将获得该数组的第一个元素的sizeof.相当于
sizeof(char*)
因为你的数组存储指针.所以,在读取的行中
char *output[sizeof(*animals)];
您在一个数组中分配4或8个指针(取决于平台上指针的宽度.通常为4或8).但那当然没有意义!你想要做的是创建一个与之相同大小的指针数组animals
.您必须首先获得animals数组的总大小,然后除以一个元素的大小
char *output[sizeof(animals)/sizeof(*animals)];
现在,这就是你想要的.但指针仍然具有不确定的值...接下来你使用*&animals
(相同的另一个)传递数组.为什么?你可以animals
直接通过.取其地址然后取消引用与首先无所事事相同.
然后在你调用的函数中,将元素指向的字符串复制animal
到某个不确定的目标位置(记住output
数组的元素- 指针 - 还有不确定的值.我们还没有分配它们!).首先必须分配适量的内存并使元素指向它.
while(*animals) { // now after this line, the pointer points to something sensible *output = malloc(sizeof("new animal ") + strlen(*animals)); sprintf(*output, "new animal %s", *animals); output++; // no need to dereference the result animals++; // don't forget to increment animals too! }
另外,大约是上面的大小
有一件重要的事情你必须确定.这是我们计算尺寸的方式.无论你做什么,一定要确保你的绳子有足够的空间!AC字符串由字符和终止空字符组成,后者标记字符串的结尾.所以,*output
应该指向一个至少同样大的缓冲区,以便它包含"new animal "
和的空间*animals
.第一个包含11个字符.第二个取决于我们实际复制的内容 - 它的长度是strlen
返回的.所以,总的来说我们需要
12 + strlen(*animals)
所有字符的空格,包括终止null.现在,将该数字硬编码到代码中并不是一种好方法.前缀可能会更改,您可能忘记更新一个或两个字符的数字或错误计数.这就是我们使用的原因sizeof
,我们提供了我们想要预先添加的字符串文字.回想一下,sizeof
表达式的计算结果是其操作数的大小.您可以使用它main
来获取数组的总大小.现在您将它用于字符串文字.所有字符串文字都是字符数组.字符串文本由您键入的字符的除了为空字符.因此,以下条件成立,因为strlen
计算C字符串的长度,并且不包括终止空字符到其长度
// "abc" would have the type char[4] (array of 4 characters) sizeof "..." == strlen("...") + 1
我们不必除以一个元素的大小,因为char的大小无论如何都是一个,所以它不会产生任何影响.为什么我们使用sizeof
而不是strlen?因为它已经考虑了终止空字符,并且它在编译时进行了计算.编译器可以直接替换sizeof表达式返回的大小.
该数组animals
是一个指针数组.它不是某种大小的缓冲区数组.因此,如果你这样做
sizeof(*animals)
您将获得该数组的第一个元素的sizeof.相当于
sizeof(char*)
因为你的数组存储指针.所以,在读取的行中
char *output[sizeof(*animals)];
您在一个数组中分配4或8个指针(取决于平台上指针的宽度.通常为4或8).但那当然没有意义!你想要做的是创建一个与之相同大小的指针数组animals
.您必须首先获得animals数组的总大小,然后除以一个元素的大小
char *output[sizeof(animals)/sizeof(*animals)];
现在,这就是你想要的.但指针仍然具有不确定的值...接下来你使用*&animals
(相同的另一个)传递数组.为什么?你可以animals
直接通过.取其地址然后取消引用与首先无所事事相同.
然后在你调用的函数中,将元素指向的字符串复制animal
到某个不确定的目标位置(记住output
数组的元素- 指针 - 还有不确定的值.我们还没有分配它们!).首先必须分配适量的内存并使元素指向它.
while(*animals) { // now after this line, the pointer points to something sensible *output = malloc(sizeof("new animal ") + strlen(*animals)); sprintf(*output, "new animal %s", *animals); output++; // no need to dereference the result animals++; // don't forget to increment animals too! }
另外,大约是上面的大小
有一件重要的事情你必须确定.这是我们计算尺寸的方式.无论你做什么,一定要确保你的绳子有足够的空间!AC字符串由字符和终止空字符组成,后者标记字符串的结尾.所以,*output
应该指向一个至少同样大的缓冲区,以便它包含"new animal "
和的空间*animals
.第一个包含11个字符.第二个取决于我们实际复制的内容 - 它的长度是strlen
返回的.所以,总的来说我们需要
12 + strlen(*animals)
所有字符的空格,包括终止null.现在,将该数字硬编码到代码中并不是一种好方法.前缀可能会更改,您可能忘记更新一个或两个字符的数字或错误计数.这就是我们使用的原因sizeof
,我们提供了我们想要预先添加的字符串文字.回想一下,sizeof
表达式的计算结果是其操作数的大小.您可以使用它main
来获取数组的总大小.现在您将它用于字符串文字.所有字符串文字都是字符数组.字符串文本由您键入的字符的除了为空字符.因此,以下条件成立,因为strlen
计算C字符串的长度,并且不包括终止空字符到其长度
// "abc" would have the type char[4] (array of 4 characters) sizeof "..." == strlen("...") + 1
我们不必除以一个元素的大小,因为char的大小无论如何都是一个,所以它不会产生任何影响.为什么我们使用sizeof
而不是strlen?因为它已经考虑了终止空字符,并且它在编译时进行了计算.编译器可以直接替换sizeof表达式返回的大小.