我正在尝试返回并在C中打印一个函数。打印出来的功能很好,但是当我从函数返回后尝试打印它时,我得到了废话。
我已经尝试了很多,我想我已经看过至少6个与此类似的堆栈溢出帖子,这是我能够接受的最接近的事情,不是分段错误或错误。
代码:
char* getBitstring(unsigned short int instr) {
//this is what the code below is going to convert into. It is set to default
//as a 16 bit string full of zeros to act as a safety default.
char binaryNumber[] = "0000000000000000";
//....
//doing things to binaryNumber
//.....
printf("don't get excited yet %s\n", binaryNumber); //note, this works
return binaryNumber;
}
int main(int argc, char *argv[]) {
char *a = getBitstring(0x1234);
printf("%s", a); //this fails
return 0;
}
这是输出:
don't get excited yet 0001001000110100
������e��r�S�����$�r�@�t�$�r�����ͅS�������t����
答案 0 :(得分:3)
这是因为您返回一个指向自动内存中分配的对象的指针 - 一种未定义的行为。
如果要从函数返回字符串,则需要返回动态分配的块或静态分配的块。
另一种选择是将缓冲区传递给函数,并以文件读取函数的方式提供长度作为函数的返回值:
size_t getBitstring(unsigned short int instr, char* buf, size_t buf_size) {
... // Fill in the buffer without going over buf_size
printf("don't get excited yet %s\n", binaryNumber);
return strlen(buf);
}
以下是您调用此功能的方法:
char binaryNumber[] = "0000000000000000";
size_t len = getBitstring(instr, binaryNumber, sizeof(binaryNumber));
现在binaryNumber
是调用者上下文中的一个自动变量,因此当调用者需要它时,内存就会存在。
答案 1 :(得分:1)
您的binaryNumber字符数组仅存在于getBitstring函数内。该函数返回后,该内存不再分配给binaryNumber。为了保持分配在该功能之外使用的内存,您可以执行以下两项操作之一:
返回动态分配的数组
char* getBitstring(unsigned short int instr) {
// dynamically allocate array to hold 16 characters (+1 null terminator)
char* binaryNumber = malloc(17 * sizeof(char));
memset(binaryNumber, '0', 16); // Set the first 16 array elements to '0'
binaryNumber[16] = '\0'; // null terminate the string
//....
//doing things to binaryNumber
//.....
return binaryNumber;
}
int main(int argc, char *argv[]) {
char *a = getBitstring(0x1234);
printf("%s", a);
free(a); // Need to free memory, because you dynamically allocated it
return 0;
}
或将数组作为参数传递给函数
void* getBitstring(unsigned short int instr, char* binaryNumber, unsigned int arraySize ) {
//....
//doing things to binaryNumber (use arraySize)
//.....
}
int main(int argc, char *argv[]) {
char binaryNumber[] = "0000000000000000";
getBitstring(0x1234, binaryNumber, 16); // You must pass the size of the array
printf("%s", binaryNumber);
return 0;
}
其他人建议将binaryNumber数组设置为静态以便快速修复。这可行,但我会避免这种解决方案,因为它是不必要的,并有其他副作用。
答案 2 :(得分:1)
这是人们在学习C
时遇到的问题的一个很好的例子,如果他们使用Java
或其他更现代的语言进行操作,他们可能不会遇到问题不会向用户公开内存布局的细节。
虽然这里的每个人的答案可能在技术上都是正确的,但我会尝试不同的方法,看看我是否可以回答你的问题而不只是给你一行代码来修复它。
首先,您需要了解返回时的情况 函数内部定义的变量,如下所示:
void f(void) {
int x = 0;
/* do some crazy stuff with x */
return x;
}
致电return x;
时会发生什么?我可能省略了一些
这里有详细介绍,但实质上是调用
context将值存储在中名为x
的变量中
那时。 分配用于存储该值的存储空间是
在函数之后不再保证包含该值
结束了。强>
其次,我们需要了解在引用数组时会发生什么 以它的名字命名。假设我们有一个'字符串':
char A[] = "12345";
在C中,这实际上相当于声明一个数组
以\0
结尾的字符:
char A[6] = { '1' , '2' , '3' , '4' , '5' , '\0' };
然后这有点像声明六个char
s A[0]
,A[1]
,......
,A[5]
。变量A
实际上是char *
类型,即它是a
包含存储A[0]
的存储器地址的指针(开头
数组)。
最后,我们需要了解调用printf时会发生什么 打印一个这样的字符串:
printf("%s", A);
你在这里说的是"打印从内存开始的所有字节
地址A
,直到您点击包含\0
"的字节。
所以,让我们把它们放在一起。运行代码时,变量binaryNumber
是一个包含数组第一个字符的内存地址的指针:binaryNumber[0]
,这个地址是什么?由函数返回。但是,您已在getBitString
内声明了数组,因此我们知道在getBitString
结束后,不再保证为数组分配的内存存储相同的值。
当您运行printf("%s", a)
时,您要告诉C到"打印从内存地址a
开始的所有字节,直到找到包含\0
的字节为止 - 但由于该内存地址只能保证在getBitString
内包含有效值,所以你得到的是它在getBitString
之外调用时所包含的垃圾。
那么你可以做些什么来解决这个问题呢?那么你有几种选择,这是一个(非详尽的)清单:
binaryString
之外声明getBitString
,以便当您尝试在main
binaryString
声明为static
,正如其他人所建议的那样,除了实际变量名binaryString
仅在函数内有效外,实际上与上面的内容相同,但是分配用于存储数组的内存在函数外部仍然有效。strdup()
函数复制字符串。请记住,如果您执行此操作,则必须free()
完成strdup()
之后返回的指针,否则您获得的是memory leak。 答案 3 :(得分:0)
您的char binaryNumber[]
是函数getBitstring()
的本地。你不能将局部变量返回给其他函数。
当binaryNumber
完成执行时,getBitstring()
的范围已结束。因此,在main()
中,char *a
未初始化。
解决方法:
static
,这样它就不会超出范围。 [不是一个好方法,但有效] 或
IMO,第二种方法更好。
答案 4 :(得分:0)
使用malloc()
函数以动态方式创建返回类型。为字符串结尾创建16 + 1个块。这不安全但容易理解。
char * binaryNumber = (char*) malloc(17*sizeof(char));//create dynamic char sequence
strcpy(binaryNumber,"0000000000000000");//assign the default value with String copy
最终结果将是;
char* getBitstring(unsigned short int instr) {
//this is what the code below is going to convert into. It is set to default
//as a 16 bit string full of zeros to act as a safety default.
char * binaryNumber = (char*) malloc(17*sizeof(char));//create dynamic char sequence
strcpy(binaryNumber,"0000000000000000");//assign the default value with String copy function
//....
//doing things to binaryNumber
//.....
printf("don't get excited yet %s\n", binaryNumber); //note, this works
return binaryNumber;
}
int main(int argc, char *argv[]) {
char *a = getBitstring(0x1234);
printf("%s", a); //this fails
return 0;
}
当然包括<string.h>
库。
答案 5 :(得分:-1)
您需要static
:
static char binaryNumber[] = "0000000000000000";
如果没有static
关键字,则函数返回后自动变量的值将丢失。可能你知道这一点。