如何在符合C标准的情况下一般地转换指针的地址

Dro*_* K. 11 c pointers strict-aliasing

通常使用隐式函数返回void*转换为分配指定指针,就像malloc()一样:

void *malloc(size_t size);
int *pi = malloc(sizeof *pi);
Run Code Online (Sandbox Code Playgroud)

我希望在传递目标指针的地址时执行相同的赋值,而不从函数内部(不在其体内,也不在参数中)显式地转换其类型.

以下代码似乎实现了这一点.

  1. 我想知道代码是否完全符合(任何)C标准.
  2. 如果它不符合,我想知道是否有可能在符合(任何)C标准的情况下达到我的要求.

.

#include <stdio.h>
#include <stdlib.h>

int allocate_memory(void *p, size_t s) {
    void *pv;
    if ( ( pv = malloc(s) ) == NULL ) {
        fprintf(stderr, "Error: malloc();");
        return -1;
    }
    printf("pv: %p;\n", pv);
    *((void **) p) = pv;
    return 0;
}

int main(void) {
    int *pi = NULL;
    allocate_memory(&pi, sizeof *pi);
    printf("pi: %p;\n", (void *) pi);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果:

pv: 0x800103a8;
pi: 0x800103a8;
Run Code Online (Sandbox Code Playgroud)

thi*_*his 6

类型int**void**不兼容您正在将其实际类型为int**的p转换为void**,然后在此处取消引用它:

*((void **) p) = pv;
Run Code Online (Sandbox Code Playgroud)

这将破坏别名规则.

您可以传递一个void指针然后正确地转换它:

void *pi = NULL;
int* ipi = NULL ;
allocate_memory(&pi, sizeof *ipi );
ipi = pi ;
Run Code Online (Sandbox Code Playgroud)

或返回一个void指针.

int *pi = allocate_memory(sizeof *pi);
Run Code Online (Sandbox Code Playgroud)


可以选择使用联合:

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

union Pass
{
    void** p ;
    int** pi ;
} ;

int allocate_memory(union Pass u , size_t s) {
    void *pv;
    if ( ( pv = malloc(s) ) == NULL ) {
        fprintf(stderr, "Error: malloc();");
        return -1;
    }
    printf("pv: %p;\n", pv);
    *(u.p) = pv;

    return 0;
}

int main() 
{
    int* pi = NULL ;
    printf("%p\n" , pi ) ;
    allocate_memory( ( union Pass ){ .pi = &pi } , sizeof( *pi ) ) ;
    printf("%p\n" , pi ) ;

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

据我了解,这个例子符合标准.

使用静态断言来保证大小和对齐方式相同.

_Static_assert( sizeof( int** ) == sizeof( void** ) , "warning" ) ;
_Static_assert( _Alignof( int** ) == _Alignof( void** ) , "warning" ) ;
Run Code Online (Sandbox Code Playgroud)


Fre*_*Foo 5

不,这不合规.你正在传递int**as void*(ok),但是然后你将其void*转换void**为不保证具有相同大小和布局的a.在将其转换回原来的指针类型后,您只能取消引用void*(除了从malloc/ 获得的一个calloc),并且此规则不会递归应用(因此a void**不会自动转换,如a void*).

我也没有办法满足你的所有要求.如果必须通过指针传递指针,那么void*在这种情况下,您需要实际传递a的地址并在调用者中执行所有必要的转换main.那就是

int *pi;
void *pv;
allocate_memory(&pv, sizeof(int));
pi = pv;
Run Code Online (Sandbox Code Playgroud)

......打败你的计划.