我是StackOverflow的新手。我现在正在学习C指针。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int alloc(int* p){
p = (int*) malloc (sizeof(int));
if(!p){
puts("fail\n");
return 0;
}
*p = 4;
printf("%d\n",*p);
return 1;
}
int main(){
int* pointer;
if(!alloc(pointer)){
return -1;
}else{
printf("%d\n",*pointer);
}
free(pointer);
return 0;
}
我编译:gcc -o main main.c
错误:free():指针无效:0xb77ac000 ***
我的代码出了什么问题?
答案 0 :(得分:4)
C中的参数始终按值传递 。因此,当您调用alloc(pointer)
时,您只需传入pointer
包含的垃圾值。在函数内部,赋值p = (int*)...
仅修改局部变量/参数p
。相反,您需要将pointer
的地址传递到alloc
,如下所示:
int alloc(int **p) {
*p = malloc(sizeof(int)); // side note - notice the lack of a cast
...
**p = 4; // <---- notice the double indirection here
printf("%d\n", **p); // <---- same here
return 1;
}
主要是,你可以这样叫alloc
:
if (!(alloc(&pointer))) {
....
然后,您的代码将起作用。
答案 1 :(得分:1)
C中的所有内容都是按值传递的。这意味着函数始终在他们传递给函数的本地副本上运行。通常,指针是模仿传递引用方案的好方法,因为指针和该指针的副本都包含相同的内存地址。换句话说,指针及其副本都指向同一个空格。
在您的代码中,问题是函数alloc获取了您自己传入的指针的本地副本。因此当您执行p = (int*) malloc (sizeof(int));
时,您需要更改{{1}的值成为新的内存地址,但p
中pointer
的值保持不变。
你可以通过传递一个指向指针,或者返回新值main
来解决这个问题。
答案 2 :(得分:1)
您的代码中存在两个主要问题。
首先,alloc
函数通过malloc
创建一个指针,但从不释放它,也不返回指向调用函数的指针。这可以保证内存永远不会通过free
命令释放指针地址,现在你有内存泄漏。
其次,int* pointer
中的变量main
未按您的想法进行修改。在C中,函数参数是&#34;由值&#34;传递。您有两种方法可以解决此问题:
以下是我的建议的两个实现:
方法1
#include <stdio.h>
#include <stdlib.h>
int alloc(int** p);
int alloc(int** p) {
if (!p) {
printf("Invalid argument\n");
return (-1);
}
if ((*p = (int*)malloc(sizeof(int))) == NULL) {
printf("Memory allocation error\n");
return (-1);
}
**p = 123;
printf("p:%p - *p:%p - **p:%d\n", p, *p, **p);
return 0;
}
int main(){
int* pointer;
if(alloc(&pointer) != 0){
printf("Error calling function\n");
}else{
printf("&pointer:%p- pointer:%p- *pointer:%d\n", &pointer, pointer, *pointer);
}
free(pointer);
return 0;
}
方法1的示例运行
p:0xbfbea07c - *p:0x8656008 - **p:123
&pointer:0xbfbea07cointer - pointer:0x8656008ointer - *pointer:123
方法2
#include <stdio.h>
#include <stdlib.h>
int* alloc(void) {
int* p;
if ((p = (int*)malloc(sizeof(int))) == NULL) {
printf("Memory allocation error\n");
return (NULL);
}
*p = 123;
printf("p:%p - *p:%d\n", p, *p);
return p;
}
int main(){
int* pointer = alloc();
if(pointer == NULL) {
printf("Error calling function\n");
}else{
printf("&pointer:%p- pointer:%p- *pointer:%d\n", &pointer, pointer, *pointer);
}
free(pointer);
pointer = NULL;
return 0;
}
方法2的示例运行
p:0x858e008 - *p:123
&pointer:0xbf9bb1ac- pointer:0x858e008- *pointer:123
答案 3 :(得分:0)
您正在将指针值传递到alloc
函数中。虽然该函数采用指向int的指针,但该指针本身不能被该函数修改。如果您alloc
接受**p
,请设置*p = ...
,然后从主要传递&pointer
,它就可以正常工作。
#include <stdio.h>
#include <stdlib.h>
int alloc(int** p){
*p = (int*) malloc (sizeof(int));
if(!*p){
puts("fail\n");
return 0;
}
**p = 4;
printf("%d\n",**p);
return 1;
}
int main() {
int* pointer;
if(!alloc(&pointer)){
return -1;
} else {
printf("%d\n",*pointer);
}
free(pointer);
return 0;
}
答案 4 :(得分:0)
如果希望函数写入类型为T
的非数组参数,则必须传递指向该参数的指针。
void func( T *ptr )
{
*ptr = new_value;
}
void foo ( void )
{
T var;
func( &var ); // writes new value to var
}
如果T
是指针类型Q *
,则它看起来像
void func( Q **ptr )
{
*ptr = new_pointer_value;
}
void foo ( void )
{
Q *var;
func( &var ); // writes new pointer value to var
}
如果Q
是指针类型R *
,您将获得
void func( R ***ptr )
{
*ptr = new_pointer_to_pointer_value;
}
void foo ( void )
{
R **var;
func( &var ); // writes new pointer to pointer value to var
}
三种情况下的模式相同;您传递变量var
的地址,因此形式参数ptr
必须比实际参数var
多一个间接级别。
一个音节尼特:而不是写作
p = (int *) malloc( sizeof (int) );
使用
p = malloc( sizeof *p );
代替。
在C中(截至1989年标准),您不需要投射malloc
的结果; void
指针可以分配给其他指针类型,反之亦然,而不需要强制转换(在C ++中这是不 true,但是如果你正在编写C ++,你应该使用{{无论如何,1}}运算符而不是new
。此外,根据1989年版本的语言,如果您忘记包含malloc
或在范围内没有stdlib.h
声明,使用演员表会掩盖错误。然而,自1999年版以来,这并不是一个问题,所以现在更多的是可读性而不是其他任何问题。
表达式malloc
的类型为*p
,因此int
的结果与sizeof *p
的结果相同。这样,如果您更改sizeof (int)
的类型,则无需修改p
来电。
要分配值数组,您可以使用类似
的内容malloc
或者,如果您希望最初将所有内容归零,请使用
T *p = malloc( sizeof *p * NUM_ELEMENTS );