在不知道函数代码中其性质的情况下分配数组或整数

在不知道函数代码中其性质的情况下分配数组或整数

本文介绍了在不知道函数代码中其性质的情况下分配数组或整数(但编译器知道)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找这样的片段.我希望它知道在编译时是否正在处理数组,并避免出现以下错误.

I'm looking for something like this snippet.I expect it to know, at compile time, wether it is dealing with an array or not, and avoid the following errors.

#include <stdio.h>


#define IS_ARRAY(x,type) _Generic((&x),          \
                                 type (*)[]: 1,  \
                                 default:   0)

#define GENERIC_ASSIGN(arg,type) if(IS_ARRAY(arg,type)){arg[0] = 1; arg[1] = 2;}else{arg = 2;}

int main(void)
{

    int foo = 0;
    int bar[10] = {0};

    GENERIC_ASSIGN(bar,int); //-->  error: assignment to expression with array type
    GENERIC_ASSIGN(foo,int); //--> error: subscripted value is neither array nor pointer nor vector  "arg[0] = 1; arg[1] = 2;"

    return 0;
}

当我写GENERIC_ASSIGN(bar,int)时,我确实知道'bar'是一个数组,编译器也是如此.

When I do write GENERIC_ASSIGN(bar,int) i do know that 'bar' is an ARRAY, so does the compiler.

请参阅此主题,以解释问题的一部分

See this topic that explains one part of the problem here

如果在宏中允许使用"#if",该问题将很容易解决

The problem would have been solved easily if '#if' were allowed inside macros

推荐答案

您无法分配给数组,因此必须使用memcpy.例如,让宏创建所有初始化程序的复合文字,然后将其初始化.

You can't assign to arrays, so you will have to use memcpy. For example, have the macro create a compound literal of all initializers and then memcpy that one.

#include <stdio.h>
#include <string.h>

#define IS_ARRAY(x,type) _Generic((&x),                             \
                                 type (*)[]: 1,                     \
                                 default:    0)

#define INIT(arg, type, ...) memcpy(&(arg),                         \
                                    (type[]){__VA_ARGS__},          \
                                    sizeof((type[]){__VA_ARGS__}))

#define GENERIC_ASSIGN(arg,type) IS_ARRAY(arg,type) ?               \
                                 INIT(arg,type,1,2) :               \
                                 INIT(arg,type,2)

int main(void)
{
  int foo = 0;
  int bar[10] = {0};

  GENERIC_ASSIGN(bar,int);
  GENERIC_ASSIGN(foo,int);

  printf("%d %d\n",bar[0], bar[1]);
  printf("%d\n",foo);

  return 0;
}

值得注意的是,使用此方法实际上与使用什么类型(是否使用数组)无关紧要.初始化列表的大小很重要.

Notably, with this method it doesn't really matter what type you use, array or not. The size of the initializer list is all that matters.

gcc -O2将其解析为几个寄存器加载(x86):

gcc -O2 resolves this into a couple of register loads (x86):

    mov     edx, 2
    mov     esi, 1
    xor     eax, eax
    mov     edi, OFFSET FLAT:.LC0
    call    printf
    mov     esi, 2
    mov     edi, OFFSET FLAT:.LC1
    xor     eax, eax
    call    printf

这篇关于在不知道函数代码中其性质的情况下分配数组或整数(但编译器知道)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 20:30