如何在calloc指针中打印值存储(c)

时间:2017-09-13 04:24:36

标签: c pointers

假设我的指针看起来像:

char *tmp = calloc(1, 500);

然后我将值签名到指针:

char *token = "star";
for(int cur = 0, cur < 500,cur += 50){
       strncpy(&tmp[cur], token, 50);//each 50 units will get a value

}

现在我有一个存储了多个值的指针。我应该怎样逐一打印出这个价值?

printf("--- %s\n", tmp); // this seems can only print the first one

我不知道如何跳转或读取下一个值,并保持读数直到打印整个指针。

3 个答案:

答案 0 :(得分:2)

由于您使用(更正后的代码)将以null结尾的值复制到数组中:

for (int cur = 0; cur < 500; cur += 50)
    strncpy(&tmp[cur], token, 50);

您可以使用以下方式打印值:

for (int cur = 0; cur < 500; cur += 50)
    printf("--- %s\n", &tmp[cur]);

答案 1 :(得分:1)

for(int cur = 0, cur < 500,cur += 50){

这是错误的。逗号,可能应该是分号;,并且您无意中错误地使用了comma operator

  

现在我有一个存储了多个值的指针

请定义合适的类型。我没有看到指针中存储了几个“值”。

但是,您可以看到指针指向(指向)500 char - s的数组。然后%s printf中出现%c错误(您可能会使用gcc -Wall -Wextra -g)。

建议:

  • 花几天时间阅读一些优秀的C编程书。在学习C(这是一种困难的编程语言)之前,我甚至建议花几周时间阅读SICP(编程的优秀介绍,不使用C)和练习。

  • 指定(在纸面上,用英语或您的母语),尽可能准确地说明您的代码应该做什么。

  • 仔细阅读并多次参考您使用的每个函数callocstrncpyprintf

    < / LI>
  • 详细了解pointers和指针arithmetic以及C dynamic memory allocation

  • 编译所有警告和调试信息,例如gdbGCC

  • 抛弃你的代码,完全重写它(直到你没有得到任何警告),使用rubber duck debugging;了解如何debug small programs

  • 在电路板上绘制你的记忆图片(带箭头指针和位置框)

  • 使用调试器,例如struct逐步运行代码并查询程序的状态,从而准确了解流程中发生的情况。

  • 学习 - 获取灵感 - 一些现有 free software的源代码(例如github

  

我应该怎样逐一打印出这个值?

首先,您需要了解并定义所涉及的types。也许你想要数组(什么类型?)或struct yourstruct { char name[50]; }; - s(有哪些字段和类型),可能以某些flexible array member结尾

  

我不知道如何跳转或读到下一个值

你从未解释过(并且可能没有理解)你对什么类型的“价值”有所考虑。所以跳到下一个是没有意义的(没有明确的值和类型)。

也许你对C中的字符串感到困惑。读一本好书。了解什么是undefined behavior

也许你想要一些

的数组
struct yourstruct *p = calloc(10, sizeof(struct yourstruct));
if (!p) { perror("calloc failed"); exit(EXIT_FAILURE); };

类型。但是你的代码错了!例如。它将从

开始
calloc

(当使用mallocuser.res_email == req.body.res_email && user.res_empno == req.body.res_empno 进行动态内存分配时,应检查是否有失败)

答案 2 :(得分:1)

  

我不知道如何跳转或读取下一个值,并保持阅读   直到打印整个指针。

嗯,你已经让自己变得更加困难了。为什么? 跳转读取内存块中的下一个值通常通过指针算术数组索引进行处理(其中本身只是一种方便的指针算法)。

存储在数组或内存块中的顺序值的 jump offset 通常由类型控制(例如{{1 },charint等。)。它不一定是那种方式(正如你在其他答案中看到的那样),但它默认设置为以这种方式工作。

每个类型具有一个大小(以字节数表示),例如struct foosizeof (char) = 1(通常),sizeof (int) = 4(x86_64上通常为sizeof (char *) = sizeof (a pointer)或x86上为8类型大小控制跳转或偏移到下一个值,例如

4

通过将size_t n = 10; int *intarray = calloc (n, sizeof *intarray); /* allocates space for 10 ints */ for (int i = 0; i < 10; i++) /* fill array, 0, 10, 20, ... 90 */ intarray[i] = i * 10; 声明为类型intarray,编译器知道int是第二个值的地址(例如intarray + 1),而10是第3个值(intarray + 2),依此类推。 注意,由您决定不超过内存范围,例如: 20是第10个值(OK),intarray + 9超出了分配和调用的内存块的末尾( Undefined Behavior )。

指针算术提供了另一种从内存中的一个值跳到下一个值的简单方法。同样,这基于类型大小

注意:您必须始终保留指向已分配内存块开头的指针,以便以后可以释放,以便跳转到intarray + 10中的每个值,或者使用数组索引,例如intarray,或者声明一个指向开头的第二个指针,并将其用于指针算法,例如

intarray[i]

另请注意:在尝试访问它们之前,必须初始化所有值。 (因为你使用... int *p = intarray; size_t i = 0; while (i < n) { /* loop to do this 10 times */ printf ("value[%zu] : %d\n", i, *p); /* print the value stored at p */ p++; /* increment p to point to next */ } 是安全的 - 因为所有字节都被初始化为零)。但是,使用calloc时,内存未初始化。

数组索引和指针算法适用于所有类型,甚至是malloc等已定义的类型。这里,编译器知道struct foo { int a; int b; };的大小,因此您可以使用指向sizeof (struct foo)的指针,就像使用指向foo(或int等的指针一样。 ..)

如果您在自己身上做了很多事情,那么您正试图以char的{​​{1}}间隔存储字符串(大小为0-49字符) 。虽然这很好,但是编译器无法帮助你,你不能使用指针算法或数组索引(除非你自己动手) - 因为你构成了类型 50

现在您可以使用静态声明的2D数组(例如tmp)让编译器帮助您。然后你可以使用索引(例如char + 50或者你可以声明一个指向50个字符数组的指针,你可以使用指针算法(例如char tmp[10][50]然后tmp[0], tmp[1], ...来到第二个,等等..

注意:由于C-Operator Precedence,char (*p)[50] = tmp;周围的括号是必需的,没有您创建指向char 的指针数组的parens(50他们而不是创建一个指向数组的指针

您还可以为任意数量的50个字符块动态分配内存。例如,为了做你想做的事情(在一个大块中),但告诉编译器你想要50个字符块(而不是你必须为其发明索引的500个字符块),你可以简单地做: / p>

p++

现在你可以简单地使用数组索引或指针算法来填充和迭代(*p)中每个50-char块中存储的单词。

为了把整个事情放在一起,让我们举两个例子。第一个将创建一个包含10个内存块(每个50个字符)的数组,并使用数组索引来填充和迭代char (*tmp)[50]; /* 'pointer-to-array 50, type char' */ tmp = calloc (n, sizeof *tmp); /* allocate storage for 10 tmp */ 的内容,第二个创建相同的内存块,但仅使用指针和一个柜台。 (两个例子完全相同):

tmp

示例使用/输出

tmp

内存使用/错误检查

在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放

您必须使用内存错误检查程序,以确保您不会尝试在已分配的内存块的范围之外/之外进行写入,尝试读取或基于未初始化值的条件跳转,最后,确认您释放了已分配的所有内存。

对于Linux #include <stdio.h> #include <stdlib.h> #include <string.h> #define NWRDS 10 /* number of words */ #define MAXC 50 /* max chars per-word */ int main (void) { size_t n = 0; /* number of words */ char (*tmp)[MAXC]; /* 'pointer-to-array 50, type char' */ tmp = calloc (NWRDS, sizeof *tmp); /* allocate storage for 10 tmp */ if (tmp == NULL) /* validate all memory allocations */ exit (EXIT_FAILURE); strcpy (tmp[n], "my dog has fleas."); /* copy stuff to first 3 blocks */ n++; strcpy (tmp[n], "my cat has none."); n++; strcpy (tmp[n], "... lucky cat..."); n++; for (size_t i = 0; i < n; i++) printf ("tmp[%zu] : %s\n", i, tmp[i]); free (tmp); /* dont' forget to free what you allocate */ return 0; } 是正常的选择。每个平台都有类似的记忆检查器。它们都很简单易用,只需通过它运行程序即可。

$ ./bin/ptr2array
tmp[0] : my dog has fleas.
tmp[1] : my cat has none.
tmp[2] : ... lucky cat...

注意:正好valgrind字节已按照您的意图分配。

始终确认已释放已分配的所有内存并且没有内存错误。

现在,让我们再次使用指针和计数器做同样的事情,

$ valgrind ./bin/ptr2array
==6010== Memcheck, a memory error detector
==6010== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6010== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==6010== Command: ./bin/ptr2array
==6010==
tmp[0] : my dog has fleas.
tmp[1] : my cat has none.
tmp[2] : ... lucky cat...
==6010==
==6010== HEAP SUMMARY:
==6010==     in use at exit: 0 bytes in 0 blocks
==6010==   total heap usage: 1 allocs, 1 frees, 500 bytes allocated
==6010==
==6010== All heap blocks were freed -- no leaks are possible
==6010==
==6010== For counts of detected and suppressed errors, rerun with: -v
==6010== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

(输出和内存检查相同)

虽然你的问题是基本的,但它看起来很基本,因为它涉及索引,指针算法以及两者如何直接绑定到正在处理的值的类型的基本概念。另请注意,您还可以将500声明为#include <stdio.h> #include <stdlib.h> #include <string.h> #define NWRDS 10 /* number of words */ #define MAXC 50 /* max chars per-word */ int main (void) { size_t n = 0; /* simple counter */ char (*tmp)[MAXC], (*p)[MAXC], /* 'pointer-to-array 50, type char' */ (*p2)[MAXC]; /* (3 of them) */ tmp = calloc (NWRDS, sizeof *tmp); /* allocate storage for 10 tmp */ if (tmp == NULL) /* validate all memory allocations */ exit (EXIT_FAILURE); p = p2 = tmp; /* set all pointers equal to tmp */ strcpy (*p++, "my dog has fleas."); /* copy stuff to first 3 blocks */ strcpy (*p++, "my cat has none."); strcpy (*p++, "... lucky cat..."); while (p2 < p) printf ("tmp[%zu] : %s\n", n++, *p2++); free (tmp); /* dont' forget to free what you allocate */ return 0; } 并首先分配tmp指针(例如char **tmp;然后分配,复制每个字符串,例如{{1然后你可以自由地释放每个单词,然后在你完成时释放指针(这个例子留给另一天)

希望这会有所帮助。如果您有任何其他问题,请与我们联系。