【问题标题】:How do I initialize a char array with a memory address in C?如何在 C 中使用内存地址初始化 char 数组?
【发布时间】:2016-09-29 19:12:56
【问题描述】:

我在上二年级的 C 班,这个项目是关于处理指针和设计内存转储函数的。所以我已经能够通过指针挣扎并获得一个开始和结束地址来转储,甚至对其进行位掩码,我想用开始内存地址初始化一个 char 数组。我用存储我屏蔽的起始地址的相同变量初始化它,但是当我打印数组时,它包含不同的内存地址。函数如下:

void memDump(void *base, int bytes)
{
unsigned char *begin;
begin = base;//beginning of range of memory
unsigned char *end;// ending range of memory
end = base + bytes;
int a, b;
long long int d=base;
d=d&0xFFFFF0; //trying to bitmask
long long int e=end;
e = e&0xFFFF0; //masked off the beginning and ending range
char c[16]={d}; //loop variables
printf("%x", c);

for (a=begin; a<=end; a+=16)
    {
        printf("\n%016X\n", d);
        printf("%016X\n", a);
        printf("%016X", e);
    }

}

对不起,伙计们,我找不到类似的东西,这是我最后的选择。谢谢!

更新:感谢大家的洞察力,阅读更多关于 C 的内容和一些关于如何调试的文章帮助了我。

【问题讨论】:

  • 您期待什么,什么不让您满意?请注意,将指针值存储在 char 中可能会做任何事情,但不是您想要的 (char c[16]={d};)。是否要将 d 内容作为字节复制到数组中?
  • 这里有些人对C很亲近,所以“指针垃圾”可能会冒犯。
  • 两个问题(这不应该影响您尝试做的事情,但无论如何这是错误的):您不应该将指针分配给普通整数变量。如果您需要一个保证适合指针的整数,您应该使用intptr_t from &lt;stdint.h&gt;。此外,如果您想使用printf 打印指针,请使用"%p" 格式来打印void *(需要转换为void * 才能没有未定义的行为)。
  • 我并不容易被冒犯,但我确实觉得“指针垃圾”有点烦人。
  • @EugeneSh.: 哦,这不是问题,考虑到该术语用于带有一些垃圾代码的问题;-)

标签: c arrays memory memory-address


【解决方案1】:

你不能用一些“内存地址”来“初始化一个字符数组”。 char数组只能用字符初始化。

Stackoverflow 不是为你做功课,所以我会给你一些建议,然后你可以尝试实现它。如果您无法将建议放入代码中,那么您不应该提交已完成的作业。

首先,一旦你对你的“d”进行了位掩码,你需要将它存储回“begin”,这样你就有一个指针,你可以从中开始读取要转储的字节。

这条指令:

printf( "%08p ", begin );

将以 8 个字符后跟一个空格呈现您的“开始”地址的十六进制表示。这就是您开始每一行内存转储的方式。

指令:

printf( "%02x ", *(begin++) );

获取“begin”指向的字节,并以两个字符呈现该字节的十六进制表示,后跟一个空格。然后它递增“开始”,以指向下一个字节。您需要执行此操作 8 或 16 次,具体取决于您希望内存转储的宽度,然后执行 printf( "\n" ) 以移至下一行。

然后你需要不断重复上面的步骤,直到你的“开始”超过你的“结束”。 (因此,您正在查看针对每一行的外部循环和针对该行中的每个字节的内部循环。)

我希望这会有所帮助。

【讨论】:

  • 是的,谢谢。我不是想为我完成作业,只是一些见解。在我发布这个之后,我做了我应该先做的事情并阅读了网站的其余部分,关于如何调试小程序的页面,指南和东西。再次感谢。
  • 很好,很高兴能帮上忙,达米安。正如您可能自己发现的那样,stackoverflow 是全球程序员不可或缺的资源。
【解决方案2】:

正如@Jean-FrançoisFabre 所观察到的,

char c[16]={d};

可能不会像您认为的那样做。也就是说,除非您认为它所做的是将存储在d 中的long long int 值转换为char 类型(产生从比d 本身更小的范围提取的实现定义的结果),初始化数组c 的第一个元素使用该值,并用0 初始化其他十五个元素。我无法想象你想对结果做什么,但由于你实际上对它做任何事情,这可能没有实际意义。

据我观察,

printf("%x", c);

也可能不会像您认为的那样做。事实上,你不能依赖它来做任何特定的事情,因为它的行为是未定义的。您将 pointer 传递给 c 的第一个元素作为第二个参数,但将需要 unsigned int 类型的值(基于格式)。无论如何,这既不会“打印[s] 数组”,也不会告诉您它包含的任何内容。

我怀疑您的实际想法是将c 声明为一个数组,其地址(而不是内容)是base 指定的数组,截断为16 字节-对齐的地址。你不能这样做,因为你不能指定你声明的任何变量的地址,但是你可以将c声明为一个指针,像这样:

unsigned char *c = d;

(哦,不,更多指针!)那里有一些实现依赖性,但它可能有我认为你想要的结果。或者如果你想变得非常聪明,你可以这样做:

unsigned char (*c16)[16] = d;

这将c16 声明为指向16 个数组unsigned char 的指针。它尽可能接近在您指定的地址声明数组。不过,我怀疑您会发现使用另一个声明会更容易。

如果你想打印这样一个指针指向的内存的内容(因为“内存转储”函数似乎不会这样做),那么你需要做更多的工作。除了 C 字符串之外,标准库的格式化 I/O 函数不直接提供打印数组(出于充分的理由,我不会在这里讨论),而且您似乎不想将数据打印为 C 字符串。但是,请考虑这个调用,以及如何修改或调整它以适应您的目的(假设我上面对c 的声明):

printf("%02x", *c);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 2013-09-12
    • 2021-02-04
    • 2012-07-27
    • 2018-11-15
    • 2023-03-17
    相关资源
    最近更新 更多