我正在尝试使用malloc
创建24字节内存空间的程序。我们的想法是在12 byte
频谱中的前10个字节中存储名称(字符串),在后2个字节中存储年龄(int)。我希望对两组数据执行此操作,因此我分配 2 x 12 = 24字节。我想将空间用作异构2D数组。
下图说明了我想如何组织内存空间。
这是我的代码:
void* ptr = malloc(24);
string* st;
string t_string;
int i=0, c=1, t_int;
int* it;
while(i < 24){
cout << "Enter name and age (" << (c++) << "): ";
cin >> t_string >> t_int;
st = (string*)(ptr) + i;
*st = t_string;
it = (int*)(ptr) + i + 10;
*it = t_int;
i+=12;
}
cout << endl;
i=0;
while(i < 24){
st = (string*)(ptr) + i;
it = (int*)(ptr) + i + 10;
cout << *st << " is " << *it << " years old.\n";
i+= 12;
}
问题是当我输入两个名字和年龄时,第一个年龄总是显示错误。这是一个输出:
Enter name and age (1): Progyammer 19
Enter name and age (2): Coderguy00 19
Progyammer is 1629513069 years old.
Coderguy00 is 19 years old.
每一次,它都只能与第一个人一起发生。
答案 0 :(得分:2)
你这是错误的方式。你最好创建一个包含九个字符(加上空字符)char指针的结构数组,并使用一个short(不是int,即4个字节)来表示该年龄。
struct Person {
const char name[10];
short age;
};
然后您可以像这样创建两个Person数组:
struct Person arr[2] /* the 2 is optional */ = {
{"Haskell", 12}, {"Ada", 21}
};
答案 1 :(得分:1)
虽然您应该在C中使用struct
或在C ++中使用class
,但如果您在某些微控制器上限制了堆栈空间,那么额外的4字节填充12字节块有所不同,没有理由你不能完全按照自己的意愿去做 - 但我建议使用C而不是C ++来实现这种类型的hackery。此外,如果您只是为学习项目执行此操作,处理通用数据块,了解严格别名规则 C11 Standard - §6.5 Expressions (p6),并了解块内的寻址 - 那也没关系。
首先,您需要创建24字节的分配内存块,类型为char
(请参阅上面的§6.5表达式)。为内存块分配/验证存储后,您是否需要创建逻辑来存储和访问块中您希望的信息。 (你没有一个12字节块的数组,你只有一个24字节的块,所以数组索引对你没有好处,它是指针算法或什么都没有。
所需的指针运算确实没有什么困难。您知道您需要将每个12字节块视为存储区域。因此,循环遍历内存块,您可以使用(pointer + i * BLKSZ12
)来定位每个12字节块的开头。从那里,您知道您的short
将从头开始存储另一个STRSZ
(即10
)个字节。因此,当您循环播放时,您可以使用short
存储或访问每个对应的pointer + i * BLKSZ12 + STRSZ
。然后,只需从存储偏移量中存储或检索age
即可。
完全放弃,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRSZ 10
#define BLKSZ 12
#define BUFSZ 512
int main (void) {
char *block, /* pointer to generic block of memory */
buf[BUFSZ] = ""; /* buffer for fgets use */
size_t i = 0, /* general loop var / counter */
nblks = 2; /* number of BLKSZ blocks to allocate */
/* allocate block of nblks * BLKSZ bytes / validate */
if (!(block = malloc (nblks * BLKSZ))) {
perror ("malloc-block");
exit (EXIT_FAILURE);
}
while (i < nblks) { /* for each of the blocks */
size_t len; /* var for holding string length */
printf ("\nenter name (9 char max): "); /* prompt/validate */
if (!fgets (buf, BUFSZ, stdin)) { /* read/validate input */
fprintf (stderr, "warning: user canceled input.\n");
exit (EXIT_FAILURE);
}
len = strlen (buf); /* get length */
if (len && buf[len - 1] == '\n') /* check trailing '\n' */
buf[--len] = 0; /* overwrite w/nul-character */
else if (len == BUFSZ - 1) { /* check all input fit in buf */
fprintf (stderr, "error input too long or buf.\n");
continue; /* go get next name */
}
if (len > STRSZ - 1) { /* validate name fits */
fprintf (stderr, "error: name exceeds %d chars.\n", STRSZ - 1);
continue;
}
strcpy (block + i * BLKSZ, buf);
printf ("enter age : "); /* prompt/validate */
if (!fgets (buf, BUFSZ, stdin)) { /* read/validate input */
fprintf (stderr, "warning: user canceled input.\n");
exit (EXIT_FAILURE);
} /* convert age to short from buf */
if (sscanf (buf, "%hd", (short*)(block + i * BLKSZ + STRSZ)) != 1) {
fprintf (stderr, "error: conversion failed, block %zu.\n", i);
continue;
}
i++; /* we got a valid block, increment block count */
}
printf ("\nNames Age\n");
for (i = 0; i < nblks; i++) /* output info stored in each block */
printf ("%-10s %2hd yrs.\n", block + i * BLKSZ,
*(short*)(block + i * BLKSZ + STRSZ));
free (block); /* free block */
return 0;
}
示例使用/输出
$ ./bin/alloc_blk24
enter name (9 char max): Mary
enter age : 25
enter name (9 char max): Joeseph
enter age : 90
Names Age
Mary 25 yrs.
Joeseph 90 yrs.
内存使用/错误检查
每次在C中动态分配内存时,由您来验证是否已正确使用该内存,没有内存错误以及已分配的所有内存已被释放。在Linux上,valgrind
工具是首选工具。所有操作系统都有类似的工具。它们易于使用,您只需通过它们运行程序即可。
例如,使用valgrind
,您可以确认您只分配了一个24字节的内存块,没有内存错误,并且在程序执行之前已分配的所有内存都已正确释放,例如
valgrind ./bin/alloc_blk24
==26366== Memcheck, a memory error detector
==26366== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==26366== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==26366== Command: ./bin/alloc_blk24
==26366==
enter name (9 char max): Mary
enter age : 25
enter name (9 char max): Joeseph
enter age : 89
Names Age
Mary 25 yrs.
Joeseph 89 yrs.
==26366==
==26366== HEAP SUMMARY:
==26366== in use at exit: 0 bytes in 0 blocks
==26366== total heap usage: 1 allocs, 1 frees, 24 bytes allocated
==26366==
==26366== All heap blocks were freed -- no leaks are possible
==26366==
==26366== For counts of detected and suppressed errors, rerun with: -v
==26366== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
正如所有人都建议的那样,包括在内,这不是你应该使用一块内存来保存两种不相关的数据类型(缺少在内存关键硬件上,或者用于学习练习)的方法。优点是C提供了执行此操作所需的所有工具,仅仅是出于讨论的原因。 C可以让你做任何可以在计算机上以闪电般速度完成的事情 - 无论你是否应该 - 只是问题的另一个方面。
如果您还有其他问题,请与我们联系。