【问题标题】:Filling malloc'd memory and converting into a char array填充 malloc 的内存并转换为 char 数组
【发布时间】:2018-01-04 17:10:18
【问题描述】:

我有一些数据想发送到只接受字符数组的 USART 终端。

首先我创建数据并用东西填充它:

uint32_t * testdata =   malloc(60 * sizeof(uint32_t)); // 240 bytes on my system
memset(testdata,3,240); // fill it

然后创建一个char数组并将测试数据复制到其中

char* valueAsString =  malloc(60 * sizeof(uint32_t) + 1);// one more for 0-terminator
snprintf( valueAsString, 240 + 1, "%d", testdata );

发送数据的函数如下所示:

static void sendRS232string(char message[], uint16_t messageLength )
{
    for (uint8_t i = 0; i < messageLength; i++)
        {
            usart_putchar(USART_SERIAL, message[i]);
        }
}

我得到的输出是'88'?

顺便说一句,我使用的是 32 位 ATMEL 微控制器:ATXMEGA128A1U

关于如何实现这一点的任何想法?

--------------------------更新------ ------------------------------

我已经重新措辞了这个问题以尝试更具体:

我正在尝试创建一个 446 字节长的内存块,将一些数据放入其中并一次将内存块打印到终端一个字节。

uint16_t * WordToSend =   malloc(446); // create the memory
memset(WordToSend,0,446); //set it to zero fill
uint16_t test = 2; // on my system uint16_t is 2 bytes long
memcpy(WordToSend,test,sizeof(test)); // copy test into my new memory starting at the begining

// print out one byte at a time
int i;
for(i = 0; i < 447; i++) 
{
    unsigned char valueAsString = ((char*)WordToSend)[i] ;

    usart_putchar(USART_SERIAL, valueAsString);
}

Putchar 需要:

enum status_code usart_putchar(USART_t *usart, uint8_t c)

问题是 WordToSend 充满了零,我希望前 2 个字节为 02。我也不确定问题出在哪里,是我错误地复制测试还是 valueAsString 的问题任务。如果有人能阐明为什么会发生这种情况或提出更好的方法,那就太好了。

仅供参考:调试时,如果我查看内存位置

WordToSend 

它包含零而

*( WordToSend) 

包含数据。

【问题讨论】:

  • 你为什么从一开始就和uint32_t合作?
  • 预期输出是什么?
  • 格式说明符 "%d" 需要 int 参数,但您传递了一个指针值。你的编译器应该给你一个警告。
  • snprintf( valueAsString, 240 + 1, "%s", testdata );?
  • 您要发送二进制数据还是字符串(很可能是 ASCII)数据?

标签: c arrays char printf malloc


【解决方案1】:

根据您的评论“我希望输出为 240 x '3'”,执行此操作的代码是

char *testdata = malloc(240);
memset(testdata, '3', 240);
sendRS232string(testdata, 240);

如果您担心sendRS232string 函数似乎需要一个数组,并且您正在传递一个指针,那不是问题,因为所谓的“C 中的数组和指针的等价性” ”。 (如果你不明白这一点,请询问,或在其上进行谷歌搜索。)

您需要了解的另一件事是3'3' 之间存在巨大差异。 3 是整数 3。'3'字符 3,在 ASCII 中其值为 51。

当你打电话时

memset(testdata,3,240);

你用数字 3 填充 testdata,它最终(同样,在 ASCII 中)等同于字符 control-C。

我不确定你想通过snprintf 调用来完成什么。根据您要执行的操作,您可能需要也可能不需要使用 snprintf 之类的东西来在字符和整数之间转换,或者在整数和它们的十六进制表示之间进行转换,等等。

听起来你真的很想处理一堆 4 字节的整数。但是您需要决定如何通过串行端口传输这些整数:作为原始的“二进制”数字(每个 4 个字节)或作为某种文本表示形式(十六进制、十进制或其他形式)。


根据您的评论“我需要显示 240 个字节中的每一个,最好是十六进制”,您想要的代码可能更像

int i;
for(i = 0; i < 60; i++) {
    char valueAsString[30];
    snprintf(valueAsString, sizeof(valueAsString), "%X\n", testdata[i]);
    sendRS232string(valueAsString, strlen(valueAsString));
}

请注意,我循环遍历testdata 中的值,使用snprintf 将它们一次转换为十六进制,并分别调用sendRS232string 60 次。我没有创建一个包含所有 60 个格式化整数的文本缓冲区,或者类似的东西。

如果您希望每个 4 字节 into 始终由 8 个十六进制数字表示,只需将 printf 格式从 %X 更改为 %08X

【讨论】:

  • 非常感谢,但是,正如您提到的,我有一个 uint32、4 字节数据块,您的示例以 char * 数据开头。理想情况下,我需要一种将 uint32_t * 测试数据转换为 char testdata[] 的方法。所以基本上每4个字节的testdata[0]....等等变成一个有4个元素的char数组。
  • @moonraker 我的回答中水平线上方的代码----与下面的代码几乎没有关系。我的答案中的第二个代码片段(行下方)旨在与您的 uint32_t * testdata 数据完全配合。
  • 顺便说一句,snprintf()的返回值是字符串长度(当不是-1时)所以代码可以使用int len = snprintf(valueAsString, ...); sendRS232string(valueAsString, len);
猜你喜欢
  • 2015-03-09
  • 2011-06-08
  • 2013-03-02
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
相关资源
最近更新 更多