在C函数中返回char数组

时间:2016-02-12 17:58:29

标签: c

我在编写一个非常小的C程序时遇到了一些问题。看看我能找到的所有堆栈溢出文章,但没有取得多大成功。该程序假设在纯文本字符串上使用非常简单的XOR“加密”。输入字符串和键都是6个字符长。我是C和指针的新手。我想我没有掌握一些语言的基础知识。

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

#define LENGTH 7
#define KEY "secret"

char * encryptDecrypt(char *plaintext);

int main(int argc, char **argv)
{
    if(argc > 1)
    {
        char *plainText = argv[1];
        printf("Encrypting plaintext: %s (%i)\n", plainText, strlen(plainText));
        char *cipherText = encryptDecrypt(plainText);
        printf("Encrypted: %s (%i)\n", cipherText, strlen(cipherText));
        char *decryptedText = encryptDecrypt(cipherText);
        printf("Decrypted: %s (%i)\n", decryptedText, strlen(decryptedText));
    }
    return 0;
}

char * encryptDecrypt(char *text)
{
    char result[LENGTH];
    for (int i = 0; i < LENGTH-1; i++)
    {
        result[i] = (char)(text[i] ^ KEY[i]);
    }
    char *resultPtr = &result;
    return resultPtr;
}

使用arg“foobar”输出程序运行:

加密明文:foobar(6)

加密:╠╠╠╠╠╠╠╠T¨(19)

解密:╠╠╠╠╠╠╠╠T¨(19)

问题:

  1. 在encryptDecrypt函数中使用以及在返回结果数组后,打印指向结果数组的指针是不同的
  2. 在密文上使用XOR不会将其恢复为原始纯文本(尽管因为我打印的内容不对,这部分可能没问题)
  3. 加密/解密文本的字符串长度是19个字符长?如果原始字符串是6个字符,那怎么可能?

4 个答案:

答案 0 :(得分:4)

 char *resultPtr = &result;
 return resultPtr;

你不能这样做。当函数结束时,result不存在,您无法返回result

像这样修改你的功能:

void encryptDecrypt(char *text, char *result)
{
  for (int i = 0; i < LENGTH - 1; i++)
  { 
    result[i] = (char)(text[i] ^ KEY[i]);
  }
}

在调用者站点创建一个数组,并将其作为result传递。 e.g。

char result[LENGTH] = {0}; 
encryptDecrypt(plainText, result);

注意:实际上使用%s打印加密数据并不是最好的选择,因为例如作为XOR的结果,您可能会在文本之间得到一个空字节,这将是被视为字符串的空终止符,printf将不显示字符串的其余部分。考虑使用this之类的内容来打印密文。

strlen的格式说明符也有误,使用%zu的{​​{1}},或者您会触发undefined behaviour

答案 1 :(得分:3)

你无法返回指向局部变量的指针。你必须

  • 传递缓冲区的地址
  • malloc space并返回它(然后调用者必须释放它)
  • strdup局部变量并返回(这实际上只是malloc为你包裹)

您无法返回指向局部变量的指针的原因是因为它们在您退出函数时被销毁

答案 2 :(得分:3)

您的edu.stanford.math.plex4.homology.barcodes.BarcodeCollection正在返回本地变量的地址。函数返回后该内存无效,因此尝试使用它是undefined behavior

您应该使用encryptDecrypt为此函数的结果动态分配内存。此外,您应该传入字符串的大小,以便知道要分配多少空间。

将加密的字符串作为字符串打印也是未定义的行为,因为您拥有的不是字符串,而是非空终止的字符数组。

另外,在打印malloc的结果时,请务必使用%zu格式说明符。

sizeof

编辑:

修正#include <stdio.h> #include <stdlib.h> #include <string.h> #define LENGTH 7 #define KEY "secret" char * encryptDecrypt(char *text, int len); int main(int argc, char **argv) { if(argc > 1) { char *plainText = argv[1]; // use the string length + 1 to include the null terminator int len = strlen(plainText)+1; printf("Encrypting plaintext: %s (%zu)\n", plainText, strlen(plainText)); char *cipherText = encryptDecrypt(plainText,len); //printf("Encrypted: %s (%zu)\n", cipherText, strlen(cipherText)); char *decryptedText = encryptDecrypt(cipherText,len); printf("Decrypted: %s (%zu)\n", decryptedText, strlen(decryptedText)); // clean up the allocated memory free(cipherText); free(decryptedText); } return 0; } char * encryptDecrypt(char *text, int len) { char *result = malloc(len); // allocate memory for the result for (int i = 0; i < len; i++) { // if the text is longer that the key, wrap around on the key result[i] = (char)(text[i] ^ KEY[i%LENGTH]); } return result; // return the allocated buffer } 上的索引以防止超出它。

答案 3 :(得分:2)

encryptDecrypt函数中的结果字符数组只是此函数的局部变量,只要encryptDecrypt函数正在执行,它的内容将保留在内存中。一旦函数执行完成数组结果内容可能存在或可能不存在于存储器中。(如果内容被破坏,那么它将包含一些垃圾值)。

数组名称本身指向数组的第一个元素 所以char *resultPtr = &result;正在发送指向第一个元素的指针的地址。 相反,您应该写char *resultPtr = &result[0];char *resultPtr = result;

要使代码正常工作,请替换为  char result[LENGTH];

 char * result = (char*)malloc(sizeof(LENGTH));
 result[LENGTH-1] = '\0';      // To make result string null terminated

malloc函数用于动态内存分配,现在结果数组中的内容将保留在内存中(即使在函数执行完毕后),直到使用自由函数从内存中显式释放它。

注意:即使加密后的结果字符串为空终止但我们也不能使用printf("%s",result);来打印它,因为加密方法使用XOR,甚至可以使字符串的其他字符为空终止。要打印这样的字符串,您必须创建自己的函数来打印结果数组的前6个字节。