标签: pointers

函数调用中的malloc似乎在返回时被释放?

我想我已经把它归结为最基本的情况:

int main(int argc, char ** argv) {
  int * arr;

  foo(arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int * arr) {
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
}
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

> ./a.out 
 car[3]=-1869558540
 a.out(4100) malloc: *** error for object 0x8fe01037: Non-aligned pointer
                         being freed
 *** set a breakpoint in malloc_error_break to debug
>
Run Code Online (Sandbox Code Playgroud)

如果有人能够阐明我的理解失败的地方,我们将不胜感激.

c malloc pointers

16
推荐指数
2
解决办法
2万
查看次数

函数指针转换为不同的签名

我使用函数指针的结构来实现不同后端的接口.签名非常不同,但返回值几乎都是void,void*或int.


struct my_interface {
    void  (*func_a)(int i);
    void *(*func_b)(const char *bla);
    ...
    int   (*func_z)(char foo);
};
Run Code Online (Sandbox Code Playgroud)

但是后端不需要支持每个接口函数的功能.所以我有两种可能性,第一种选择是在每次调用之前检查指针是否为NULL.我不太喜欢这样,因为可读性和因为我担心性能影响(但我没有测量它).另一种选择是具有虚函数,对于极少数情况,接口函数不存在.

因此,我需要为每个签名都使用一个虚函数,我想知道是否有可能只有一个用于不同的返回值.并将其转换为给定的签名.


#include <stdio.h>

int nothing(void) {return 0;}

typedef int (*cb_t)(int);

int main(void)
{
    cb_t func;
    int i;

    func = (cb_t) nothing;
    i = func(1);

    printf("%d\n", i);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用gcc测试了这段代码,它确实有效.但它是否理智?或者它可以破坏堆栈还是会导致其他问题?

编辑:感谢所有答案,经过一番深入阅读后,我现在学到了很多关于调用约定的知识.并且现在可以更好地理解引擎盖下发生的事情.

c pointers

16
推荐指数
1
解决办法
2万
查看次数

c ++:何时使用指针?

在阅读了一些教程后,我得出的结论是,应该总是使用指针来表示对象.但是我在阅读一些QT教程(http://zetcode.com/gui/qt4/painting/)时也看到了一些例外,其中QPaint对象是在堆栈上创建的.所以现在我很困惑.我什么时候应该使用指针?

c++ qt pointers object

16
推荐指数
4
解决办法
2万
查看次数

使用函数更改指针在C中表示的值

我有一个main具有char 的函数,我试图将指针传递给char函数并将其更改为A,B但它似乎并没有改变它.这里显示的例子只是代码的当前状态我尝试了许多不同的变体,因此可能存在其他错误,只是简单地抓住吸管.

int main()
{
    char result = 'A';
    setChar(&result);
    printf("%C", result);
}

void setChar(char* charToChange)
{
    charToChange = "B";
}
Run Code Online (Sandbox Code Playgroud)

c pointers

16
推荐指数
4
解决办法
6万
查看次数

C - 如果使用realloc是免费必要的吗?

使用realloc时内存是否自动释放?或者是否有必要免费使用realloc?以下哪项是正确的?

//Situation A
ptr1 = realloc(ptr1, 3 * sizeof(int));

//Situation B
ptr1 = realloc(ptr2, 3 * sizeof(int));
free(ptr1);
ptr1 = ptr2;
Run Code Online (Sandbox Code Playgroud)

c pointers

16
推荐指数
3
解决办法
2万
查看次数

可靠地确定数组中的元素数量

每个C程序员都可以使用这个众所周知的宏来确定数组中元素的数量:

#define NUM_ELEMS(a) (sizeof(a)/sizeof 0[a])
Run Code Online (Sandbox Code Playgroud)

这是一个典型的用例:

int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19};
printf("%lu\n", NUM_ELEMS(numbers));          // 8, as expected
Run Code Online (Sandbox Code Playgroud)

但是,没有什么能阻止程序员意外地传递指针而不是数组:

int * pointer = numbers;
printf("%lu\n", NUM_ELEMS(pointer));
Run Code Online (Sandbox Code Playgroud)

在我的系统上,这打印2,因为显然,指针是整数的两倍.我想过如何防止程序员错误地传递指针,我找到了一个解决方案:

#define NUM_ELEMS(a) (assert((void*)&(a) == (void*)(a)), (sizeof(a)/sizeof 0[a]))
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为指向数组的指针与指向其第一个元素的指针具有相同的值.如果改为传递指针,指针将与指向自身的指针进行比较,这几乎总是假的.(唯一的例外是递归的void指针,也就是指向自身的void指针.我可以忍受它.)

意外地传递指针而不是数组现在在运行时触发错误:

Assertion `(void*)&(pointer) == (void*)(pointer)' failed.
Run Code Online (Sandbox Code Playgroud)

太好了!现在我有几个问题:

  1. 我的用法是assert逗号表达式的左操作数有效标准C吗?也就是说,标准是否允许我assert用作表达式?对不起,如果这是一个愚蠢的问题:)

  2. 可以在编译时以某种方式完成检查吗?

  3. 我的C编译器认为这int b[NUM_ELEMS(a)];是一个VLA.有没有办法说服他呢?

  4. 我是第一个想到这个吗?如果是这样,我可以期待在天堂等待多少处女?:)

c arrays assert pointers sizeof

16
推荐指数
2
解决办法
2463
查看次数

在C/C++中,对于数组a,我刚学会了(void*)&a ==(void*)a.这是如何运作的?

所以,我总是知道在C/C++中传递的数组"对象"只包含数组中第一个对象的地址.

指向数组"对象"的指针和它包含的值如何相同?

有人可能会向我指出更多信息,也许是关于汇编中的所有信息.

c c++ arrays pointers

16
推荐指数
2
解决办法
834
查看次数

不支持在c或c ++中添加两个指针.为什么?

为什么在c或c ++中不支持添加两个指针.

当我做,

int *ptr,*ptr1;
int sum = ptr + ptr1;
Run Code Online (Sandbox Code Playgroud)

C或C++会抛出错误.虽然它支持,

int diff = ptr - ptr1;
Run Code Online (Sandbox Code Playgroud)

c c++ pointers

16
推荐指数
1
解决办法
2万
查看次数

*p ++ + = 2定义得很好吗?

我不确定下面的陈述是否由标准C明确定义

*p1++ += 2;
Run Code Online (Sandbox Code Playgroud)

或其他类似声明:

*E1++ <operator>= E2
Run Code Online (Sandbox Code Playgroud)

从标准C关于后增量:

postfix ++运算符的结果是操作数的值.获得结果后,操作数的值递增.(即,将相应类型的值1添加到其中.)有关约束,类型和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论.更新操作数的存储值的副作用应发生在前一个和下一个序列点之间.

关于coumpund-assignment:

E1 op = E2形式的复合赋值与简单赋值表达式E1 = E1 op(E2)的不同之处仅在于左值E1仅被评估一次.

c c++ pointers post-increment compound-assignment

16
推荐指数
1
解决办法
1215
查看次数

使用reinterpret_cast将函数转换为void*,为什么它不合法?

这是我前一个问题切线跟进.匹配bool vs const void*overload的函数的地址.回答者解释说:

[C++ 11]标准没有定义从"指向函数的指针"到"指向"的任何标准转换void.

没有东西可以提供引用,但我能做的最接近的是C++ 11 4.10/2 [conv.ptr]:

类型为"指向cv的 指针"的prvalue T,其中T是对象类型,可以转换为类型为"指向cv的 指针"的prvalue void.一个"指针转换的结果CV T "发送给"指针CV void "指向其中类型的对象的存储位置的起始T驻留,仿佛对象是类型T的最派生对象(1.8)(即,而不是基类子对象).空指针值将转换为目标类型的空指针值.

(强调我的)

假设func是声明void func();,如果你进行C风格的演员表,即(void*) func演员表会成功.static_cast<void*>(func)但是无效,但reinterpret_cast<void*>(func)会成功.但是,您无法将后续转换的指针转换回其原始类型.例如,

精细:

int main() {
  int* i;
  void* s = static_cast<void*>(i);
  i = static_cast<int*>(s);
  s = reinterpret_cast<void*>(i);
  i = reinterpret_cast<int*>(s);
}
Run Code Online (Sandbox Code Playgroud)

不好:

void func() { }

int main() { …
Run Code Online (Sandbox Code Playgroud)

c++ pointers language-lawyer c++11

16
推荐指数
1
解决办法
2893
查看次数