【问题标题】:How to construct and return a String in C? [duplicate]如何在 C 中构造和返回一个字符串? [复制]
【发布时间】:2017-10-31 02:01:02
【问题描述】:

我正在尝试用 C 构造并返回一个字符串,但遇到了function returns address of local variable [-Wreturn-local-addr] 编译器警告。我知道返回packet 就像我尝试做的那样不起作用,因为数据包是指向我的大小为packet_size 的字符开头的指针,并且该内存地址在我的函数之外无效。我在 AVR 芯片上运行,不想使用malloc。我该如何解决这个问题?

#include <stdio.h>
#include <string.h>
#include <stdint.h>

const char* construct_packet(const char* data);
void append(char* str, char c);

int main()
{
    const char* my_packet = construct_packet("QERT");
    printf("%s", my_packet);

    return 0;
}

const char* construct_packet(const char* data)
{
    const char training_chars[] = "___";
    const char start_char = '>';
    uint8_t checksum = 0;
    for(uint16_t i = 0; i < strlen(data); i++) {
        checksum += data[i];
    }
    const char checksum_char = checksum;

    uint8_t packet_size = strlen(training_chars) + strlen(data) + 2; // Plus 2 for start byte and checksum byte
    char packet[packet_size];

    strcat(packet, training_chars);
    append(packet, start_char);
    strcat(packet, data);
    append(packet, checksum_char);

    return packet;
}

void append(char* str, char c)
{
    str[strlen(str) + 1] = c;
}

【问题讨论】:

  • 这很肮脏,我讨厌这样做的想法,但是如果您无能为力,static char* 变量可以为您工作吗?
  • @jonathon-reinhart OP 不能使用 malloc 你的副本是错误的。或者这个answer 可能不适用于这个问题。你说得对。
  • @Stargateur 阅读完整的第一个答案。

标签: c avr-gcc


【解决方案1】:

如果您不想使用动态内存分配,也不想使用static 缓冲区,那么您可以尝试计算并提供堆栈上的内存缓冲区:

#include <stdio.h>
#include <string.h>
#include <stdint.h>

const char* construct_packet(const char* data, const char* training_chars, const char start_char, char* packet);
void append(char* str, char c);

int main()
{
    const char data[] = "QERT";
    const char training_chars[] = "___";
    const char start_char = '>';
    const uint8_t packet_size = strlen(training_chars) + strlen(data) + 2; // Plus 2 for start byte and checksum byte
    char packet[packet_size];

    const char* my_packet = construct_packet(data, training_chars, start_char, packet);
    printf("%s", my_packet);  // same as printf("%s", packet);

    return 0;
}

const char* construct_packet(const char* data, const char* training_chars, const char start_char, char* packet)
{
    uint8_t checksum = 0;
    for(uint16_t i = 0; i < strlen(data); i++) {
        checksum += data[i];
    }
    const char checksum_char = checksum;

    strcat(packet, training_chars);
    append(packet, start_char);
    strcat(packet, data);
    append(packet, checksum_char);

    return packet;
}

void append(char* str, char c)
{
    str[strlen(str) + 1] = c;
}

【讨论】:

    【解决方案2】:

    Phil Brubaker:如果您不想使用动态内存分配,也不想使用静态缓冲区,那么您可以尝试计算并提供堆栈上的内存缓冲区:

    我不会说更好,我的实现:

    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    
    // in some header file
    const char *construct_packet(char *packet, const char* data);
    size_t size_packet(const char* data);
    
    int main(void)
    {
        const char *data = "QERT";
        size_t packet_size = size_packet(data);
        char packet[packet_size];
        construct_packet(packet, data);
        printf("%s", packet);
    }
    
    // can be on a other file of course `training_chars` and `start_char` could be give in parameter
    // of course cause there are static `size_packet()` and `contruct_packet()` must be in the same file
    static const char * const training_chars = "___";
    static const char start_char = '>';
    
    size_t size_packet(const char* data)
    {
        // you forgot nul terminate byte
        return sizeof training_chars - 1 + 1 + strlen(data) + 1 + 1;
    }
    
    const char *construct_packet(char *packet, const char* data)
    {
        size_t i = 0;
    
        // I replace strcat because I supose you want speed note they are better method that this one
        for (size_t j = 0; training_chars[j] != '\0'; j++) {
            packet[i++] = training_chars[j];
        }
    
        packet[i++] = start_char;
    
        // maybe this should be a char but you don't give information about checksum so I can't be sure
        uint8_t checksum = 0;
        for (size_t j = 0; data[j] != '\0'; j++) {
            packet[i++] = data[j];
            checksum += data[j];
        }
        packet[i++] = (char)checksum;
    
        // you forgot nul terminate byte
        packet[i] = '\0';
    
        return packet;
    }
    

    当然,你可以不计算大小并给出最大值:

    char packet[256];
    construct_packet(packet, data, 256);
    

    【讨论】:

      猜你喜欢
      • 2015-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多