我已经尝试过Google所能做到的一切,但似乎无法理解这一点。我正在尝试返回一个字符并传递给另一个没有运气的函数。我需要做某种内存位置吗?
char hostname[] = "www.XXXXX.com";
uint8 ipaddr[] = {XXX,XXX,XXX,XXX};
char uri[] = "/api/Login/";
char key[] = API_KEY; //3490324032-asdfasd-234234
const int port = 80;
//function to combine uri and key
char combine(char key[], char uri[]) {
int i = 0;
int x = 0;
char long_s[sizeof(uri) + sizeof(key)];
while(uri[i]) {
long_s[i] = uri[i];
++i;
}
while(key[x]) {
long_s[i] = key[x];
++i;
++x;
}
long_s[i] = '\0';
//Serial.print(long_s);
return long_s; //pointer?
}
char lon = combine (key, uri);
char* newURI = &lon;
// A get request
GETrequest getSession(ipaddr, port, hostname, newURI);
答案 0 :(得分:6)
上面的combine
函数声称返回一个char,但实际上return long_s
返回一个char *作为此行怀疑之后的注释。但是,更改函数以返回char *将不会真正让你在任何地方,因为返回堆栈上的字符串(char数组)的地址是一个危险的游戏 - 一旦函数返回,你不能依赖此指针有效。最好有一个第三个参数组合,char result[]
放入结果,或者返回一个malloc的char数组,并确保你在某个时候释放()。
答案 1 :(得分:5)
您的函数返回值为char
- 这意味着它返回单 char
(只能代表一个字符)。字符串由char
s数组表示,通常由指针(char *
)引用。
所以你需要返回char *
- 但这会导致另一个问题。指针必须指向一个比函数调用更长的数组。函数返回后,数组long_s
将被销毁,因此不适用。通常的替代方法是允许调用者提供足够大小的缓冲区(还要注意您的循环可以用strcpy()
和strcat()
函数替换):
char *combine(char result[], size_t result_sz, const char key[], const char uri[])
{
/* Test to see if there is sufficient space */
if (strlen(uri) + strlen(key) + 1 > result_sz)
{
return NULL;
}
strcpy(result, uri);
strcat(result, key);
return result;
}
然后你的来电者必须使用:
char lon[1024];
char *newURI = combine (lon, sizeof lon, key, uri);
if (newURI == NULL)
{
/* Error - URL too long */
}
else
{
GETrequest getSession(ipaddr, port, hostname, newURI);
}
答案 2 :(得分:2)
您正在尝试返回字符数组,而不是字符。将功能定义为
char *combine(char key[], char uri[])
和
char *newURI = combine(key, uri);
编辑:正如其他几条评论中所提到的,函数的主体也是一个问题,因为你返回一个只在函数范围内有意义的字符串。你可以改为:
void combine(char key[], char uri[], char *dest)
{
... and place the result in dest
}
和
char *newURI = (char*)malloc(strlen(key) + strlen(uri) + 1);
combine(key, uri, newURI);
... do whatever
free(combine);
答案 3 :(得分:2)
您没有尝试返回char
,而是尝试返回字符串。
C中的char
是一个字符(或一个字节)。字符串是一系列字符。是的,您需要某种内存位置,可以使用combine
在malloc
函数中分配,也可以作为额外参数由调用者提供。或者更可能是两个额外的参数,一个指针和一个长度,以帮助确保有足够的空间来编写连接的字符串。
C中的每个人都按值[*]传递(并返回)。因此,当您返回char
时,您只需返回char
可能带来的一个可能值。您无法从字符串的开头返回char
,获取指向返回值的指针,并获取字符串的其余部分。通过类比,如果我告诉你我正在考虑字母“a”,那么问我是指“问”中的“a”还是“中庸”中的“a”是没有意义的。我只是说一个字母“a”:没有进一步的背景。如果要指示字母“a”所属的字符串,则需要指针。
此外,sizeof
不会测量字符串的长度。它为您提供类型或对象的大小,这是它的操作数。由于C语法的不幸特性,您的参数key
和uri
属于char*
类型 - 它们是指针,因此它们的大小是指针的大小,而不是它指向的数组的长度(第一个元素)。因此,您的long_s
缓冲区只有8/16字节大(在典型的32/64位架构上),并且会溢出。这会导致未定义的行为,这意味着它可能会崩溃,可能会起作用,或者可能允许攻击者控制您的计算机。
最后,您可以查看标准函数strlen
,strcat
和strncat
,以了解字符串处理在C中的工作原理。以下是一种方法:
char *newURI = malloc(strlen(uri) + strlen(key) + 1);
if (newURL == 0) { /* indicate failure, somehow */ }
strcpy(newURI, uri);
strcat(newURI, key);
GETrequest session = getSession(ipaddr, port, hostname, newURI);
free(newURI); // avoids a memory leak
// do something with the session...
[*]甚至指针也按值传递。
答案 4 :(得分:2)
该函数不返回char,而是返回字符串。 将功能签名更改为
char* combine(char key[], char uri[]) {
(使其返回char *而不是char) 并称之为:
char* newURI = combine(key, uri);
答案 5 :(得分:1)
您说该函数返回char
,但您尝试返回char*
(对数组的引用)。因此,您需要将函数更改为char*
,或者需要返回实际的char
。此外,您返回对不再有效的内存的引用,您需要在堆上使用malloc,或者传入指针以填充函数调用。
编辑:进一步澄清
所有这些都是指向uint8或char的数组的指针。
char hostname[] = "www.XXXXX.com";
uint8 ipaddr[] = {XXX,XXX,XXX,XXX};
char uri[] = "/api/Login/";
char key[] = API_KEY; //3490324032-asdfasd-234234
这是常规数据。
const int port = 80;
//function to combine uri and key
char combine(char key[], char uri[]) {
int i = 0;
int x = 0;
下一行声明一个指向具有8个元素的字符数组的指针。这可能不是你想要的。 sizeof宏正在评估4
,因为这是指针的大小(编译并运行下面的程序)。此外,您需要将其更改为char * long_s = malloc(sizeof(uri) + sizeof(key));
不要忘记稍后将其释放。
char long_s[sizeof(uri) + sizeof(key)];
while(uri[i]) {
long_s[i] = uri[i];
++i;
}
while(key[x]) {
long_s[i] = key[x];
++i;
++x;
}
long_s[i] = '\0';
//Serial.print(long_s);
这将返回指向您刚刚填充的数组的指针,而不是实际的char。
return long_s; //pointer?
}
这些下一行应该是char * newURI = combine(key, uri);
char lon = combine (key, uri);
char* newURI = &lon;
// A get request
GETrequest getSession(ipaddr, port, hostname, newURI);
编辑:试试这个:
#include <stdio.h>
void test(char k[])
{
printf("%d\n", sizeof(k));
}
int main ()
{
char* key[100];
test(key);
printf("%d\n", sizeof(key));
return 0;
}
答案 6 :(得分:1)
你有几个问题:
你正在返回一个指向局部变量的指针。虽然您可能会意外地从该结果中打印出合理的输出结果,但这里存在一个错误,即您正在访问不再有效的数据。一旦函数返回
您正在调整结果缓冲区的大小。 uri
和key
参数确实是指针(请参阅Sizeof array passed as parameter),所以
char long_s[sizeof(uri) + sizeof(key)];
实际上为你提供了一个足以容纳2个指针的字符数组,这个字符不一定足以容纳你的字符串。
您需要决定如何管理组合字符串。有几种选择:
让你的来电者通过一个缓冲区来使用(连同大小,以防止出现超限错误)
让函数分配缓冲区并要求调用者在不再需要时释放它。
使用选项2的示例:
//function to combine uri and key
char* combine(char const* key, char const* uri) {
int len = strlen(key) + strlen(uri) + 1; /* don't the '\0' terminator */
char* pResult = malloc(len);
if (pResult) {
/* we got a buffer */
strcpy( pResult, uri);
strcat( pResult, key);
}
return pResult; /* will return NULL on failure */
/* caller is responsible for calling free() */
}
答案 7 :(得分:0)
您还需要更改combine
以处理char*
。
//function to combine uri and key
void combine(char key[], char uri[], char long_s[]) {
int i = 0;
int x = 0;
while(uri[i]) {
long_s[i] = uri[i];
++i;
}
while(key[x]) {
long_s[i] = key[x];
++i;
++x;
}
long_s[i] = '\0';
//Serial.print(long_s);
}
char newURI = malloc(strlen(uri) + strlen(key) + 1);
combine(key, uri, newURI);
然后,您还必须将lon
参数更改为char*
。
正如评论所指出的那样,你实际上必须做更多的事情,因为long_s是一个局部变量。
您可能需要更改函数以将lon
作为参数并在函数外部初始化它。
同样,这是快速代码,你必须根据自己的需要定制它(并进行垃圾收集)。
答案 8 :(得分:0)
如果您计划返回指向char的指针,则应将您的函数声明为
char *combine (char key[], char uri[])
{
//...etc...
return long_s; //pointer?
}
答案 9 :(得分:0)
第一个问题:您显然是在尝试从combine
函数返回一个字符串,而不是字符。那么你为什么要宣布它为char
?它需要返回字符串的类型,即char*
。
第二个问题:函数无法在C中真正获取数组参数。当您将combine
声明为采用两个数组参数时,它与将其声明为采用两个指针参数完全等效。最好将指针显式声明为参数,因为这样你就有机会避免下一个问题。到目前为止,我们有:
char* combine(char *key, char *uri) {
第三个问题:由于key
和uri
不是数组而是指针,sizeof(key)
和sizeof(uri)
会给出指针的大小,这在这里没用。相反,你需要的是弦的长度。并且您需要添加1以允许组合字符串末尾的“0”。
第四个问题:如果将long_s
分配为本地数组变量,则在函数末尾回收分配给它的内存。所以你不能退货。为了获得在函数结束时仍然存在的一块内存,您需要使用malloc
使用动态内存分配:
char *long_s = malloc(strlen(key) + strlen(uri) + 1);
if (long_s == NULL) { ... /*out of memory*/ }
修复这些问题后,您可以直接执行char *newURI = combine(key, uri);
。完成使用后不要忘记free(newURI)
。
如果这是一个真正的程序而不是学习练习,请学习使用字符串库函数。特别是,您的combine
函数更容易编写为strcpy
,后跟strcat
。