Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 返回前后指针值不同_C_Pointers - Fatal编程技术网

C 返回前后指针值不同

C 返回前后指针值不同,c,pointers,C,Pointers,我有一个奇怪的问题,我使用malloc分配内存,并返回这个新分配内存的地址。但是这个地址在返回内外函数前后是不同的 以下代码仅涉及最后3行: char* InfoFile_getValue(char* projectName, char* key) { char* returnValue = NULL; char projectInfoPath[200]; sprintf(projectInfoPath,"projects/%s/info.txt",

我有一个奇怪的问题,我使用malloc分配内存,并返回这个新分配内存的地址。但是这个地址在返回内外函数前后是不同的

以下代码仅涉及最后3行:

char* InfoFile_getValue(char* projectName, char* key)
{
    char* returnValue = NULL;

    char projectInfoPath[200];
    sprintf(projectInfoPath,"projects/%s/info.txt",projectName);

    FILE* fp = fopen(projectInfoPath,"r");

    if (fp != NULL) {
        char* ptr;
        size_t len = 0;
        char* lineFromFile = NULL;
        while(getline(&lineFromFile, &len, fp)!=-1)
        {
            if (strstr(lineFromFile,key))
            {
                ptr = lineFromFile + strlen(key);
                ptr = ptr + strspn(ptr, ": ");
                returnValue = malloc(strlen(ptr)+1);
                strcpy(returnValue,ptr);
                break;
            } 
        }
        free(lineFromFile);
        fclose(fp);
    }
    
    printf("Inside size: %d\n",sizeof(returnValue));
    printf("String address inside function %p\n", returnValue);
    return returnValue;
}
然后我使用以下方法调用此函数:

char* baseString = InfoFile_getValue(projectName, "base");
printf("Outside size: %d\n",sizeof(baseString));
printf("String address outside function: %p\n",baseString);
printf("%s\n", baseString);
我使用CC和下面的标志来实现这一点:

pkg config-cflags gtk+-3.0-Wno不兼容的指针类型 -Wno int转换-Wno丢弃的限定符包配置-libs gtk+-3.0-lpthread-lm

它给出了以下结果:

Inside size: 8
String address inside function 0x5567d9ff4540
Outside size: 8
String address outside function: 0xffffffffd9ff4540
Naruszenie ochrony pamięci (zrzut pamięci)

看起来它将这个地址削减为4个字节,并以0xff作为前缀,但我不知道为什么,我从未遇到过这样的问题。任何建议都会有帮助。

您似乎得到了地址低32位的符号扩展。这只是一个猜测,但我认为编译器将InfoFile_getValue视为一个返回int的函数,而指针是64位长的

规则是函数在使用前必须声明。如果不是,C假定它被声明为int func,这是一个接受任何参数并返回int的函数。您应该确保:

char* InfoFile_getValue(char* projectName, char* key);

函数之前可能包含char*baseString=InfoFile\u getValueprojectName,base

您似乎得到了地址低32位的符号扩展名。这只是一个猜测,但我认为编译器将InfoFile_getValue视为一个返回int的函数,而指针是64位长的

规则是函数在使用前必须声明。如果不是,C假定它被声明为int func,这是一个接受任何参数并返回int的函数。您应该确保:

char* InfoFile_getValue(char* projectName, char* key);

函数之前可能包含char*baseString=InfoFile\u getValueprojectName,base

这看起来像符号扩展,所以闻起来很像C90隐式int bug。也就是说,编译器认为该函数返回值为0xd9ff4540的int,在32位系统上,该值很可能是负2的补码。然后,由于%p的原因,它被转换为64位,您得到了符号扩展

解决这个问题的最简单方法就是停止使用C90,它已经有30年的历史了,已经坏了,而且很危险。仅仅去掉隐式int就足以将代码移植到标准C


如果必须使用它,请确保函数声明和定义相同,并且调用方可以看到函数声明。然后最大化编译器警告并注意它们。

这看起来像符号扩展,所以闻起来很像C90隐式int bug。也就是说,编译器认为该函数返回值为0xd9ff4540的int,在32位系统上,该值很可能是负2的补码。然后,由于%p的原因,它被转换为64位,您得到了符号扩展

解决这个问题的最简单方法就是停止使用C90,它已经有30年的历史了,已经坏了,而且很危险。仅仅去掉隐式int就足以将代码移植到标准C


如果必须使用它,请确保函数声明和定义相同,并且调用方可以看到函数声明。然后最大化编译器警告并注意它们。

由于调用者准备不足,您会遇到值截断和符号扩展。也就是说,由于缺乏适当的原型,调用方不知道实际的函数返回类型。这可能会让人恼火,除非你密切关注C语言,尤其是在处理一个代码库时,这个代码库在int和void*大小相同的平台上似乎工作得很好

下面是重新编程的最简单案例,并记录了必须进行的操作

main.c

在两个平台上运行的结果显然,此处的值在您的系统上可能会有所不同

x86

x64

有了这些,你就有希望看到两件事是多么重要:

始终确保在源代码中调用的函数在使用前已正确原型化。 始终以警告作为错误进行编译,以捕获此类问题。
也许你要记住的最大一件事是,如果不同时执行上述两项,代码在x86上仍然可以正常运行,在x64上仍然可以编译。前者会让你产生一种虚假的成就感,而后者只是进一步证实了这一点,使得寻找像这样的问题特别令人恼火。让编译器帮助您。确保1和2在您的例程中。

由于调用者准备不足,您正在经历值截断和符号扩展。也就是说,由于缺乏适当的原型,调用方不知道实际的函数返回类型。这可能会让人恼火,除非你密切关注C语言,尤其是在处理一个代码库时,这个代码库在int和void*大小相同的平台上似乎工作得很好

最简单的例子就是重新编程 下面是,并记录了必须进行的操作

main.c

在两个平台上运行的结果显然,此处的值在您的系统上可能会有所不同

x86

x64

有了这些,你就有希望看到两件事是多么重要:

始终确保在源代码中调用的函数在使用前已正确原型化。 始终以警告作为错误进行编译,以捕获此类问题。
也许你要记住的最大一件事是,如果不同时执行上述两项,代码在x86上仍然可以正常运行,在x64上仍然可以编译。前者会让你产生一种虚假的成就感,而后者只是进一步证实了这一点,使得寻找像这样的问题特别令人恼火。让编译器帮助您。确保1和2在例程中。

sizeofreturnValue=sizeof指针,而不是指针指向的对象。只是说说而已。不知道这是否是目的,但不管怎样,这就是你得到的。是的,我想检查指针的大小,以确保它在这里和那里是8字节。只是为了确定一下。通常情况下,只有当打电话的人没有做好打电话的准备时,你才会看到这样的情况。也就是说,它没有合适的原型,并假设int返回,这是由sqelchers通过硬扔掉它来修复的。在这种情况下,如果int和char*是x64平台典型的不同大小,则实际上只获得64位结果中的32位;其余部分是从幻影int的msb进行的。但是我在这里没有看到这样的恶作剧。有了原型,这段代码看起来是正确的。如果你所说的是真的,那么应该重新编写InfoFile_getValue。真的吗?谢谢大家,你们真快!是的,我错过了正确的功能原型。InfoFile_getValue在单独的文件中,我忘了包含InfoFile.h。最后,我需要学习阅读警告,或者将隐式声明警告视为错误。再次感谢,你太棒了!嗯,你应该告诉你,这个不见了。如果没有,您需要打开警告级别:-Wall-Wextra。当然,您需要注意指针的warnings.sizeofreturnValue=sizeof,而不是指针指向的内容。只是说说而已。不知道这是否是目的,但不管怎样,这就是你得到的。是的,我想检查指针的大小,确保它在这里和那里是8字节。只是为了确定一下。通常情况下,只有当打电话的人没有做好打电话的准备时,你才会看到这样的情况。也就是说,它没有合适的原型,并假设int返回,这是由sqelchers通过硬扔掉它来修复的。在这种情况下,如果int和char*是x64平台典型的不同大小,则实际上只获得64位结果中的32位;其余部分是从幻影int的msb进行的。但是我在这里没有看到这样的恶作剧。有了原型,这段代码看起来是正确的。如果你所说的是真的,那么应该重新编写InfoFile_getValue。真的吗?谢谢大家,你们真快!是的,我错过了正确的功能原型。InfoFile_getValue在单独的文件中,我忘了包含InfoFile.h。最后,我需要学习阅读警告,或者将隐式声明警告视为错误。再次感谢,你太棒了!嗯,你应该告诉你,这个不见了。如果没有,您需要打开警告级别:-Wall-Wextra。当然,你需要注意这些警告。谢谢,伙计,事情就是这样发生的。我从x86迁移到x64,之后我面临这个问题。现在我学到了一些新的和添加的东西-Werror隐式函数声明,以防止将来出现类似的错误。谢谢,伙计,这正是发生的事情。我从x86迁移到x64,之后我面临这个问题。现在我学到了一些新的和添加的东西——Werror隐式函数声明,以防止将来出现类似的错误。
#include <stdio.h>

void *foo()
{
    static int x;
    void *p = &x;
    printf("foo: p = %p\n", p);
    return p;
}
1>main.c(13): warning C4013: 'foo' undefined; assuming extern returning int
1>main.c(13): warning C4047: 'initializing': 'void *' differs in levels of indirection from 'int'    
foo: p = 00A38138
main: p = 00A38138
foo: p = 00007FF7E7B0C160
main: p = FFFFFFFFE7B0C160