我不能 return C 中的字符串

I can't return a character string in C

你好;

我的程序有问题,需要计算一个IP地址的@host网络。程序的步骤是:

  1. 在二进制(int)的“网络”变量中添加掩码和 ip
  2. 将“reseau”变量转换为十进制(在 char[] 中)
  3. Return main
  4. 中的“网络”变量

无论如何,我在第 1 步。为了确保一切正常,我正在尝试 return 包含二进制加法的字符串“reseau”。

问题:很遗憾我做不到。它给我以下错误代码:

returning 'char *' from a function with return type 'char' makes integer from without a cast [-Wint-conversion] 33. return reseau;

我怀疑这是因为你不能 return 那样的字符标签(根据我的研究),但我无法弄明白。

代码:

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

char calcul(char* octet, char* masque);

void main(){
    char octetB[]="11000000101010000000000100000111";
    char masqueB[]="11111111111111111111111100000000";

    printf("octetB : %s\n", octetB);
    printf("octetB 3e valeur : %c\n", octetB[2]);

    printf("Adresse réseau : %s\n", calcul(octetB, masqueB));
}

char calcul(char* octet, char* masque){
    int i;
    char reseau[100];

    printf("\n");
    printf("octet dans calcul : %s\n", octet);
    printf("masque dans calcul : %s\n", masque);

    for(i=0; i<32; i++){
        if((octet[i]='1') && (masque[i]='1')){
            reseau[i]='1';
        } else {
            reseau[i]='0';
        }
        printf("nombre %d : %d\n", i, reseau[i]);
    }
    return reseau;
}

所以我很想得到一些帮助来知道我哪里出错了? 为了理解。谢谢 :D

问题是您的函数 calcul() return 是一个字符数组或指向字符 (char*) 的指针,尽管您的函数定义说 return 类型是char。这就是您收到编译错误的原因。

但是你不能 return 数组 reseau。此变量是本地变量,仅在您的函数内可用。在函数之外 calcul() 这个字符数组不再有效。

您的代码中的下一个问题是 reseau 最后没有 nul 终止。所以你的 printf() 不会像你预期的那样工作。

最后我在你的代码中发现了另一个问题。语句 octet[i]='1' 是一个赋值。在您的情况下,您需要进行比较。您必须将其更改为 octet[i]=='1'(双等号)。

向上:

我已经考虑了您的意见和解释。现在它可以工作了(使用 malloc 系统)。

感谢您的评论。

这是更新后的代码,供遇到该主题的人使用:

char* calcul(char* octet, char* masque){
    int i;
    char reseau[100];

    printf("\n");
    printf("octet dans calcul : %s\n", octet);
    printf("masque dans calcul : %s\n", masque);

    for(i=0; i<32; i++){
        if((octet[i]=='1') && (masque[i]=='1')){
            reseau[i]='1';
        } else {
            reseau[i]='0';
        }
        printf("nombre %d : %d\n", i, reseau[i]);
    }
    char* result = malloc(strlen(reseau)+1);
    strcpy(result, reseau);
    return result;
}

您的代码无法编译,因为您在 calcul() 函数 return char 和 returning 字符数组。如果你想 return reseau 字符数组,你可以使用指针来完成。查看下面代码与您的代码的区别,了解如何实现它。

您的代码中也存在一些逻辑问题,例如 reseau 数组中没有结束行,这导致在您想要的字符串之后打印垃圾值。并且您使用一个等于 = 而不是双等于 == 来比较代码中的相等。

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

const char* calcul(char* octet, char* masque);

int main(){
    char octetB[]="11000000101010000000000100000111";
    char masqueB[]="11111111111111111111111100000000";

    printf("octetB : %s\n", octetB);
    printf("octetB 3e valeur : %c\n", octetB[2]);

    printf("Adresse réseau : %s\n", calcul(octetB, masqueB));
}

const char* calcul(char* octet, char* masque){
    int i;
    char *reseau = malloc(100);
    printf("\n");
    printf("octet dans calcul : %s\n", octet);
    printf("masque dans calcul : %s\n", masque);

    for(i=0; i<32; i++){
        if((octet[i]=='1') && (masque[i]=='1')){//use double equal to compare
            reseau[i]='1';
        } else {
            reseau[i]='0';
        }
        printf("nombre %d : %c\n", i, reseau[i]);
    }
    reseau[i]= '[=10=]';//add endline
    return reseau;
}

使用malloc()的解决方案的缺点是分配了内存,但释放内存的责任不明确。调用者甚至不需要知道内存是动态分配的(为什么要知道?),并且无法释放它导致内存泄漏。通常释放分配的责任应该是明确的。在这种情况下,这不是一个好的解决方案。

一个简单(但仍然不完善)的解决方案是静态分配返回的字符串:

const char* calcul( const char* octet, const char* masque )
{
    static char reseau[33] = "" ;

    ...

    return reseau;
}

但是这有一个不可重入的问题(多线程或递归代码中的一个问题)并且调用者仍然需要了解与使用静态缓冲区相关的限制和问题。返回的指针对于所有调用者都是相同的,这样如果随后调用函数,字符串将被修改。调用者可以复制该字符串,或确保在再次调用该函数之前已完成对它的所有处理。动态内存分配可能更好,但仍然需要调用者了解内部内存管理才能正确使用它。

该解决方案的另一个缺点是返回 const 无法在函数外部执行写访问,因此如果有必要,调用者必须将字符串复制到本地缓冲区。返回一个非常量将是一个非常糟糕的主意 - 您将修改函数内的“隐藏”缓冲区。

更常用和更灵活的习惯用法是让调用者“拥有”缓冲区并将其传递给要填充的函数。这样内存可能是一个数组,或者根据调用者的需要动态分配。在这种情况下,您还可以传递数组的长度,以便函数可以避免溢出调用者的缓冲区:

const char* calcul( const char* octet, const char* masque, 
                    char* reseau, size_t reseau_len )
{
    ...

    for( i = 0; 
         octet[i] != 0 && masque[i] != 0 && i < reseau_len; 
         i++)
    {
        ...
    }

    return reseau;
}

那么函数可以这样调用:

    char reseau_buf[sizeof(octetB)] ;
    printf( "Adresse réseau : %s\n", 
            calcul( octetB, masqueB, 
                    reseau_buf, sizeof(reseau_buf) ) ) ;

请注意,最后一个版本也没有对 masqueoctet 的长度做出任何假设 - 循环在所有输入中较短的一个停止。如果它们不同,那是调用者的错误,函数实现将“优雅地”确定性地失败,因此更容易调试。


除了对作业的解释

上面的

None 似乎正确地解决了您似乎误解了的任务。我希望解决方案看起来像:

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

uint32_t subnet( uint32_t ip, uint32_t mask, char* subnet_str ) ;

int main()
{
    uint32_t ip = 0xC0A80001 ;      // 192.168.0.1
    uint32_t netmask = 0xFFFFFF00 ; // 255.255.255.0

    char ipstring[] = "000.000.000.000" ;
    printf( "0x%08X : ", subnet(ip, netmask, ipstring) ) ;
    printf( "%s\n", ipstring ) ;
}

uint32_t subnet( uint32_t ip, uint32_t mask, char* subnet_str )
{
    // Step 1 : apply mask to get subnet
    uint32_t network = ...

    // Step to: convert network to "xxx.xxx.xxx.xxx" string form
    // in subnet_str
    ...

    // Step 3
    return network ;
}

输出:

0xC0A80000 : 192.168.1.0

显然对其中任何一个问题的帮助都值得提出一个新问题。但是,远比您已经投入的工作简单。步骤 1 和步骤 2 都可以作为一行代码来实现。